Inside Enumerable

Preview:

DESCRIPTION

A look at the Enumerable module in Ruby. What it is, how it works and what you can do with it.

Citation preview

Inside Enumerable

Inside Enumerable

Mike BowlerGargoyle Software Inc.

Mike BowlerGargoyle Software Inc.

AgendaAgenda

1.What is Enumerable?

2.What can you do with it?

3.How does it do that?

What is it?What is it?

It’s a group of related methods all having to do with collections

It’s the interesting part behind Array, Set, Hash and Range

It’s a Module (often called a mixin)

hash = {:a => 1, :b => 2}hash.collect do |key, value| value * 4end

[4,8]

[4,8,12]

[4,8,12]

array = [1,2,3]array.collect do |value| value * 4end

range = 1..3range.collect do |value| value * 4end

hash = {:a => 1, :b => 2}hash.collect do |key, value| value * 4end

array = [1,2,3]array.collect do |value| value * 4end

range = 1..3range.collect do |value| value * 4end

module Enumerable def collect ... endend

multiple inheritancemultiple inheritance

mixinsmixins

MixinsMixins

Cannot be instantiatedCan be mixed in

Mixins usually don’t stand alone

Mixins usually don’t stand alone

Typically...

mixins aren’t completely self-contained

they rely on certain methods being present on the class they are mixed into

This isn’t mandatory but is very common

Let’s look at an example...

Enumerable requires each()

Enumerable requires each()

[1,2,3].collect {|i| i*2} [2,4,6]

class Foo include Enumerable

def each yield 1 yield 2 yield 3 endend

Foo.new.collect do |num| num * 2end

Enumerable.collectEnumerable.collectmodule Enumerable def collect array = [] each do |a| array << yield(a) end array endend

module Enumerable def collect array = [] each do |a| array << yield(a) end array endend

class Foo include Enumerable

def each yield 1 yield 2 yield 3 endend

Foo.new.collect do |num| num * 2end

Enumerable.collectEnumerable.collect

module Enumerable def collect array = [] each do |a| array << yield(a) end array endend

class Foo include Enumerable

def each yield 1 yield 2 yield 3 endend

Foo.new.collect do |num| num * 2end

Enumerable.collectEnumerable.collect

class Foo include Enumerable

def each yield 1 yield 2 yield 3 endend

Foo.new.collect do |num| num * 2end

module Enumerable def collect array = [] each do |a| array << yield(a) end array endend

Enumerable.collectEnumerable.collect

module Enumerable def collect array = [] each do |a| array << yield(a) end array endend

class Foo include Enumerable

def each yield 1 yield 2 yield 3 endend

Foo.new.collect do |num| num * 2end

Enumerable.collectEnumerable.collect

class Foo include Enumerable

def each yield 1 yield 2 yield 3 endend

Foo.new.collect do |num| num * 2end

module Enumerable def collect array = [] each do |a| array << yield(a) end array endend

Enumerable.collectEnumerable.collect

Result[2,4,6]

Comparisonoperator

Required methodsRequired methods

collect() would not have worked if Foo hadn’t declared each()

All methods in Enumerable require each()

A couple also require <=>

min(), max(), sort()

Enumerable methods

Enumerable methods

all?, any?, collect, detect, each_cons, each_slice, each_with_index, entries,

enum_cons, enum_slice, enum_with_index, find, find_all, grep, include?, inject, map, max, member?, min, partition, reject,

select, sort, sort_by, to_a, to_set, zip

any?any?

[1,2,3,4].any? {|a| a > 2}

Returns true if this block...

...returns true for any of these

values

all?all?

[1,2,3,4].all? {|a| a > 2}

Returns true if this block...

...returns true for ALL of these

values

collect, mapcollect, map

“Returns a new array with the results of running block once for every element in enum”

map is an alias for collect

[1,2,3].collect {|i| i*2} [2,4,6]

find, detectfind, detect

find(ifnone = nil) {| obj | block } => obj or nil

Passes each entry in enum to block. Returns the first for which block is not false. If no object matches, calls ifnone and returns its result when it is specified, or returns nil

detect is an alias for find

find_all, selectfind_all, select

find_all {| obj | block } => array

Returns an array containing all elements of enum for which block is not false

select is an alias for find_all

Case equality

grepgrepgrep(pattern) => array

Returns an array of every element in enum for which Pattern === element. If the optional block is supplied, each matching element is passed to it, and the block‘s result is stored in the output array

Case equalityCase equalityFor most objects, === is the same as ==

Caseequality

Regularequality

Case equalityCase equality

case myvar when 1..50 # do something when 51 # do something when /^\d+$/ # do somethingend

Within the range

This exact number

Matches this regular expression

Different kind of equality as aconvenience in case statements

Case equality in grepCase equality in grep

[1,2,3].grep(1..50)

[1,2,3].grep(51)

[1,2,3].grep(/^\d+$/)

Within the range

This exact number

Matches this regular expression

Wrap upWrap up

Enumerable is already mixed into all the core collections

You can mix it into any of your classes so long as you implement each()

It provides all kinds of useful methods to walk across the collections and get information out of them

Shameless PlugShameless Plug

I can help you with your Ruby and/or Rails projects. Ask me how.

Mike Bowlermbowler@GargoyleSoftware.comwww.GargoyleSoftware.com (company)www.SphericalImprovement.com (blog)

Recommended