From: Robert Klemme Date: 2013-04-13T06:52:03+09:00 Subject: Re: Trying to understand blocks --000e0cd6b43cc1a9fc04da30e907 Content-Type: text/plain; charset=ISO-8859-1 On Fri, Apr 12, 2013 at 10:12 PM, Vincent Stowbunenko wrote: > I am confused about what is going on with this code: > IMO the most important aspect to remember about this is that a block is an anonymous function. > def foo > yield("Jim") > end > > def bar > baz = lambda { |n| n.upcase } > foo(&baz) > end > > bar # => "JIM" > > > From what I understand where this is going: > > 1. The method bar is being called. > Check. > 2. Inside the bar method, the lambda function is being assigned to the > baz variable, to upcase whatever is assigned to the variable n inside > the lambda function. > Check. > 3. I don't understand the use of ampersand operator associated with the > variable baz. Whatever that is, it is an argument for the foo method. > The ampersand is used in two ways: one way presented by you here at the calling site to pass a block (or something which implements #to_proc) to a method. The other one is inside methods to access the block as an object: irb(main):008:0> def f(&b) p b; yield 1; b.call(2); b[3] end => nil irb(main):009:0> f {|x| printf "(%p)\n", x} # (1) (2) (3) => nil When accessing the block as object it can be stored somewhere (e.g. in a member variable) for later use. That's the main advantage. irb(main):010:0> o = Object.new => # irb(main):011:0> def o.to_proc; lambda {|y| p y} end => nil irb(main):012:0> f(&o) # 1 2 3 => 3 #to_proc is a special mechanism which allows to pass arbitrary things as a block, for example: irb(main):013:0> (1..4).map(&:to_s) => ["1", "2", "3", "4"] Here method #to_proc of the symbol "to_s" invoked. It returns a block with a single argument which invokes the method represented by the given name on the object: irb(main):014:0> b = :to_s.to_proc => # irb(main):015:0> b.call 123 => "123" 4. Inside the foo method, it uses a yield function with an argument > "Jim". Somehow, the string "Jim" made it way to assign to the variable > n, upcasing it. > Keyword "yield" is used to invoke a block passed to the method; since the method does not have a name there must be a standard way to invoke it. The other ways I have also shown in line 1 above. A few other aspects http://blog.rubybestpractices.com/posts/rklemme/001-Using_blocks_for_Robustness.html http://blog.rubybestpractices.com/posts/rklemme/002_Writing_Block_Methods.html Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/ --000e0cd6b43cc1a9fc04da30e907 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable



On Fri, Apr 12, 2013 at 10:12 PM, Vincent Stowbunenko <lists@ru= by-forum.com> wrote:
I am confused about what is going on with this code:

IMO the most important aspect to remember about t= his is that a block is an anonymous function.
=A0
def foo
=A0 =A0 yield("Jim")
end

def bar
=A0 =A0baz =3D lambda { |n| n.upcase }
=A0 =A0foo(&baz)
end

bar # =3D> "JIM"


From what I understand where this is going:

1. The method bar is being called.

Check.
=A0
2. Inside the bar method, the lambda function is being assigned to the
baz variable, to upcase whatever is assigned to the variable n inside
the lambda function.

Check.
=
=A0
3. I don't understand the use of ampersand operator associated with the=
variable baz. =A0Whatever that is, it is an argument for the foo method.

The ampersand is used in two ways: = one way presented by you=A0here at the calling site=A0to pass a block (or s= omething which implements #to_proc) to a method. =A0The other one is inside= methods to access the block as an object:

irb(main):008:0> def f(&b)= p b; yield 1; b.call(2); b[3] end
=3D> nil
irb(main= ):009:0> f {|x| printf "(%p)\n", x}
#<Proc:0x8b19= 358@(irb):9>
(1)
(2)
(3)
=3D> nil

When accessing the block as object it can be stored somewher= e (e.g. in a member variable) for later use. =A0That's the main advanta= ge.

irb(main):010:0> o =3D Object.new
=3D> = #<Object:0x8b265e4>
irb(main):011:0> def o.to_proc; lamb= da {|y| p y} end
=3D> nil
irb(main):012:0> f(&= ;o)
#<Proc:0x8b3e810@(irb):11 (lambda)>
1
2
3
=3D> 3

#to_proc i= s a special mechanism which allows to pass arbitrary things as a block, for= example:

irb(main):013:0> (1..4).map(&:t= o_s)
=3D> ["1", "2", "3", "= 4"]

Here method #to_proc of the symbol = "to_s" invoked. =A0It returns a block with a single argument whic= h invokes the method represented by the given name on the object:

irb(main):014:0> b =3D :to_s.to_pro= c
=3D> #<Proc:0x8b4c4ec>
irb(main):015:0> b= .call 123
=3D> "123"


4. Inside the foo method, it uses a yield = function with an argument
"Jim". =A0Somehow, the string "Jim" made it way to assi= gn to the variable
n, upcasing it.

= Keyword "yield" is used to invoke a block passed to the method; s= ince the method does not have a name there must be a standard way to invoke= it. =A0The other ways I have also shown in line 1 above.

A few= other aspects

Kind regards

robert


--
remember.guy do |as, often| as.you_can - without end
= http://blog.rubybestpractice= s.com/
--000e0cd6b43cc1a9fc04da30e907--