|
|
|
#1 |
|
Messages: n/a
Hébergeur: |
the following program for showing Variable / Method Ambiguity
def a print "Function 'a' called\n" 99 end for i in 1..2 if i == 2 print "a=", a, "\n" else a = 1 print "a=", a, "\n" end end will produce the result: a=1 Function 'a' called a=99 (as described in the PickAx2 book, p. 329) So at first I thought a Ruby program is interpreted? If interpreted, then the interpreter will see the "a = 1" at first as treat "a" as a variable, and then the second time it sees "a", the interpreter should treat it as a variable again, not as a method. So does that mean a Ruby program is not interpreted but compiled into some bytecode first? But then, sometimes I run a Ruby program and then it can run all the way until it see an "undefined local variable"... so that means it probably is not compiled... or else it would have stopped without running anything at all. So is a Ruby program interpreted or compiled? -- Posted via http://www.ruby-forum.com/. |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
> So is a Ruby program interpreted or compiled? interpreted. -- Posted via http://www.ruby-forum.com/. |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
Hi --
On Mon, 17 Sep 2007, Summercool Summercool wrote: > the following program for showing Variable / Method Ambiguity > > def a > print "Function 'a' called\n" > 99 > end > > for i in 1..2 > if i == 2 > print "a=", a, "\n" > else > a = 1 > print "a=", a, "\n" > end > end > > will produce the result: > > a=1 > Function 'a' called > a=99 > > (as described in the PickAx2 book, p. 329) > > So at first I thought a Ruby program is interpreted? If interpreted, > then the interpreter will see the "a = 1" at first as treat "a" as a > variable, and then the second time it sees "a", the interpreter should > treat it as a variable again, not as a method. No, because there's no such variable in scope. The second time through the loop, there's no assignment to a, and the first variable a has gone out of scope. So the only thing that "a" could mean, outside of an assignment, is the method a. David > So does that mean a > Ruby program is not interpreted but compiled into some bytecode first? > But then, sometimes I run a Ruby program and then it can run all the way > until it see an "undefined local variable"... so that means it probably > is not compiled... or else it would have stopped without running > anything at all. > > So is a Ruby program interpreted or compiled? > -- > Posted via http://www.ruby-forum.com/. > -- * Books: RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242) RUBY FOR RAILS (http://www.manning.com/black) * Ruby/Rails training & consulting: Ruby Power and Light, LLC (http://www.rubypal.com) |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
On Sep 17, 12:49 am, "David A. Black" <dbl...@rubypal.com> wrote:
> > No, because there's no such variable in scope. The second time through > the loop, there's no assignment to a, and the first variable a has > gone out of scope. So the only thing that "a" could mean, outside of > an assignment, is the method a. wow... i thought the "a" variable is kind of like in C or Python: for (i = 1; i <= 2; i++) { int a; if (i==2) { ... } else { ... } } so that the "a" exists all inside the for loop... maybe that's not right. now, we can view the variable "a" as existing in the else block but no where else in the original Ruby code? -- Posted via http://www.ruby-forum.com/. |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
Summercool Summercool wrote:
> So at first I thought a Ruby program is interpreted? If interpreted, > then the interpreter will see the "a = 1" at first as treat "a" as a > variable, and then the second time it sees "a", the interpreter should > treat it as a variable again, not as a method. So does that mean a > Ruby program is not interpreted but compiled into some bytecode first? > But then, sometimes I run a Ruby program and then it can run all the way > until it see an "undefined local variable"... so that means it probably > is not compiled... or else it would have stopped without running > anything at all. > > So is a Ruby program interpreted or compiled? It is interpreted but before being interpreted it is parsed. And whether a symbol is a variable or not is determined at parse time: when the parser sees the assignment "a = 1", it assumes that 'a' is a variable for all subsequent *lines* of the source code, until the end of the method or block where the assignment occured. It is has nothing to do with the order in which the code is executed. Also you'll notice that the "undefined local variable" message is actually "undefined local variable or method", because ruby can't know if the unknown symbol was supposed to be a method or a variable. Daniel |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
On 9/17/07, David A. Black <dblack@rubypal.com> wrote:
> Hi -- > > On Mon, 17 Sep 2007, Summercool Summercool wrote: > > <snip> > > > > (as described in the PickAx2 book, p. 329) > > > > So at first I thought a Ruby program is interpreted? If interpreted, > > then the interpreter will see the "a = 1" at first as treat "a" as a > > variable, and then the second time it sees "a", the interpreter should > > treat it as a variable again, not as a method. > > No, because there's no such variable in scope. The second time through > the loop, there's no assignment to a, and the first variable a has > gone out of scope. so this is lexical scoping, then? > So the only thing that "a" could mean, outside of > an assignment, is the method a. > > > David > -jf -- In the meantime, here is your PSA: "It's so hard to write a graphics driver that open-sourcing it would not ." -- Andrew Fear, Software Product Manager, NVIDIA Corporation http://kerneltrap.org/node/7228 |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
On Sep 17, 2007, at 12:08 PM, Jeffrey 'jf' Lim wrote: > On 9/17/07, David A. Black <dblack@rubypal.com> wrote: >> Hi -- >> >> On Mon, 17 Sep 2007, Summercool Summercool wrote: >> >> <snip> >>> >>> (as described in the PickAx2 book, p. 329) >>> >>> So at first I thought a Ruby program is interpreted? If >>> interpreted, >>> then the interpreter will see the "a = 1" at first as treat "a" as a >>> variable, and then the second time it sees "a", the interpreter >>> should >>> treat it as a variable again, not as a method. >> >> No, because there's no such variable in scope. The second time >> through >> the loop, there's no assignment to a, and the first variable a has >> gone out of scope. > > so this is lexical scoping, then? No, it is just that Ruby has a single-pass parser. The parser needs to decide if an identifier is a local variable or a zero-argument method before it has seen the entire text of the file (no look-ahead). Until the parser sees an assignment of the form "a = ..." it assumes that 'a' is a method call. So if/then/else statements do *not* create new lexical scopes. Gary Wright |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
David A. Black wrote:
> No, because there's no such variable in scope. The second time through > the loop, there's no assignment to a, and the first variable a has > gone out of scope. So the only thing that "a" could mean, outside of > an assignment, is the method a. > That doesn't seem to bear out. If you switch the if statement around so that the assignment happens first: def x print "Function 'x' called\n" 99 end for i in 1..2 if i == 1 x = 10 print "x=", x, "\n" else print "x=", x, "\n" end end the output is: x=10 x=10 The second time through that loop, there is no assignment to x and the previous x has gone out of scope, yet the else clause's use of x does not result in a method call. As p. 329 in pickaxe2 carefully explains, it is a ruby parsing rule that determines what x means. As I read the rule, and as Daniel explains, and as the two examples show(the 'a' example and the 'x' example), the rule is: if there is any code that has x=val on a line before the use of x, then x will be interpreted as a variable. If there is no assignment to x on a line higher in the code, then x will be interpreted as a method call. -- Posted via http://www.ruby-forum.com/. |
|
|
|
#9 |
|
Messages: n/a
Hébergeur: |
7stud -- wrote:
>David Black wrote: >The second time through >the loop, there's no assignment to a, and the first variable a has >gone out of scope. > Wait a minute. 'a' has gone out of scope? for i in 1..2 if i == 1 a = 10 print "a=", a, "\n" else puts a end end puts "*#{a}" puts a --output:-- a=10 10 *10 In ruby, for loops and if clauses don't create a scope. -- Posted via http://www.ruby-forum.com/. |
|
|
|
#10 |
|
Messages: n/a
Hébergeur: |
7stud -- wrote:
> That doesn't seem to bear out. If you switch the if statement around so > that the assignment happens first: > > def x > print "Function 'x' called\n" > 99 > end > > The difference between the both examples is the following: Ruby parses this: for i in 1..2 if i == 2 print "a=", a, "\n" >> Here Ruby decides, that "a" must mean the a method and creates the call-method node in its tree. else a = 1 >> Here Ruby decides, a is a local variable. print "a=", a, "\n" >> Here Ruby creates a evaluate-local-variable node in its tree. end end In your example: > for i in 1..2 > if i == 1 > x = 1 > >> Here Ruby decides, "x" is a local variable. > print "x=", x, "\n" > >> Here Ruby creates a evaluate-local-variable node in its tree. > else > print "x=", x, "\n" > >> Sticks to its former decision, that "x" is local variable, and creates a evaluate-local-variable node in its tree. > end > end > This is an interaction between parsing and execution or ruby code, and it can be a bit surprising. The later execution (== comparisons, etc.) doesn't alter the behavior of the parser, which does its jobs earlier. -- Florian Frank |
|
|
|
#11 |
|
Messages: n/a
Hébergeur: |
RnJvbTogN3N0dWQgLS0gW21haWx0bzpkb2xndW5AZXhjaXRlLm NvbV0gDQojIEluIHJ1YnksIGZv
ciBsb29wcyBhbmQgaWYgY2xhdXNlcyBkb24ndCBjcmVhdGUgYS BzY29wZS4NCg0KaXJiKG1haW4p OjAwMTowPiBpZiBmYWxzZQ0KaXJiKG1haW4pOjAwMjoxPiAgIC B4DQppcmIobWFpbik6MDAzOjE+ IGVuZA0KPT4gbmlsDQppcmIobWFpbik6MDA0OjA+IHgNCk5hbW VFcnJvcjogdW5kZWZpbmVkIGxv Y2FsIHZhcmlhYmxlIG9yIG1ldGhvZCBgeCcgZm9yIG1haW46T2 JqZWN0DQogICAgICAgIGZyb20g KGlyYik6NA0KaXJiKG1haW4pOjAwNTowPiBpZiBmYWxzZQ0KaX JiKG1haW4pOjAwNjoxPiAgICB4 ID0gNQ0KaXJiKG1haW4pOjAwNzoxPiBlbmQNCj0+IG5pbA0KaX JiKG1haW4pOjAwODowPiB4DQo9 PiBuaWwNCg0KdGhleSBjYW4gaW50cm9kdWNlIGEgdmFyICh1bm RlciB0aGUgZXhpc3RpbmcgbG9j YWwgc2NvcGUgb2YgY291cnNlKS4NCmkgdGhpbmsgaXRzIGluIH RoZSBhc3NpZ25tZW50IGJlaGF2 aW91ciBpZiB5b3UgbG9vayBhdCBpdC4gIHBhcnNlciBzZWVzIG Fzc2lnbm1lbnQgZXZlbiBpZiBj b2RlIGlzIG5vdCBleGVjdXRlZC4NCnJ1YnkganVzdCB0cnkgdG 8gYmUgZnJpZW5kbHksIGJ1dCB5 b3UgY2FuIGJlIHNsb3BweSBpZiB5b3Ugd2FudCB0byBhbmQgcn VieSB3aWxsIG5vdCBnaXZlIHlv dSBhbiBlcnJvciA6KQ0KYWdhaW4sIGkgdGhpbmsgdGhpcyBpcy BhIGZhcS4NCg0Ka2luZCByZWdh cmRzIC1ib3RwDQo= |
|
|
|
#12 |
|
Messages: n/a
Hébergeur: |
Hi,
7stud -- wrote: > David A. Black wrote: > As p. 329 in pickaxe2 carefully explains, it is a ruby parsing rule that > determines what x means. As I read the rule, and as Daniel explains, > and as the two examples show(the 'a' example and the 'x' example), the > rule is: if there is any code that has x=val on a line before the use of > x, then x will be interpreted as a variable. If there is no assignment > to x on a line higher in the code, then x will be interpreted as a > method call. Please, look at this 2 examples of "parse-time": 1) > pp ParseTree.translate('bar = 3 define_method(:foo) do bar end') [:block, [:lasgn, :bar, [:lit, 3]], [:iter, [:fcall, :define_method, [:array, [:lit, :foo]]], nil, [:lvar, :bar]]] 2) > pp ParseTree.translate('bar = 3 def foo bar end') [:block, [:lasgn, :bar, [:lit, 3]], [:defn, :foo, [:scope, [:block, [:args], [:vcall, :bar]]]]] *** In 1) we see a :lvar node, whereas in 2) we see a :vcall. From my interpretation of p.329 of pickaxe2 i do not agree with the 2nd case (but probably it's my problem - comment please). In the 2nd case, IMHO, we should see a lvar node. This may seem a detail, but i was bitten by that a few minutes ago. Let me show a simplified example: bar = "test" c = Class.new c.class_eval do def foo bar end end > c.new.foo NameError: undefined local variable or method `bar' # i was expecting to get "test" The (hack) "solution" (it's a hack because IMHO i shouldn't have to do that): bar = "test" c = Class.new c.class_eval do define_method(:foo) do bar end end > c.new.foo "test" Note: only one more thing, since ruby 1.8 have a "problem" with block (it can't get other blocks - &block in argument) this could be a problem. I know you can hack these thing through a method - but that's another hack :P... too much hacks for me :-) I would appreciate very much all your comments about the current behavior of ruby (1.8). Regards, Vasco Andrade e Silva -- Posted via http://www.ruby-forum.com/. |
|
![]() |
| Outils de la discussion | |
|
|