Biraz daha derin bakarsanız, her ikisi de temel dilde diziler de içerir:
- 5. revize edilmiş Şema Raporu (R5RS), rasgele erişim için doğrusal zamandan daha iyi sabit boyutlu tamsayı ile indekslenmiş koleksiyonlar olan vektör tipini içerir .
- Haskell 98 Raporunun da bir dizi türü vardır .
Bununla birlikte, işlevsel programlama talimatı, diziler veya çift bağlantılı listeler üzerinde uzun süreli tek bağlantılı listeleri vurgulamıştır. Aslında, büyük olasılıkla fazla vurgulanmıştır. Bununla birlikte, bunun birkaç nedeni vardır.
Birincisi, tek bağlantılı listelerin en basit ama en kullanışlı özyinelemeli veri türlerinden biri olmasıdır. Haskell'in liste türünün kullanıcı tanımlı bir eşdeğeri şöyle tanımlanabilir:
data List a -- A list with element type `a`...
= Empty -- is either the empty list...
| Cell a (List a) -- or a pair with an `a` and the rest of the list.
Listelerin özyinelemeli veri türü olması, listelerde çalışan işlevlerin genellikle yapısal özyineleme kullandıkları anlamına gelir . Haskell terimleriyle: liste yapıcılarında desen eşleşmesi yaparsınız ve listenin bir alt bölümünde yinelenirsiniz . Bu iki temel işlev tanımında, as
listenin kuyruğuna başvurmak için değişkeni kullanıyorum . Bu nedenle, özyinelemeli çağrıların listede "aşağı indiğini" unutmayın:
map :: (a -> b) -> List a -> List b
map f Empty = Empty
map f (Cell a as) = Cell (f a) (map f as)
filter :: (a -> Bool) -> List a -> List a
filter p Empty = Empty
filter p (Cell a as)
| p a = Cell a (filter p as)
| otherwise = filter p as
Bu teknik, işlevinizin tüm sonlu listeler için sonlanacağını garanti eder ve aynı zamanda iyi bir problem çözme tekniğidir - doğal olarak problemleri daha basit, daha dayanıklı alt bölümlere ayırma eğilimindedir.
Dolayısıyla, tek bağlantılı listeler muhtemelen fonksiyonel programlamada çok önemli olan bu teknikleri öğrencilere tanıtmak için en iyi veri türüdür.
İkinci neden, "neden tek bağlantılı listeler" nedeninden daha az, ancak "neden çift bağlantılı listeler veya diziler değil" nedeninden daha fazladır: bu son veri türleri genellikle işlevsel programlamanın çok sık olduğu mutasyon (değiştirilebilir değişkenler) gerektirir uzağa bağlanır. Böylece, olduğu gibi:
- Şema gibi hevesli bir dilde, mutasyon kullanmadan çift bağlantılı bir liste yapamazsınız.
- Haskell gibi tembel bir dilde, mutasyon kullanmadan çift bağlantılı bir liste oluşturabilirsiniz. Ancak bu listeye dayalı yeni bir liste yaptığınızda, orijinalin yapısının tamamı olmasa bile çoğunu kopyalamak zorunda kalırsınız. Tek bağlantılı listelerde "yapı paylaşımı" kullanan işlevler yazabilirsiniz; yeni listeler uygun olduğunda eski listelerin hücrelerini yeniden kullanabilir.
- Geleneksel olarak, dizileri değişmez bir şekilde kullandıysanız, diziyi her değiştirmek istediğinizde her şeyi kopyalamanız gerektiği anlamına geliyordu. (
vector
Bununla birlikte, son Haskell kütüphaneleri bu problemi büyük ölçüde geliştiren teknikler bulmuştur).
Üçüncü ve son neden Haskell gibi tembel diller için geçerlidir: tembel tek bağlantılı listeler pratikte genellikle uygun bellek içi listelere göre yineleyicilere daha benzerdir . Kodunuz bir listenin öğelerini sırayla tüketiyor ve gittikçe dışarı atıyorsa, nesne kodu yalnızca listede ilerledikçe liste hücrelerini ve içeriğini gerçekleştirir.
Bu, tüm listenin bir anda bellekte bulunması gerekmediği anlamına gelir, sadece geçerli hücre. Mevcut olandan önceki hücreler toplanabilir (çift bağlantılı bir listeyle mümkün olmaz); mevcut olandan daha sonraki hücrelerin oraya gelinceye kadar hesaplanması gerekmez.
Bundan daha da ileri gidiyor. Derleyicinin liste işleme kodunuzu analiz ettiği ve sıralı olarak üretilen ve tüketilen ve sonra "atılan" ara listelerini belirlediği füzyon adı verilen birçok popüler Haskell kütüphanesinde kullanılan teknik vardır . Bu bilgi ile derleyici, bu listelerin hücrelerinin bellek tahsisini tamamen ortadan kaldırabilir. Bu, bir Haskell kaynak programındaki tek bağlantılı bir listenin, derlemeden sonra aslında bir veri yapısı yerine bir döngüye dönüştürülebileceği anlamına gelir .
Füzyon ayrıca yukarıda bahsedilen vector
kütüphanenin değişmez diziler için verimli kod üretmek için kullandığı tekniktir . Haskell'in çok büyük olmayan yerel türünün ( tek bağlantılı karakter listesiyle aynı olan bytestring
) yerini alan son derece popüler (bayt dizileri) ve text
(Unicode dizeleri) kütüphaneleri için String
de aynı şey geçerlidir [Char]
. Modern Haskell'de füzyon destekli değişmez dizi türlerinin çok yaygınlaştığı bir eğilim var.
Liste birleşimi, tek bağlantılı bir listede ilerleyebileceğiniz, ancak asla geriye gidemeyeceğiniz gerçeğiyle kolaylaştırılır . Bu, işlevsel programlamada çok önemli bir temayı ortaya çıkarır: bir hesaplamanın "şeklini" türetmek için veri türünün "şeklini" kullanma. Öğeleri sırayla işlemek istiyorsanız, tek bağlantılı liste, yapısal özyineleme ile tükettiğinizde, size bu erişim düzenini çok doğal olarak veren bir veri türüdür. Bir soruna saldırmak için "böl ve fethet" stratejisini kullanmak istiyorsanız, ağaç veri yapıları bunu çok iyi destekleme eğilimindedir.
Birçok insan işlevsel programlama vagonundan erken ayrılır, bu yüzden tek bağlantılı listelere maruz kalırlar, ancak daha gelişmiş altta yatan fikirlere maruz kalmazlar.