"Rudolf Polzer" <denshimeiru-sapmctacher / durchnull.de> schrieb im Newsbeitrag news:slrnblprei.b2n.denshimeiru-sapmctacher / message-id.durchnull.ath.cx... > Scripsit illa aut ille ?Karsten Meier? <discussion / internetlabor.de>: > > I'm working on the ruby section of the pleac project, > > (http://pleac.sourceforge.net) because I think a good way to learn a new > > language is trying to explain it to somebody else. > > There are a few hundred code snippnets from the famous perl cookbook, > > and one of it is perls local function: > > You can give a global variable inside a block a new value. This is > > slightly different from normal local variable, because it really changes > > the global variable. I think it is sometimes even useful, when you need > > to change the predefined global variables, but want to automatically > > restore them after you are done. > > Not really. > > rpolzer@katsuragi ~ $ perl -e ' > $a = 17; > $p = \$a; > { > local $a = 42; > $q = \$a; > } > print "$a, $p<$$p>, $q<$$q>\n"; > ' > 17, SCALAR(0x812e798)<17>, SCALAR(0x812155c)<42> > > It's more than Save&Restore of the variable contents. It saves and > restores the variable pointers in the symbol table. In fact, both > $a were DIFFERENT variables, which justifies the "declaration-style > syntax" of local. But perl and ruby treat variables differently. Especially in perl there can be two instances that carry the value 42 while in ruby this is always one instance that is referenced. If you would use the proposed solution and assign another global from the temporarily changed global you could produce similar output to your perl variant. (Without the hex addresses, of course) My concern would rather be that the proposed solution (apart from the exception thingy that you fixed) would not work for multiple threads. As far as I remember the perl's "local" does dynamically scoping, i.e., it affects only methods invoked from the method that contains the "local". In a single threaded environment this is no difference, but in MT environments as ruby this does make a significant difference. Thus a thread safe ruby solution should rather include Thread[] and Thread[]=, which unfortunately would make the syntax more ugly. Technically this could be a solution, but it does not look nice which certainly defys the original intention: def local(sym, val) ar = ( Thread.current[sym] ||= [] ) ar.unshift( val ) begin yield ensure ar.shift end end def get_local(sym) ar = Thread.current[sym] raise "#{sym} undefined" unless ar && !ar.empty? ar[0] end def set_local(sym, val) ar = Thread.current[sym] raise "#{sym} undefined" unless ar && !ar.empty? ar[0]= val end # usage, thread safe local :foo, 20 do puts get_local( :foo ) local :foo, 42 do puts get_local( :foo ) end end Regards robert