From: Robert Klemme Date: 2011-04-19T16:30:03+09:00 Subject: Re: anonymous closures with Proc,new, lambda and -> On Tue, Apr 19, 2011 at 8:07 AM, Stu wrote: > I am new to the study of functional paradigm. If this question is academic > please bear with me. > > How would I make this counter with lambda or -> without deferring to a named > generator method or sigil var? > > my ruby version: > > %  ruby -v > ruby 1.9.2p180 (2011-02-18 revision 30907) > > my code examples for explanation: > > % irb >>> closed = Proc.new( over=0){over+=1} >  => # >  >> 4.times { puts closed[] } > 1 > 2 > 3 > 4 >  => 4 That might not work as you expect: 09:22:04 ~$ ruby19 -e 'closed=Proc.new(over=0){over+=1};2.times{p closed[]};p over;over=-1;2.times{p closed[]}' 1 2 2 0 1 09:22:19 ~$ Please see below for explanation. (And btw, when it comes to local variables it's usually better to not test in IRB since that behaves a bit differently there.) > error out on  lambda > >>> closed = lambda( over=0){over+=1} > ArgumentError: wrong number of arguments(1 for 0) > ... > > and -> doesn't error but give undesired results: > >>> closed = ->( over=0){over+=1} >  => # > >>> 4.times { puts closed[] } > 1 > 1 > 1 > 1 >  => 4 > > in a named method I relize I can use a named method with argument being > bound while returning with either -> or lamda. for example: > > def closure( over=0) lambda{over+=1} end > def closure( over=0) ->{over+=1} end > > closed = closure > > both of these will work. I am just curious if there is a way to accomplish > the same thing without method name definition i.e anonymous function. The point is that for a closure to be created you need a scope. In your first case you basically do the same as over=0 closed = Proc.new{over+=1} In other words: you use the current scope. But only if you use a method or another lambda you can ensure that the scope is not visible any more to the outside world and is only accessible through the closure. And this is what one usually wants because otherwise the data can be manipulated from outside the closure which might break the desired functionality (such as resetting a counter as shown above). With these approaches you get a scope which is cut off and not accessible from the outside: 09:28:05 ~$ ruby19 -e 'def m(x=0)lambda {x+=1}end;f=m;2.times{p f[]}' 1 2 09:28:14 ~$ ruby19 -e 'm=lambda{|x=0| lambda {x+=1}};f=m[];2.times{p f[]}' 1 2 09:28:19 ~$ Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/