Spróbuj pomyśleć o "oczekiwaniach" tłumacza i pamiętaj, że w rubinie WSZYSTKO jest wyrażeniem (co oznacza, że wszystko ocenia się na pewną wartość, nawet konstrukcje, które w innych językach są uważane za "specjalne", jak np. -elses, loops, etcettera).
Więc:
y = ( #1
a #2
+ b #3
)/ #4
2 #5
Na linii 1 zaczniemy deklaracji zmiennej, a linia kończy z otwartym (w przygotowaniu) nawiasie. Interpreter oczekuje dalszej definicji, więc przechodzi do następnego wiersza, szukając VALUE do przypisania do zmiennej y
.
W wierszu 2 interpreter znajduje zmienną a
, ale bez nawiasu zamykającego. Wylicza ona wartość a
, która ma wartość 5
, a ponieważ linia 2 jest poprawnym wyrażeniem, interpreter rozumie, że to wyrażenie zostało zakończone (ponieważ w Ruby znak nowej OFTEN oznacza wskaźnik końca ekspresji). Do tej pory wyprodukował wartość 5
, ale jedyne oczekiwanie, jakie wciąż ma to, że musi pasować do otaczającego nawiasu.
Jeśli po tym tłumacz interpreter odnalazł nawias zamykający, przypisałby on wartość nawiasu do wartości a (i.e. 5)
(ponieważ wszystko musi mieć wartość, a użyta zostanie ostatnia wygenerowana wartość).
Gdy tłumacz dotrze do linii 3, znajdzie inne doskonale ważne wyrażenie ruby, + b
. Ponieważ + 5
(5
jest wartością zmiennej b
) jest VALID całkowitą deklaracją w ruby, interpreter widzi ją jako niezależną, w ogóle niezwiązaną z poprzednią 5
ocenioną dla zmiennej a
(pamiętaj, że nie miała innych oczekiwań, z wyjątkiem jeden do nawiasu). W skrócie, wyrzuca wartość uzyskaną dla a
i używa tylko wartości uzyskanej z + b
. W następnym wierszu znajduje on otaczający nawias, a więc wyrażenie w nawiasie zostaje przypisane do ostatniej wytworzonej wartości, która jest 5
wytworzona przez wyrażenie + b
.
Ponieważ w linii 4 interpreter znajduje /
, to (poprawnie) rozumie ją jako metodę dzielenia liczby całkowitej, ponieważ wygenerował on do tej pory liczbę całkowitą (int 5
)! Tworzy to oczekiwanie na możliwe argumenty metody, które znajdzie w linii 5. Wynikowe obliczone wyrażenie to y = 5/2
, co równa się 2
w dzieleniu całkowitym. Więc basicaly, oto co interpreter zrobił:
y = ( # Ok, i'm waiting for the rest of the parenthesis expression
a # cool, a has value 5, if the parenthesis ends here, this is the value of the expr.
+ b # Oh, but now I found + b, which has value + 5, which evaluates to 5. So now this is the last value I have evaluated.
)/ # Ok, the parenthesis have been closed, and the last value I had was a 5. Uow, wait, there is a slash/there! I should now wait for another argument for the/method of the 5 I have!
2 # Found, let's make y = 5/2 = 2!
Problem polega na tym, że na linii nr 2, należy opuściły oczekiwanie na tłumacza (dokładnie tak, jak w lewo na linii 4 z metodą /
) , czego nie zrobiłeś!
Odpowiedź @ Maurício Linhares sugeruje dokładnie to:
y = (
a +
b
)/
2
Przesuwając metody do końca linii 2 +
, powiedz tłumacza, że ekspresja nie jest jeszcze zakończona! Zachowuje więc oczekiwanie i przechodzi do linii # 3, aby znaleźć właściwy operand wyrażenia (lub, dokładniej, w Ruby, argument dla metody +
: D).
Te same prace sznurkiem konkatenacji:
# WRONG, SINCE + "somestring" is not a valid stand-alone expression in ruby
str = "I like to"
+ " move it!"
# NoMethodError: undefined method `[email protected]' for " move it!":String
# CORRECT, by leaving the + sign as last statement of the first line, you
# keep the 'expectation' of the interpreter for the next
# argument of the + method of the string object "I like to"
str = "I like to" +
" move it!"
# => "I like to move it!"
Różnica polega na tym, że w kodzie nie było błędu wyrzucony, ponieważ + B jest rzeczywiście ważny wyraz.
Mam nadzieję, że moja odpowiedź była przydatna na co daje pewną intuicję, dlaczego to nie działa zgodnie z oczekiwaniami, przepraszam, jeśli nie jestem zwięzły :)
żaden wyjątek, znak // komentarz był źle, przykro, że tylko po to, aby wyjaśnić wyniki programu. Edytowane. Dzięki za korektę. – waza