[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

How does ruby handle scope and closure in this case?

Chad

8/30/2007 12:24:00 AM

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.

5 Answers

Florian Aßmann

8/30/2007 12:49:00 AM

0

Hi,

I think it's a excution stack thing, you should look a the C code if you
want to understand ruby magic.

Hope I got your question, otherwise the text you got this example from
describes fairly good why the 'thing' (or aThing) variable 'gets' out of
scope (its refence is still hold by the Proc object).

Even in the first case you should got the Object out of scope since you
passed the reference:

def n_times(thing)
puts thing.object_id
return thing
end

pi = n_times(23)
puts pi.object_id


Regards
Florian


Morton Goldberg

8/30/2007 1:22:00 AM

0

On Aug 29, 2007, at 8:25 PM, grocery_stocker wrote:

> 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.

I think it does. The variable 'thing' from #n_times is not visible at
top level. If you were to do

puts thing

at this point, you would get an error.

Regards, Morton

John Miller

8/30/2007 3:40:00 AM

0

Florian AÃ?mann wrote:
> Hi,
>
> I think it's a excution stack thing, you should look a the C code if you
> want to understand ruby magic.
>
> Hope I got your question, otherwise the text you got this example from
> describes fairly good why the 'thing' (or aThing) variable 'gets' out of
> scope (its refence is still hold by the Proc object).
>
> Even in the first case you should got the Object out of scope since you
> passed the reference:
>
> def n_times(thing)
> puts thing.object_id
> return thing
> end
>
> pi = n_times(23)
> puts pi.object_id
>
>
> Regards
> Florian

This example will give a false impression. Fixnum's always have the
same ID regardless of scope. try this smae test with something other
then a small integer:

var = n_times(Object.new)
puts var.object_id

It will give you a much better sense of what is going on.

John Miller

--
Posted via http://www.ruby-....

Robert Klemme

8/31/2007 9:48:00 AM

0

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

Robert Dober

8/31/2007 10:54:00 AM

0

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