From: Arlen Christian Mart Cuss Date: 2012-12-12T19:57:27+09:00 Subject: Re: How I can create/extract a variable/hash into the current binding in Ruby? --089e011777b5daf0ee04d0a58e04 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable To expand on Jan's comments, note the difference in disassemblies: >> puts RubyVM::InstructionSequence.disasm lambda { eval 'x =3D 1'; puts x = } =3D=3D disasm: =3D= =3D=3D=3D=3D =3D=3D catch table | catch type: redo st: 0000 ed: 0028 sp: 0000 cont: 0000 | catch type: next st: 0000 ed: 0028 sp: 0000 cont: 0028 |------------------------------------------------------------------------ 0000 trace 1 ( 3= ) 0002 putself 0003 putstring "x =3D 1" 0005 send :eval, 1, nil, 8, 0011 pop 0012 trace 1 0014 putself 0015 putself 0016 send :x, 0, nil, 24, 0022 send :puts, 1, nil, 8, 0028 leave =3D> nil >> puts RubyVM::InstructionSequence.disasm lambda { x =3D nil; eval 'x =3D = 1'; puts x } =3D=3D disasm: =3D= =3D=3D=3D=3D =3D=3D catch table | catch type: redo st: 0000 ed: 0030 sp: 0000 cont: 0000 | catch type: next st: 0000 ed: 0030 sp: 0000 cont: 0030 |------------------------------------------------------------------------ local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1) [ 2] x 0000 trace 1 ( 4= ) 0002 putnil 0003 setdynamic x, 0 0006 trace 1 0008 putself 0009 putstring "x =3D 1" 0011 send :eval, 1, nil, 8, 0017 pop 0018 trace 1 0020 putself 0021 getdynamic x, 0 0024 send :puts, 1, nil, 8, 0030 leave =3D> nil In the first instance, the parser decides that, having seen no local x, it must be a function call, and so "0016 send :x, 0, nil, 24, " is emitted. In the second, having already seen an x ("0003 setdynamic x, 0"), it knows that it is referring to the local var, so it emits "0021 getdynamic x, 0" instead of a call. Unfortunately, there's no in between where it could refer to either a local or function, because the compiler needs to know all locally-referable variables in order to emit the instructions; "setdynamic x, 0" is actually "setdynamic 2, 0" (note the 'local table' before the instructions in the second disassembly, and the total lack of same in the first one), which is why local variables are so fast; they're just direct offsets from the local frame pointer ("environment pointer" as of June 2012 ). So, in short, VM constraints are responsible for this being impossible. You could either just say 'a =3D b =3D c =3D d =3D =E2=80=A6 =3D nil' before yo= ur hash.extract to make them findable, or find a possibly "more Ruby" way. :) =E2=80=94 Arlen On Wed, Dec 12, 2012 at 9:23 PM, Jan E. wrote: > Hi, > > I'm no expert on this stuff, but I think it's a problem of the Ruby > interpreter determining variables while it parses the code: > > eval 'x =3D 1' > puts x > > This doesn't work, because the parser doesn't "see" the eval stuff. It > doesn't find an assignment for "x", so it assumes it's a method (which > leads to a NameError). > > If, however, you set "x" to an arbitrary value beforehands, it correctly > regognizes "x" as a variable: > > x =3D nil > eval 'x =3D 1' > puts x > > Apart from the technical stuff: I don't find it a good idea to just dump > variables into a binding, because it's just too much "magic". It makes > it hard to keep track of which variable has which value. And I can't > think of any good reason to do that when you're programming > object-oriented. > > Did you get the idea from PHP? Because that language is notorious for > dumping values into all kinds of contexts, which has lead and still > leads to gigantic security problems. > > -- > Posted via http://www.ruby-forum.com/. > > --089e011777b5daf0ee04d0a58e04 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable To expand on Jan's comments, note the difference in disassemblies:
=
>> puts RubyVM::InstructionSequence.disasm lambda= { eval 'x =3D 1'; puts x }
=3D=3D disasm: <RubyVM::In= structionSequence:block in irb_binding@(irb)>=3D=3D=3D=3D=3D
=3D=3D catch table
| catch type: redo =C2=A0 st: 0000 ed: 00= 28 sp: 0000 cont: 0000
| catch type: next =C2=A0 st: 0000 ed: 002= 8 sp: 0000 cont: 0028
|------------------------------------------= ------------------------------
0000 trace =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A01 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (= =C2=A0 3)
0002 putself =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0
<= div>0003 putstring =C2=A0 =C2=A0 =C2=A0 =C2=A0"x =3D 1"
0005 send =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 :eval, 1, nil, 8, <= ic:0>
0011 pop =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0
00= 12 trace =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A01
0014 putself = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0
0015 putself =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0
0016 send =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 :x, 0, nil, 24, <ic:1>
0022 send =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 :puts, 1, nil, 8, <ic:2>
0028 leave =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0
=3D>= nil
>> puts RubyVM::InstructionSequence.disasm lambda= { x =3D nil; eval 'x =3D 1'; puts x }
=3D=3D disasm: <= ;RubyVM::InstructionSequence:block in irb_binding@(irb)>=3D=3D=3D=3D=3D<= /div>
=3D=3D catch table
| catch type: redo =C2=A0 st: 0000 ed: 00= 30 sp: 0000 cont: 0000
| catch type: next =C2=A0 st: 0000 ed: 003= 0 sp: 0000 cont: 0030
|------------------------------------------= ------------------------------
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] = s1)
[ 2] x =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0
0000 trac= e =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A01 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ( =C2=A0 4)
0002 putnil =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0
0003 setdynamic =C2=A0 =C2=A0 =C2=A0 x, 0
0006 trace =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A01
0008 putself =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0
0009 putstring =C2=A0 =C2=A0 =C2=A0 =C2=A0&q= uot;x =3D 1"
0011 send =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 :eval, 1, nil, 8, <ic:0>
0017 pop =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0
0018 tr= ace =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A01
0020 putself =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0
0021 getdynamic =C2=A0 =C2=A0 =C2= =A0 x, 0
0024 send =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 :put= s, 1, nil, 8, <ic:1>
0030 leave =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0
=3D> nil

