On 29.02.2012 19:22, Oliver Sch@d wrote:
> Robert Klemme wrote:
>
>> On 29.02.2012 09:00, Simon Krahnke wrote:
>>> * Oliver Sch@d (23:33) schrieb:
>>>
>>>> warum ergibt, wenn Objekt mit Namen "a" nicht definiert wurde, der
>>>> Ausdruck
>>>>
>>>> a = a
>>>>
>>>> ein nil?
>>>
>>> Weil Ruby in der Parse-Phase entscheidet, das a in diesem Kontext eine
>>> lokale Variable ist. In der Ausführ-Phase findet dann die Zuweisung
>>> statt. a ist definiert, also kein Problem.
>>
>> Stimmt! Den "a" kann ja auch ein Methodenaufruf sein. Das stellt man
>> dann erst zur Laufzeit fest. Oliver, vergiss meine Erklärung: die hier
>> ist viel besser.
>
> Das mag ja sein, dass sie besser ist, aber ich verstehe sie nicht richtig.
> Kann mir das jemand ausführlicher erklären?
>
> Wenn ich das richtig verstehe, wird erstmal entschieden, dass a ein Objekt
> sein muss und keine Methode, weil es auch links steht?
Nein. "a" ist eine lokale _Variable_, kein Objekt. Variablen
beinhalten Referenzen auf Objekte. Dass es eine Variable ist, wird
festgelegt durch das Vorkommen von "a=". Das Auftreten von "a" ohne
folgendes Gleichheitszeichen kann entweder eine lokale Variable meinen
oder einen Methodenaufruf. Ab der Zeile, in der eine Variable definiert
wird, hat diese Priorität vor dem Methodenaufruf:
$ ruby19 -e '
> class X
> def a;99;end
> def b
> p a
> a = 1
> p a
> end
> end
> X.new.b
> '
99
1
Da bei der Zuweisung "a = a" die Variable definiert wird, wird das "a"
auf der rechten Seite als Variable betrachtet und kein Methodenaufruf
versucht. Der initiale Wert aller Variablen in Ruby is "nil".
> Und der Fehler resultiert bei a = b nur daher, dass man das bei b eben
> nicht weiß, ob es Objekt oder Methode ist?
Im Falle "a = b" wird "b" als Methode betrachtet, da es vorher kein "b="
gab. Allerdings wird erst zur Laufzeit erkannt, dass es die Methode
nicht gibt. Das muss so sein, da wegen Ruby's Dynamik die Methode immer
noch angelegt worden sein kann, bevor diese Code-Zeilen ausgeführt werden:
$ ruby19 -e '
> class X
> def m1
> a = b
> end
> end
> begin
> X.new.m1
> rescue Exception => e
> p e
> end
> class X
> def b;88;end
> end
> begin
> X.new.m1
> puts "ok"
> rescue Exception => e
> p e
> end
> '
#<NameError: undefined local variable or method `b' for #<X:0x2019cbdc>>
ok
Außerdem kann man das ja mit method_missing behandeln:
$ ruby19 -e '
> class X
> def m2
> a = b
> end
> def method_missing(*a,&b)
> printf "Ooops! %p\n", a
> end
> end
> X.new.m2
> '
Ooops! [:b]