From: "ara.t.howard" Date: 2008-11-02T10:09:21+09:00 Subject: Re: How to access to local variables in enclosing scopes? On Nov 1, 2008, at 5:08 PM, Yuh-Ruey Chen wrote: > I have already posted an example: > > def foo > a = 10 > def bar > # should somehow be able to access a > end > bar > end > foo > # here, we should not be able to access foo's a, but if there is > another a in scope, we can access that > > Of course, afterwards I found out that Ruby doesn't really have nested > procedures, even if it tricks you into thinking that has them. So it's > kinda a moot point now. it's not moot, it's easy and you *can* have nested procedures: cfp:~ > cat a.rb def foo a = 10 this = self.class.method(:foo) this.singleton_class{ define_method(:bar){ a } } this.bar() end p foo() p bar() BEGIN { def singleton_class &b sc = class << self; self end b ? sc.module_eval(&b) : sc end } cfp:~ > ruby a.rb 10 a.rb:11: undefined method `bar' for main:Object (NoMethodError) here 'bar' is a static method (attached to the method object *itself*) of foo. of course it has access to the local variables. this construct makes even methods which take blocks trivial cfp:~ > cat a.rb def foo &block a = 10 this = self.class.method(:foo) this.singleton_class{ define_method(:bar){ block.call + a } } this.bar() end p foo{ 32 } BEGIN { def singleton_class &b sc = class << self; self end b ? sc.module_eval(&b) : sc end } cfp:~ > ruby a.rb 42 i'll accept that you might not like the syntax, but as someone who coded perl professionally for 5 years i know exactly the pain that 'my' can inflict - here is one of the last perl scripts i wrote http://codeforpeople.com/lib/perl/ozone/ozone.pl i save it to remind myself of the insanity you have to jump through to provide data encapsulation, which 30 years of software design has proven to be a 'good thing' (recall that 'my' is/was heavily reccomended by all the perl style guids (at the time). in any case, we do the same with ml/lisp etc - only insane people don't use 'let' and then only with good reason. all of us who remember that recall using a debugger to figure out where that damn variable came from (i have never, in 7 years, needed a debugger with ruby). (OT - i *did* learn a ton about these concepts from http://www.manning.com/conway - highly recommended for people that want to know what it is to *make* objects from scratch using little else but scoping rules) i totally see that you are correct, but it really seems like you are arguing for something as provably arcane and slippery as GOTO - it might make certain programs shorter, but it makes *all* programs more difficult to maintain. in the end it seems vastly simpler to *provide* a scope when it's needed, rather than to always be wondering what the scope actually is. my brain hates stack frames.... the key to seeing how to do this is to realize blocks *always* cary the scope/closure in ruby, you can always do this: cfp:~ > cat a.rb def foo &block b = block.call a = eval('a', block) a + b end a = 32 p foo{ 10 } cfp:~ > ruby a.rb 42 and you can always use Kernel.binding, which ERB certainly does. as matz says, "it's no harm to learn new programming languages". or, as a british guy i used to now used to say: "suck it and see" good luck! a @ http://codeforpeople.com/ -- we can deny everything, except that we have the possibility of being better. simply reflect on that. h.h. the 14th dalai lama