SORU
20 HAZİRAN 2009, CUMARTESİ


Nasıl bir şey kesilebilir devlet olmadan yararlı olabilir mi?

Fonksiyonel programlama son zamanlarda hakkında bir sürü şey okudum ve çoğunu anlıyorum, ama ben sadece kafamın almadığı tek şey vatansız kodlama. Bana öyle geliyor ki, basitleştirme programlama kaldırarak kesilebilir devlet gibi "basitleştirme" bir araba kaldırarak pano: bitmiş ürün olabilir basit, ama iyi şanslar yapma etkileşim ile son kullanıcılar.

Her kullanıcı uygulama aklıma içerir çekirdek bir kavram olarak devlet. Eğer bir belge (bir yazı) yazarsanız, devletin her yeni giriş ile değiştirir. Ya da eğer bir video oyunu oynamak, durum değişkenleri ton, etrafında sürekli hareket etme eğilimi olan tüm karakterleri, konumları ile başlıyor. Nasıl işe yarar bir şey değişen değerleri takip olmadan yapabilir misin?

Her zaman bu sorun anlatılır bir şey buldum, yok bu ağır FP bir arka plan varsayar gerçekten teknik fonksiyonel-ese yazılmış. Herkes zorunlu kodlama iyi, sağlam bir anlayışa sahip biri bunu açıklamak ama işlevsel bir tarafta tam bir n00b bir yol biliyor mu?

EDİT: cevaplar BİR demet kadar sabit değerler avantajlarından beni ikna etmeye çalışıyor gibi görünüyor. O kısmı anladım. Bence çok mantıklı. Değişmesi, değerlerin takip edilmesi ve sürekli değiştirebilirsiniz nasıl olduğunu anlamadığım şey, değişken değişkenler olmadan.

CEVAP
20 HAZİRAN 2009, CUMARTESİ


Ya da eğer bir video oyunu oynamak, vardır durum değişkenleri ton başına tüm pozisyonları karakterler, hareket eden eğilimindedir sürekli. Nasıl yapabilir misin hiçbir şeyi takip etmeden yararlı değişen değerleri?

Senin istekli, here's Ayrık ile oyun programlama anlatan bir yazı dizisi.

Muhtemelen bu cevap gibi olmayacak, ama olmayacak . ben^>olsunfonksiyonel bu kadar program. Kod örnekleri gönderebilirsiniz ve "burada değilsiniz . ben^>bakın"-- eğer sözdizimi ve temel ilkeleri anlamıyorsun eğer doğru değilse, o zaman sadece gözleri donuklaşır. Sizin bakış açınızdan, eğer zorunlu bir dil olarak aynı şeyi yapıyorum gibi görünüyor, ama kasıtlı sınırları her türlü ayarlama programlama daha zor hale getiriyor. Benim açımdan, sadece Blub paradox yaşıyorsunuz.

İlk başta şüpheliydim, ama fonksiyonel programlama trende bir kaç yıl önce ben atladım ve ona aşık oldu. Fonksiyonel programlama ile hile desenleri, özellikle değişken atamaları, tanımak ve zorunlu devlet yığını taşımak için güçlü olmak. -Bir döngü, örneğin, özyineleme olur:

// Imperative
let printTo x =
    for a in 1 .. x do
        printfn "%i" a

// Recursive
let printTo x =
    let rec loop a = if a <= x then printfn "%i" a; loop (a   1)
    loop 1

Onun o kadar da güzel değil, ama hiç bir mutasyon ile aynı sonucu aldık. Mümkün olan her yerde elbette, tamamen döngü önlemek ve soyut tıpkı biz gibi:

// Preferred
let printTo x = seq { 1 .. x } |> Seq.iter (fun a -> printfn "%i" a)

Seq.iter yöntemi koleksiyonu sıralamak ve her madde için anonim işlevini çağırır. Çok kullanışlı :)

Ben, baskı sayıları tam olarak etkileyici değil. Ancak, oyun ile aynı yaklaşımı kullanabilirsiniz: tüm devlet yığın tutun ve özyinelemeli çağrı yaptığımız değişiklikler ile yeni bir nesne oluşturur. Bu şekilde, her kare her kare sadece ne vatansız nesneleri güncellenmesi istenen değişiklik ile yeni bir nesne oluşturur oyunun vatansız bir görüntüsüdür. Bu yalancı olabilir:

// imperative version
pacman = new pacman(0, 0)
while true
    if key = UP then pacman.y  
    elif key = DOWN then pacman.y--
    elif key = LEFT then pacman.x--
    elif key = UP then pacman.x  
    render(pacman)

// functional version
let rec loop pacman =
    render(pacman)
    let x, y = switch(key)
        case LEFT: pacman.x - 1, pacman.y
        case RIGHT: pacman.x   1, pacman.y
        case UP: pacman.x, pacman.y - 1
        case DOWN: pacman.x, pacman.y   1
    loop(new pacman(x, y))

