On 8/31/07, Robert Klemme <shortcutter / googlemail.com> wrote:
> 2007/8/30, grocery_stocker <cdalten / gmail.com>:
> > How come when I do something like
> >
> > #!/usr/bin/ruby -w
> >
> > def n_times(thing)
> >         return thing
> > end
> >
> > pi = n_times(23);
> > puts pi
> >
> >
> > the variable 'thing' doesn't go out of scope.
> >
> > But when I do something like
> >
> > #!/usr/bin/ruby
> >
> > def n_times(thing)
> >         return lambda{|n| thing * n}
> > end
> >
> > pi = n_times(23);
> > puts pi.call(2)
> >
> >
> > The varialble 'thing' does go out of scope.
>
> Does it?
>
> $ ruby<<XXX
> > def n_times(thing)
> >        return lambda{|n| thing * n}
> > end
> >
> > pi = n_times(23);
> > puts pi.call(2)
> > puts thing
> > XXX
> 46
> -:7: undefined local variable or method `thing' for main:Object (NameError)
>
> Ruby has static scoping rules but, err, can't remember the proper
> term, dynamic binding.  When you create the lambda you create a
> closure which keeps references in its environment alive.
>
> Kind regards
>
> robert
>
>
Hmm it might be a case where object and variable could easily get
confused, I have jotted down a little example which, I hope, shows
what is going on here:

------------------ 8< ----------------
def a param
  proc { param << "." }
end
def b param
  proc { param = param + "." }
end

o = "42"
p = a o
q = a o
puts p.call
puts p.call
puts q.call
puts o

-->42.
-->42..
-->42...
-->42...

o = "42"
p = b o
q = b o
puts p.call
puts p.call
puts q.call
puts o
-->42.
-->42..
-->42.
-->42

Cheers
Robert
-- 
I'm an atheist and that's it. I believe there's nothing we can know
except that we should be kind to each other and do what we can for
other people.
-- Katharine Hepburn