Hi i am at about page fifty in the pickaxe book, and i have a
question. I see a lot of examples of a block that starts with |
SomeVar| and I dont really understand how you know when you can do
this or what the value will be that is passed to the variable. What
is the name of this construct or the var that goes in pipes? Thank
you
On Oct 10, 2007, at 9:35 PM, A Love of Surf wrote:
Hi i am at about page fifty in the pickaxe book, and i have a
question. I see a lot of examples of a block that starts with |
SomeVar| and I dont really understand how you know when you can do
this or what the value will be that is passed to the variable. What
is the name of this construct or the var that goes in pipes? Thank
you
In the PDF version of Pickaxe, this is explained beginning on p. 47
(p.50 in the printed text). Read the explanation that goes along with
the fib_up_to example. More info can be found in Chapter 22 under the
heading: Blocks, Closures, and Proc Objects.
A quick and dirty explanation is the the vertical bars at the
beginning of a block delimit the block’s formal arguments. When the
block is evaluated by a yield expression, the actually arguments
passed to the yield will be assigned to the formal arguments in a
manner similar to a function call. Just as you can’t call a function
without knowing what arguments it takes, you must know what arguments
a method accepting a block passes to the block in order to write a
block for that method. It is a matter of documentation.
Regards, Morton
A Love of Surf wrote:
Hi i am at about page fifty in the pickaxe book, and i have a
question. I see a lot of examples of a block that starts with
|SomeVar|
and I dont really understand how you know when you can do
this
Whenever a method specified to the left of the block has a yield
statement in its definition, the method is going to pass a value to the
block. For example:
def my_method
yield 10
end
my_method {|num| puts num * 2} #20
How do you know if one of ruby’s methods has a yield statement in its
definition? You could look at the source code, but for now just
remember that when the book says that a method is an iterator, then the
method is going to send one or more values to a block. Or, if the book
introduces a method and also uses a block after the method call, then
you know the definition of the method has a yield statement in it, which
just means it is going to send one or more values to the block. What
you should be trying to figure out is:
-
what values the method call sends to the block
-
what the return value of method call is
The most common iterator is ‘each’. When called on an array, each sends
each element of the array to the block one at a time.
You should make frequent use of the reference section in the back of the
book to look up methods and read about what values they send to a block,
and what the return value of the method call is.
or what the value will be that is passed to the variable.
It depends on how the method you call is defined:
def my_method
yield 20
yield 30
end
my_method {|num| puts num * 2} #40 60
What
is the name of this construct or the var that goes in pipes?
The construct is exactly like a method definition, and it is called a
“block”. The thing in the pipes is the same thing as a parameter
variable in a method definition.
You are calling a method:
my_method
with a block specified on the right:
{|num| puts num * 2}
The block is just like a method, but it doesn’t have a name.
Backing up a little, you can define methods that call each other like
this:
def my_method
calculate(10)
end
def calculate(num)
puts num * 2
end
my_method #20
The same thing is happening with a method call that is followed by a
block: you are calling a method that sends values to another method(the
block).
Another way to explain, complementing our friend Morton, is that when
you
use a block, you are kind of inserting code inside another function. Let
me
give you an example to help you understand.
Let’s take the “each” method of an array. You use this method when you
want
to do something with every item inside the array.
You could call something like:
my_string = “”
my_array.each do |foo|
puts foo
my_string += " AND #{foo}"
end
Now, why did we place that |foo| on the block? Imagine that the “each”
method on the array is implemented like this:
def each
i = 0
while i <= self.size
current_item = self[i]
yield(current_item)
end
self
end
Now notice two things: First, the “each” method itself has no
parameters,
though it could have. They would have nothing to do with the pipes,
though.
Second, look at the yield line. what yield do is to call the block that
you
gave to this function. Since the yield is inside the while statement, it
will run as many times as there are items on your array. And, as i said
it
is just like putting your piece of code inside the “each” (or any other)
method. It would be like you’ve written
def my_each
my_string = “”
i = 0
while i <= self.size
current_item = self[i]
# ----
puts current_item
my_string += " AND #{foo}"
# -----
end
self
end
Now, the actual values that the block will take will clearly depend on
the
function that you are using. SInce yield can pass as many parameter as
it
wants (you could have something like yield a, b, c, d, e, …) you
should
see the documentation of the function to know which values are passed to
the
block.
It’s obviously not a technical explanation, and some things are
intentionally wrong (the each method for array is implemented in C, for
instance), but maybe it helps you understand.
Hope this helps
On Oct 10, 7:46 pm, 7stud – [email protected] wrote:
block. For example:
method is going to send one or more values to a block. Or, if the book
each element of the array to the block one at a time.
yield 20
variable in a method definition.my_method #20
The same thing is happening with a method call that is followed by a
block: you are calling a method that sends values to another method(the
block).–
Posted viahttp://www.ruby-forum.com/.
Thank you so much for your help, I was having a tough time with that
but you cleared it up for me.
My example was wrong. Where it reads
def my_each
my_string = “”
i = 0
while i <= self.size
current_item = self[i]
# ----
puts current_item
my_string += " AND #{foo}"
# -----
end
self
end
it should read
def my_each
my_string = “”
i = 0
while i <= self.size
current_item = self[i]
# ----
puts current_item
my_string += " AND #{current_item}"
# -----
end
self
end