Thread overview
D vs Racket, bir ornek
Jan 04, 2015
Mengu
Jan 04, 2015
Mengu
January 04, 2015

selamlar herkese

coursera'da programming languages isminde bir kurs aliyorum ve ilerledim bayagi. (maalesef gec basladigim icin herhangi bir degerlendirme olmayacak ama ogrenme adina harika bir kurs.) bu kurs fonksiyonel programlama dilleri olan ML ile basliyor, Racket ile devam ediyor ve Ruby ile bitiyor.

Racket odevlerinden ilkini yaparken bir kac ornegin D'de de ayni sekilde yapilabilecegi geldi aklima. mesela asagidaki kod xs ismindeki liste argumaninin her elemanina suffix argumanini ekliyor.

(define (string-append-map xs suffix)
 (map (lambda (x) (string-append x suffix)) xs))

bunun d karsiligini ben su sekilde yaptim:

auto stringAppendMap(T)(T list, string suffix) {
 return list.map!(a => a ~= suffix);
}

fakat bir baska ornek var ki, bu bir stream uretiyor. her cagrildiginda bir tuple donuyor. bu tuple'in ilk elemani bir deger ve ikinci elemani anonymous function. cagrildiginda yine ayni sekilde bir sonraki degeri ve ayni sekilde anonymous function donuyor. ek bir olay daha var, eger gosterilecek deger 5'e tam bolunebiliyorsa sayiyi negatif veriyoruz. dolayisiyla 1'den istedigimiz sayiya kadar deger dondurecek bu fonksiyon. ancak lazy evaluation yapmak istedigimiz icin her seferinde sadece tek bir deger ve siradaki degeri dondurecek bir fonksiyon donuyor.

(define funny-number-stream
 (letrec ([f (lambda (x)
               (cons (if (= 0 (remainder x 5))
                         (- x)
                         x)
                     (lambda () (f (+ x 1)))))])
   (lambda () (f 1))))

hep beraber bunun d versionunu yazalim istedim.

mesela ben asagidaki sekilde yazdigimda su hatayi aliyorum: "forward reference to inferred return type of function call 'funnyNumberStream'"

auto funnyNumberStream(int x) {
 return tuple(x % 5 == 0 ? -x : x, () => funnyNumberStream(x + 1));
}

Racket kodunu aciklamak icin:

letrec -> f isminde tanimlanan lambda expr'in body'de kullanilmasini saglar.
lambda -> anonymous function tanimlamasi yapar.
cons -> verilen argumanlarla liste olusturur ya da append eder.

haydi bakalim, gelsin oneriler.

p.s. yalniz su method calissaydi efsane olurdu. :-)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

January 04, 2015

freenode'daki #d kanalinda input range ile yapmayi tavsiye ettiler. bence de fena fikir degil ama racket ile (ve haliyle diger fonksiyonel programlama dilleriyle) ufacik bir kod parcacigiyla yapip d'de bu kadar kod yazmak insanin canini sikiyor. ancak d'deki take metodu ile range kullanildiginda lazy eval'e yaklasabiliyor durum.

struct FunnyNumberRange {

 int val = 1;

 @property bool empty() const {
   return false;
 }

 @property int front() {
   return val % 5 == 0 ? -val : val;
 }

 void popFront() {
   val = val + 1;
 }
}

take(FunnyNumberRange(), 10).writeln;

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

January 05, 2015

Bu konu Y combinator denen büyüye çok benziyor (ama aynısı değil). :) Y combinator, funnyNumberStream() içinden funnyNumberStream()'in çağrılamaması sorununu aşar:

http://rosettacode.org/wiki/Y_combinator

Oradaki D dili çözümünde özyinelemeli işlevlerin nasıl kendilerini self diye çağırabildiklerine dikkat edin.

Alıntı (Mengu):

>

fonksiyonel programlama dilleriyle) ufacik bir kod parcacigiyla yapip d'de bu kadar kod yazmak insanin canini sikiyor

Aynı sıkıntıyı Typed Racket'çiler de yaşıyorlar aslında. Yukarıdaki bağlantıda önce Racket başlığındaki nezih çözüme bak sonra da biraz aşağıdaki Typed Racket'teki can sıkıntısına... ;) Dil strongly typed olunca bu gibi konular güçleşiyor.

Bana sanki bu sorun D'de de Y combinator'daki fikirler kullanılarak çözülebilir gibi geliyor. Y combinator'u Tuple kullanacak biçimde değiştirmek gerek ama doğrusu bende şu anda onu çözecek enerji yok. :(

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]