How we iterate
@h6165
Abhishek Yadav
ரூபீ ப்ரோக்ராமர்
Co-organizer: Chennai.rb
Iteration/Looping in Ruby
-
loop
-
while
-
for..in
-
Iterators
Iterators are more popular than the others
Iteration/Looping in Ruby
An iterator operates on some kind of list,
It expects a block as argument
[1,2,3].each do |x|
puts (x**2)
end
each | is the iterator |
[1,2,3] | is the list |
do..end | is the block |
each
Iteration/Looping in Ruby
object.method(argument)
Follows this familiar method invocation pattern in object oriented programming
[1,2,3] is an object of the Array class.
The Array class has defined the method each.
The each method takes one argument.
each anatomy
Iteration/Looping in Ruby
- The block-argument here is a little different.
- The argument we are passing is a block
- A block is a lump of code. It can be passed around before being executed. Blocks are closures
- It is similar to Javascript functions
blocks
Iteration/Looping in Ruby
So,
We are creating a lump of code and passing it to the each method as an argument:
{ |x| puts(x**2) }
The each method can execute it.
blocks
Iteration/Looping in Ruby
To execute a block, the yield keyword is used.
yield 12 will invoke the given block with 12 as argument
Its very similar to given_block.call(12)
Array's each method is implemented in similar way
block needs yield
def foo
yield 12
end
foo {|x| x**2 } #=> 144
def bar(&given_block) # Very similar
given_block.call(12)
end
bar {|x| x**2 } #=> 144
Iteration/Looping in Ruby
Array#each and yield
class Array
# Approximate implementation of each
def each
list = self
i = 0
loop do
break if i >= list.length
yield list[i] # <= given_block.call(list[i])
i += 1
end
end
end
Iteration/Looping in Ruby
- While defining the block, we specify the argument within pipes
- Block code can be enclosed within braces or do..end keywords
And x is the argument in both
do-end
# So,
{ |x| puts x**2 }
# is the same as
do|x|
puts(x**2)
end
Iteration/Looping in Ruby
- Block is not an object
- Block can be represented as a Proc object/lambda
block as object
a = { |x| puts x**2 } # SyntaxError
a = Proc.new do |x| # works
puts x**2
end
a = lambda{ |x| puts x**2 } # works
a = ->(x){ puts x**2 } # works
Iteration/Looping in Ruby
- Iterators are idiomatic Ruby
- Iterators read better (subjective)
- Iterators can be monkey patched
- Lazy enumeration is possible and simple
Are iterators better ?
Iteration/Looping in Ruby
monkey patching
class Array
def myeach
return unless block_given?
arr = self
len = arr.length
i = 0
loop do
yield arr[i]
break if arr[i] == nil # Loop stops at nil
i += 1
i = 0 if i >= len
end
end
alias_method :old_each, :each
alias_method :each, :myeach
end
Iteration/Looping in Ruby
lazy enumeration
range = [1..Float::INFINITY]
range.lazy.map {|x| x**2 }.first(5) # [1, 4, 9, 16, 25]
@h6165
Abhishek Yadav
ரூபீ ப்ரோக்ராமர்
Co-organizer: Chennai.rb
how we iterate
By Abhishek Yadav
how we iterate
- 1,204