Understanding Ruby Blocks, Procs and Lambdas

97 views
Skip to first unread message

Fernando Marcheselli

unread,
Feb 21, 2013, 12:16:44 AM2/21/13
to laruby...@googlegroups.com

Bruce Hobbs

unread,
Feb 21, 2013, 4:50:59 AM2/21/13
to laruby...@googlegroups.com

You may also find this free episode from Avdi Grimm's Ruby Tapas series worth watching:

--
Bruce Hobbs, CCP, CDP  Engineered Software      Office:  626-570-8028
Partner                856 N Monterey St        Cell:    626-278-0273
                       Alhambra, CA 91801-1574  FAX:     208-474-0732

Cynthia Kiser

unread,
Feb 28, 2013, 2:22:57 AM2/28/13
to laruby...@googlegroups.com
Oh my, my brain hurts. Some things are a lot clearer after reading Chapter 3 of Metaprogramming Ruby and watching the videos (and Dave Thomas's Ruby Object Model #3) but each of those just raised some additional questions. 

Probably the most puzzling example from this evening's discussion (at least to me) was that we could alter the values in variables in a lambda using eval, but using instance_eval. By eval'ing a string with a binding, we were able to change the value of a variable that was available at the time our lambda was created. And we could use instance_eval to set instance variables in our lambda but we couldn't figure out how to use instance_eval to set local variables, such as the variable we were able to alter via normal 'eval' + the binding.  Our example code was: 

def count_with_increment(start, incr)
  start -= incr
  puts binding
  lambda { start += incr }
end

1.9.3p392 :001 > load 'vid.rb'
 => true
1.9.3p392 :002 > c = count_with_increment(10, 3)
#<Binding:0x007fdabd02b9b8>
 => #<Proc:0x007fda...@vid.rb:4 (lambda)>
1.9.3p392 :003 > c.call
 => 10
1.9.3p392 :004 > c.call
 => 13
1.9.3p392 :005 > eval 'start = 30', c.binding
 => 30
1.9.3p392 :006 > c.call
 => 33
1.9.3p392 :007 > c.instance_eval { start = 2 }
 => 2
1.9.3p392 :008 > c.call
 => 36
1.9.3p392 :009 > c.instance_eval { junk = 2 }
 => 2
1.9.3p392 :010 > c.instance_eval { start }
NameError: undefined local variable or method `start' for #<Proc:0x007fda...@vid.rb:4 (lambda)>
        from (irb):10:in `block in irb_binding'
        from (irb):10:in `instance_eval'
        from (irb):10
        from /Users/cnk/.rvm/rubies/ruby-1.9.3-p392/bin/irb:16:in `<main>'
1.9.3p392 :011 > c.instance_eval { @junk = 2 }
 => 2
1.9.3p392 :012 > c.instance_eval { @junk }
 => 2


--- 
Next week, once we have mostly recovered, we'll be discussing Chapter 4 which gets back to somewhat more familiar territory: Class Definitions. That may let us get to the test framework articles that seem rather apropos:

What happens when MiniTest runs, or, what I think about testing using classes http://interblah.net/how-minitest-works
What happens when RSpec runs, or, what I think about testing with blocks http://interblah.net/how-rspec-works

Fernando Marcheselli

unread,
Feb 28, 2013, 3:58:03 PM2/28/13
to laruby...@googlegroups.com

Yesterday we were noticing how when you send a block to a method there was a difference b/w the block delimiters. Like:

method_name :some_object {block}

and

method_name :some_object do block end

I found jim wierich's response on http://onestepback.org/index.cgi/Tech/Ruby/BraceVsDoEnd.rdoc
to be very helpful in understanding the way the ruby parser

The difference is where in the operator precedence table they fall. { } binds tighter than do/end. 
For example:
f g { } is parsed as f(g { }), where the braces belong to the method g. 
On the other hand, f g do end is parsed as f(g) do end, where the braces belong to the method f. 
It only matters when you omit parenthesis and create ambiguities.

 
Message has been deleted

rex f

unread,
Mar 1, 2013, 5:10:37 PM3/1/13
to laruby...@googlegroups.com
another good one from more recently

http://code.google.com/p/tokland/wiki/RubyIdioms

On Friday, March 1, 2013 12:15:45 PM UTC-8, rex f wrote:
it's interesting to see how these paradigms are implemented: procs and lambdas as means to gain more duck typed secure code with control of side effects

Reply all
Reply to author
Forward
0 new messages