2014-06-15 12 views
6

Jak poprawnie pisać arytmetykę wielowierszową w języku Ruby? Poprzednio próbowałem czegoś takiego jak y, wtedy zdałem sobie sprawę, że coś jest nie tak z tym kodem. Muszę napisać wielowątkową arytmetykę z powodu mojego bardzo długiego równania.Napisz arytmetykę wielowierszową w języku Ruby

a = 5 
b = 5 

x = (a + b)/2 

puts x # 5, as expected 

y = (
     a 
     + b 
    )/
    2 

puts y # 2, what happened? 
+0

żaden wyjątek, znak // komentarz był źle, przykro, że tylko po to, aby wyjaśnić wyniki programu. Edytowane. Dzięki za korektę. – waza

Odpowiedz

5

Analizator składni Ruby przyjmuje, że instrukcja zakończyła się, jeśli wygląda na zakończoną na końcu wiersza.

co można zrobić to uniemożliwić opuszczenie operatora arytmetycznego tuż przed nową linię, jak to:

a = 1 
b = 2 
c = a + 
    b 

a dostaniesz wynik można oczekiwać.

+3

Alternatywnie można również zapobiec analizowaniu końca instrukcji za pomocą znaku '\\ (znak ukośnika odwrotnego), po którym następuje znak nowej linii. –

+0

Ta odpowiedź nie zapewnia żadnej pracy w pobliżu – Ven

+1

** instrukcja została zakończona ... jeśli wygląda na zakończoną na końcu linii ** jest prawie tautologią. To nie wyjaśnia niczego. – sawa

2
(
    expr1 
    expr2 
) 

jest w rzeczywistości, w Ruby, tak samo jak

(expr1; expr2) 

który właśnie wykonuje pierwszy wyraz (dla efektów ubocznych) i zwraca drugi (również po przeanalizowaniu go)

+0

Więc nie można pisać arytmetycznych wielowierszowych? – waza

+0

@ fidz.id Jest to możliwe. Maurício Linhares opisał, jak w jego odpowiedzi, która jest w 100% poprawna. –

+0

Wzniesiono go, ponieważ nie zasługuje on na komisję. Prawidłowe jest, że kod OP jest interpretowany jako '(a; + b)/2 == (5; 5)/2 == 5/2 == 2' - dzielenie całkowite. –

2

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 :)

Powiązane problemy