Zorunlu ve işlevsel sürümleri aynı ama işlevsel sürümü için net bir değişken devlet kullanır. Fonksiyonel kod tüm devlet bu yaklaşım hakkında güzel bir şey, eğer bir şeyler yanlış giderse, hata ayıklama kolay -- yığında tutulan tutar, bir yığın izlemesi gerek.

Bu tüm nesneleri (veya ilgili nesnelerin koleksiyonları) kendi iplik kılınabilir çünkü nesnelerin herhangi bir sayı kadar oyun ölçeklendirir.

Her kullanıcı uygulaması I aklıma bir temel olarak devlet içerir kavram.

Nesnelerin durumunu mutasyona yerine fonksiyonel dillerde, biz sadece istediğimiz değişiklikleri ile yeni bir nesne döndürür. Bunu daha verimli geliyor. Veri yapıları, örneğin, değişmez veri yapıları temsil etmek çok kolaydır. Yığınlar, örneğin, uygulamak herkesin bildiği kolay

using System;

namespace ConsoleApplication1
{
    static class Stack
    {
        public static Stack<T> Cons<T>(T hd, Stack<T> tl) { return new Stack<T>(hd, tl); }
        public static Stack<T> Append<T>(Stack<T> x, Stack<T> y)
        {
            return x == null ? y : Cons(x.Head, Append(x.Tail, y));
        }
        public static void Iter<T>(Stack<T> x, Action<T> f) { if (x != null) { f(x.Head); Iter(x.Tail, f); } }
    }

    class Stack<T>
    {
        public readonly T Head;
        public readonly Stack<T> Tail;
        public Stack(T hd, Stack<T> tl)
        {
            this.Head = hd;
            this.Tail = tl;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Stack<int> x = Stack.Cons(1, Stack.Cons(2, Stack.Cons(3, Stack.Cons(4, null))));
            Stack<int> y = Stack.Cons(5, Stack.Cons(6, Stack.Cons(7, Stack.Cons(8, null))));
            Stack<int> z = Stack.Append(x, y);
            Stack.Iter(z, a => Console.WriteLine(a));
            Console.ReadKey(true);
        }
    }
}

Yukarıdaki kod iki değişmez listeleri oluşturur, onları yeni bir liste yapmak için ekler ve sonuçları ekler. Hayır kesilebilir devlet herhangi bir uygulamada kullanılır. Biraz hantal görünüyor, ama sadece C için# ayrıntılı bir dildir. İşte F eşdeğer program#:

type 'a stack =
    | Cons of 'a * 'a stack
    | Nil

let rec append x y =
    match x with
    | Cons(hd, tl) -> Cons(hd, append tl y)
    | Nil -> y

let rec iter f = function
    | Cons(hd, tl) -> f(hd); iter f tl
    | Nil -> ()

let x = Cons(1, Cons(2, Cons(3, Cons(4, Nil))))
let y = Cons(5, Cons(6, Cons(7, Cons(8, Nil))))
let z = append x y
iter (fun a -> printfn "%i" a) z

Hiçbir değişken oluşturmak ve işlemek için gerekli listeler. Neredeyse tüm veri yapıları kolaylıkla fonksiyonel eşdeğerleri dönüştürülebilir. Yığınlar, kuyruklar, solcu kümeler, kırmızı-siyah ağaçlar, tembel listelerinin değişmez uygulamaları sağlayan bir sayfa here yazdım. Kod tek bir parçacığın herhangi bir değişken durum içerir. "Mutasyona" bir ağaç, ben oluşturmak yepyeni bir yeni düğüm istiyorum -- bu çok etkili çünkü ihtiyacım yok olun bir kopyasını her düğüm ağacında, ben yeniden eskisi olanlar benim yeni ağaç.

Daha önemli bir örnek, ben de olan this SQL parser yazdı olmayan (ya da en azından . kesinlikle kullanma ben^>benimkod, temel lexing kütüphane vatansız olup olmadığını bilmiyorum vatansız).

Vatansız programlama programlama duruma kadar etkileyici ve güçlü olduğunu, sadece kendini statelessly düşünmeye başlamak için eğitmek için biraz pratik gerektirir. Elbette mümkün, durum bilgisi olan programlama gerektiğinde" en saf fonksiyonel dil sloganı gibi görünüyor. "programlama vatansız Tekrar işlevsel yaklaşım gibi temiz ya da verimli değil mutables düşen bir sakıncası yok.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • jkimisyellow

    jkimisyellow

    6 Mayıs 2009
  • Ludique

    Ludique

    21 NİSAN 2009
  • Vladimir Jenko

    Vladimir Jen

    1 Mart 2010