In the first instance= , the parser decides that, having seen no local x, it must be a function ca= ll, and so "0016 send :x, 0, nil, 24, <ic:1>" is emitted.

In the second, having already seen an x ("0003 set= dynamic x, 0"), it knows that it is referring to the local var, so it = emits "0021 getdynamic x, 0" instead of a call.

Unfortunately, there's no in between where it could refer to= either a local or function, because the compiler needs to know all locally= -referable variables in order to emit the instructions; "setdynamic x,= 0" is actually "setdynamic 2, 0" (note the 'local table= ' before the instructions in the second disassembly, and the total lack= of same in the first one), which is why local variables are so fast; they&= #39;re just direct offsets from the=C2=A0local frame pointer=C2=A0(= "environment pointer" as of June 2012).

So, in short, VM constraints are responsible for this b= eing impossible. You could either just say 'a =3D b =3D c =3D d =3D =E2= =80=A6 =3D nil' before your hash.extract to make them findable, or find= a possibly "more Ruby" way. :)

=E2=80=94 Arlen

On Wed, Dec 12, 2012 at 9:23 PM, Jan E. <li= sts@ruby-forum.com> wrote:
Hi,

I'm no expert on this stuff, but I think it's a problem of the Ruby=
interpreter determining variables while it parses the code:

eval 'x =3D 1'
puts x

This doesn't work, because the parser doesn't "see" the e= val stuff. It
doesn't find an assignment for "x", so it assumes it's a = method (which
leads to a NameError).

If, however, you set "x" to an arbitrary value beforehands, it co= rrectly
regognizes "x" as a variable:

x =3D nil
eval 'x =3D 1'
puts x

Apart from the technical stuff: I don't find it a good idea to just dum= p
variables into a binding, because it's just too much "magic".= It makes
it hard to keep track of which variable has which value. And I can't think of any good reason to do that when you're programming
object-oriented.

Did you get the idea from PHP? Because that language is notorious for
dumping values into all kinds of contexts, which has lead and still
leads to gigantic security problems.

--
Posted via http://= www.ruby-forum.com/.


--089e011777b5daf0ee04d0a58e04--