From: Rudolf Polzer Date: 2003-09-09T06:19:43+09:00 Subject: Re: Emulate perls local Scripsit illa aut ille �Karsten Meier� : > 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. > def local(var) > eval("save = #{var.id2name}") > result = yield > eval("#{var.id2name} = save") > result > end [...] > It works quite well, but I like to know if I can get rid of the eval(). > I already have my variable as symbol, so I think it must be possible > somehow to restore the variable from the symbol, without use of eval. > Do you have an idea for a more elegant solution? I cannot solve THAT problem, but there's another thing: def local(var) eval("save = #{var.id2name}") begin result = yield ensure eval("#{var.id2name} = save") end end Otherwise it doesn't work through exceptions. What do you need it for? If you don't need to use the $something variables in the usual way, you could use something like this: class SaveRestoreVariable < Array attr_accessor :value def initialize(val) @value = val end def localize(&block) push(@value) begin yield ensure @value = pop() end end end v = SaveRestoreVariable.new(17) v.localize() do v.value = 42 puts v.value end puts v.value