Swoją przygodę z Rubim rozpocząłem dwie godziny temu, choć nie jest to mój pierwszy język programowania (chociaż w interpreterach niewiele dotąd siedziałem) i bardzo mnie zdziwił następujący błąd:
pierwszy.rb:18:in +': can't convert Fixnum into Array (TypeError) from pierwszy.rb:18:inFibonacci’
from pierwszy.rb:6:in `main’
from pierwszy.rb:26
w następującej metodzie:
def Fibonacci n
tmp1 =1, tmp2 =1
if n<2
return n
else
n=n-1
while n>0
wynik = tmp1 + tmp2
tmp1=tmp2
tmp2 = wynik
end
return tmp1
end
end
Oczywiście ma on miejsce przy dużych wartościach, dla małych metoda działa poprawnie. Mój zonk polega na tym, że przecież w Ruby’im jak i w Pythonie rzutowanie odbywa się niejako automatycznie, więc co niby zrobiłem źle?
Pozdrawiam
Aha… nie dziwcie się, że tego Fibonacciego tak dziwnie liczę, nie chodzi o wynik tylko to czy kod działa czy nie :D.
Nie działa, poniewaz do zmiennej tmp1 przypisujesz tablice.
# dla rubiego ponizsze dwie linie sa jednoznaczne
tmp1 = 1, tmp2 = 1
tmp1 = [1, tmp2 = 1]
Daje to w rezultacie tablice skladajaca sie z dwoch jedynek pod zmienna tmp1 oraz wartosc 1 pod zmienna tmp2 i stad TypeError.
Aby dzialalo, wybierz jedna z ponizszych linii:
tmp1, tmp2 = 1, 1
tmp1 = tmp2 = 1
I nie zapomnij o dekrementacji licznika petli…
Błąd poprawiony, ale pozwolę sobie jeszcze na kilka uwag.
Dla metod używaj małych liter (Fibonacci sugeruje nazwę klasy). Przy deklaracji raczej używa się nawiasów, zatem lepiej jest:
def fibonacci(n)
#...
end
Używaj lepiej dobranych nazw zmiennych, “tmp1, tmp2” niewiele mówią (myślę że w liczeniu ciągów a, b lub n1, n2 byłoby lepsze).
I jeszcze mała uwaga co do stwierdzenia:
Niestety nie jest to prawdą. Mylisz tutaj pojęcia języka typowanego statycznie/dynamicznie oraz silnie/słabo typowanego. Ruby to język dynamiczny jednak typowanie ma silne. W skrócie oznacza to, że zmienne mogą posiadać dowolne typy podczas działania programu, ale typu danego obiektu nie można zmienić). Generalnie Ruby nie próbuje na siłę dopasować typów, dlatego “5” + 5 rzuci wyjątkiem (inaczej niż php który zwróci 10).
jeszcze jedno pytanko. Chce czytać ze standardowego wejścia dwie liczby, powiedzmy w konwencji:
scanf( “%d %d\n”, &liczbaA, &liczbaB );
korzystam z metody gets.to_i która mi niestety robi enter po każdym czytaniu. gets_chomp zamienia mi to na stringa co mi się też nie bardzo podoba więc z niej zrezygnowałem. Jak to najładniej zrobić, bo szukam w API języka i nic sensownego nie widzę