What exactly do the blocks represent?
In other languages the syntax may look something like this:
ark = ["Cat", "dog", "pig", "goat"];
ark.each(function (animal) { puts animal; });
Does that clear it up? It's the syntax for an anonymous function. If you're not familiar with that concept, how about this?
function putAnimal(animal) {
puts animal;
}
ark = ["Cat", "dog", "pig", "goat"];
ark.each(putAnimal);
|animal|
is the argument list for the anonymous function. Very roughly speaking, Ruby's syntax for the common function (arg) { ... }
is do |arg| ... end
.
Understanding some Ruby code
It's a block. In Ruby exists blocks, procs and lambdas. Check this link to understand it better.
http://www.reactive.io/tips/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/
Ruby documentation for a complete beginner
We can find documentation of Ruby's Array class here: http://www.ruby-doc.org/core-2.1.5/Array.html including it's each
instance method: http://www.ruby-doc.org/core-2.1.5/Array.html#method-i-each
There we see:
each { |item| block } → ary
Calls the given block once for each element in self, passing that element as a parameter.
Which is a good hint that we want to learn more about "blocks" (the chunk of code wrapped in those {}
s) so we could look at a related question like Best explanation of Ruby blocks? or look for related documentation like http://docs.ruby-doc.com/docs/ProgrammingRuby/html/tut_containers.html
do..end vs curly braces for blocks in Ruby
The general convention is to use do..end for multi-line blocks and curly braces for single line blocks, but there is also a difference between the two that can be illustrated with this example:
puts [1,2,3].map{ |k| k+1 }
2
3
4
=> nil
puts [1,2,3].map do |k| k+1; end
#<Enumerator:0x0000010a06d140>
=> nil
This means that {} has a higher precedence than do..end, so keep that in mind when deciding what you want to use.
One more example to keep in mind while you develop your preferences.
The following code:
task :rake => pre_rake_task do
something
end
really means:
task(:rake => pre_rake_task){ something }
And this code:
task :rake => pre_rake_task {
something
}
really means:
task :rake => (pre_rake_task { something })
So to get the actual definition that you want, with curly braces, you must do:
task(:rake => pre_rake_task) {
something
}
Maybe using braces for parameters is something you want to do anyways, but if you don't it's probably best to use do..end in these cases to avoid this confusion.
Ruby yield example explanation?
Let's build this up step-by-step. We will simplify things a bit by taking it out of the class context.
For this example it is intuitive to think of an iterator as being a more-powerful replacement for a traditional for-loop.
So first here's a for-loop version:
seq1 = (0..2)
seq2 = (0..2)
for x in seq1
for y in seq2
p [x,y] # shorthand for puts [x, y].inspect
end
end
Now let's replace that with more Ruby-idiomatic iterator style, explicitly supplying blocks to be executed (i.e., the do...end
blocks):
seq1.each do |x|
seq2.each do |y|
p [x,y]
end
end
So far, so good, you've printed out your cartesian product. Now your assignment asks you to use yield
as well. The point of yield
is to "yield execution", i.e., pass control to another block of code temporarily (optionally passing one or more arguments).
So, although it's not really necessary for this toy example, instead of directly printing the value like above, you can yield
the value, and let the caller supply a block that accepts that value and prints it instead.
That could look like this:
def prod(seq1, seq2)
seq1.each do |x|
seq2.each do |y|
yield [x,y]
end
end
end
Callable like this:
prod (1..2), (1..2) do |prod| p prod end
The yield
supplies the product for each run of the inner loop, and the yielded value is printed by the block supplied by the caller.
Related Topics
Is Ruby Pass by Reference or by Value
Why Is Division in Ruby Returning an Integer Instead of Decimal Value
How to Test If a String Is Basically an Integer in Quotes Using Ruby
Sudo Gem Install' or 'Gem Install' and Gem Locations
How to Call Shell Commands from Ruby
Why Use Ruby'S Attr_Accessor, Attr_Reader and Attr_Writer
How to Sum Array of Numbers in Ruby
Rails 4: List of Available Datatypes
How to Fix "Your Ruby Version Is 1.9.3, But Your Gemfile Specified 2.0.0"
Tzinfo::Datasourcenotfound Error Starting Rails V4.1.0 Server on Windows
How to Split (Chunk) a Ruby Array into Parts of X Elements
Avoiding Applescript Through Ruby: Rb-Appscript or Rubyosa
Best Explanation of Ruby Blocks
Best Way to Convert Strings to Symbols in Hash
Access Variables Programmatically by Name in Ruby