Piszę Ruby czytam Javascript…
Czy możliwość pisania w Rubym kodu, który jest automagicznie zamieniany na Javascript uruchamiany w przeglądarce nie brzmi intrygująco ?
Na liście ruby-talk kilka dni temu pojawił się post Paula Battley'a informujący o takim eksperymentalnym konwerterze. Dodam jeszcze, że cały kod który dokonuje tej konwersji ma około 250 linii... Musiałem sprawdzić, czy to rzeczywiście działa.
Postanowiłem napisać kawałek kodu w Rubym który wylicza n-tą liczbę z ciągu Fibonacciego. Gotowy efekt mojej pracy jest tutaj. Tak wygląda kod w Ruby:
-
class Fibonacci
-
def initialize
-
@cache = {'0'=>0, '1'=>1}
-
end
-
-
def calculate(n)
-
if @cache[n.to_s ]
-
return @cache[n.to_s ]
-
else
-
@cache[n.to_s ] = self.fib(n)
-
return @cache[n.to_s ]
-
end
-
end
-
-
def fib(n)
-
@curr = 0
-
@succ = 1
-
n.times do |i|
-
# jasne, ze nie jest to ruby way
-
@tmp = @curr
-
@curr = @succ
-
@succ = @tmp + @succ
-
end
-
return @curr
-
end
-
end
-
-
require 'rb2js'
-
puts RB2JS.class_to_js(Fibonacci, :debug => true)
po konwersji na JS wygląda tak:
-
function Fibonacci() {
-
var self = this;
-
self.instanceVariables = {};
-
self.instanceVariables['@cache'] = {
-
"0" : Number(0), "1" : Number(1)
-
}
-
}
-
Fibonacci.prototype = {
-
calculate : function(n) {
-
var self = this;
-
if(rb_true(self.instanceVariables['@cache'][n.toString()])) {
-
return self.instanceVariables['@cache'][n.toString()]
-
} else {
-
{
-
self.instanceVariables['@cache'][n.toString()] = self.fib(n);
-
return self.instanceVariables['@cache'][n.toString()]
-
}
-
}
-
},
-
fib : function(n) {
-
var self = this;
-
self.instanceVariables['@curr'] = Number(0);
-
self.instanceVariables['@succ'] = Number(1);
-
n.times(function(i) {
-
{
-
self.instanceVariables['@tmp'] = self.instanceVariables['@curr'];
-
self.instanceVariables['@curr'] = self.instanceVariables['@succ'];
-
self.instanceVariables['@succ'] = self.instanceVariables['@tmp'] +
-
self.instanceVariables['@succ']
-
}
-
});
-
return self.instanceVariables['@curr']
-
}
-
}
Cały konwerter to oczywiście bardziej proof-of-concept niż prawdziwe narzędzie, ale szlak został już przetarty...
[javascript ruby]








Manthios said,
lipiec 8, 2006 @ 08:39
Ciekawa koncepcja :)
Rozumiem, ze uzycie “calculate(n)” mialo wprowadzic pewien poziom skomplikowania dla konwertera - tak?
— P.J.S.
daniel said,
lipiec 8, 2006 @ 09:30
Dziękuję :)
calculate dodatkowo cache’uje wyniki obliczen ciagu (trzymane sa @cache) stad taki dodatkowy stopien komplikacji.
Manthios said,
lipiec 8, 2006 @ 18:42
No to moze sam fib(n) moglby korzystac z tego cache-a? Albo niech go chociaz pre-wypelnia w trakcie liczenia “dalszych” wynikow :) Wiem, wiem… nie o to chodzilo… przymykam sie ;)
daniel said,
lipiec 8, 2006 @ 20:56
Tak jest czytelniej IMHO, ale skoro się pytasz to implementacja najszybszego zdaje się algortymu dla wyliczania liczb fibonacciego jest tutaj.
Cala dyskusja na ruby-talk jest tutaj.
Manthios said,
lipiec 8, 2006 @ 21:55
Zwracam honor! Nie wiedzialem, ze ludzie z tego doktoraty pisza :)
daniel said,
lipiec 8, 2006 @ 22:07
hmm, chyba nie brałes nic ode mnie… ;)
Suler said,
lipiec 10, 2006 @ 13:14
Valar enters the blogosphere. The world ends ;-)
daniel said,
lipiec 10, 2006 @ 14:00
Suler na powietrzu, żebym zryżał…
Adam Hoscilo said,
lipiec 13, 2006 @ 14:03
Mala optymalizaja (czytaj czepianie sie :)):
@curr, @succ, i @tmp mozna zmienic ze zmiennych instancyjnych na lokalne i
moze to zaoszczedzic jeden cykl procesora na milion.
Chyba, ze RB2JS wymaga tu zmiennych instancyjnych (nie wyglada na to).
Do tego pytanie czy przy konwersji tworzone sa jakiekolwiek obiekty czy analizowana jest tylko klasa.
PS Zapomnialem sie przywitac. Witam:)
daniel said,
lipiec 13, 2006 @ 14:46
No wreszcie ktoś to zauważyl !! Niestety tak musiałem zrobić żeby JS działał poprawnie :) w przeciwnym razie tworzone są w JS lokalne zmienne wewnątrz pętli i całość nie działa. Gratuluje spostrzegawczości!
WItam serdecznie również.