Yığın anlambiliminin kullanılmasına izin veren işlevsel bir dil var mı - kapsamın sonunda otomatik deterministik yıkım?
Yığın anlambiliminin kullanılmasına izin veren işlevsel bir dil var mı - kapsamın sonunda otomatik deterministik yıkım?
Yanıtlar:
Bildiğim kadarıyla işlevsel bir programlama uzmanı olmasam da.
Prensipte oldukça zor görünüyor, çünkü işlevlerden döndürülen değerler, aynı işlev içinde oluşturulan (yığında) diğer değerlere referanslar içerebilir veya bir parametre olarak kolayca iletilmiş veya iletilen bir şey tarafından başvurulan olabilir parametre olarak. C'de, bu sorun, programcı işleri doğru yapmazsa, sarkan işaretçilerin (veya daha kesin olarak tanımsız davranış) oluşmasına izin verilerek ele alınmaktadır. Bu, fonksiyonel dil tasarımcılarının onayladığı bir çözüm değil.
Yine de potansiyel çözümler var. Bir fikir, değerin kullanım ömrünü, değer referansının yanı sıra, değerin türünün bir parçası haline getirmek ve yığın tarafından ayrılan değerlerin geri döndürülmesini veya geri döndürülen bir şey tarafından referans alınmasını engelleyen tür tabanlı kuralları tanımlamaktır. işlevi. Etkilerin üzerinden çalışmadım, ama korkunç olacağını düşünüyorum.
Monadik kod için, (aslında veya neredeyse) monadik olan ve otomatik olarak determinist olarak tahrip edilmiş bir IORef türünü verebilecek başka bir çözüm var. İlke "iç içe geçme" eylemlerini tanımlamaktır. Birleştirildiğinde (bir ilişkisel işleç kullanarak) bunlar iç içe geçmiş bir kontrol akışını tanımlar - bence "XML elemanı", dış başlangıç ve bitiş etiketi çiftini sağlayan değerlerin en soluyla. Bu "XML etiketleri", başka bir soyutlama düzeyindeki monadik eylemlerin sırasını tanımlamaktadır.
Bir noktada (birleştirici kompozisyon zincirinin sağ tarafında) yuvalamayı sonlandırmak için bir tür sonlandırıcıya ihtiyacınız vardır - ortadaki deliği dolduracak bir şey. Bir sonlandırıcıya duyulan ihtiyaç, yuvalama kompozisyonu işlecinin monadik olmadığı anlamına gelmesidir, ancak yine de, ayrıntılarla çalışmadığımdan tam olarak emin değilim. Sonlandırıcının tüm uygulanması, bir yerleştirme eylemini etkili bir şekilde oluşturulmuş normal monadik eyleme dönüştürmek olduğundan, belki de değil - yerleştirme bileşimi işlecini mutlaka etkilemez.
Bu özel eylemlerin birçoğu boş bir "bitiş etiketi" basamağına sahip olacak ve "başlangıç etiketi" basamağını bazı basit monadik eylemlerle eşleştirecektir. Ancak bazıları değişken bildirimleri temsil eder. Bunlar kurucu ile başlama etiketini ve yıkıcı ile bitiş etiketini temsil eder. Demek böyle bir şey alıyorsun ...
act = terminate ((def-var "hello" ) >>>= \h ->
(def-var " world") >>>= \w ->
(use-val ((get h) ++ (get w)))
)
Aşağıdaki yürütme sırasına sahip bir monadik bileşime çeviri yapmak, her bir etiket (eleman değil) normal bir monadik eylem haline gelir ...
<def-var val="hello"> -- construction
<def-var val=" world> -- construction
<use-val ...>
<terminator/>
</use-val> -- do nothing
</def-val> -- destruction
</def-val> -- destruction
Bunun gibi kurallar, C ++ tarzı RAII'nin uygulanmasına izin verebilir. IORef'e benzeyen referanslar, normal IORef'lerin monaddan neden kaçamayacağına benzer nedenler nedeniyle, kapsamdan kaçamazlar - ilişkisel kompozisyonun kuralları referansın kaçmasına imkan vermez.
EDIT - neredeyse söylemeyi unuttum - burada emin olamadığım kesin bir alan var. Bir dış değişkenin bir iç değişkene referans verememesini sağlamak önemlidir, bu nedenle bu IORef benzeri referanslarla yapabilecekleriniz kısıtlamaları olmalıdır. Yine, tüm detayları üzerinde çalışmadım.
Bu nedenle, inşaat, örneğin yıkımın kapandığı bir dosyayı açabilir. İnşaat, yıkımın kapandığı bir soket açabilir. Temel olarak, C ++ 'da olduğu gibi, değişkenler kaynak yöneticisi olur. Ancak C ++ 'dan farklı olarak, otomatik olarak tahrip edilemeyen yığınla tahsis edilmiş nesneler yoktur.
Bu yapı RAII'yi desteklese de, hala bir çöp toplayıcısına ihtiyacınız var. Yuvalama eylemi belleği ayırabilir ve boşaltabilse de, kaynak olarak kabul etse de, bu bellek yığını içindeki ve başka yerlerdeki (potansiyel olarak paylaşılan) işlevsel değerlere ilişkin tüm referanslar hala vardır. Hafızanın yığın üzerinde basit bir şekilde tahsis edilebildiği ve bir yığın ücretsiz ihtiyacından kaçınılabileceği düşünüldüğünde, asıl önemi (eğer varsa) diğer kaynak yönetimi türleri içindir.
Öyleyse, bu başarının amacı RAII tarzı kaynak yönetimini bellek yönetiminden ayırmak, en azından RAII'nin basit yuvalama kapsamına dayanması durumunda. Bellek yönetimi için hala bir çöp toplayıcısına ihtiyacınız var, ancak diğer kaynakların güvenli ve zamanında otomatik olarak deterministik bir şekilde temizlenmesini sağlıyorsunuz.
shared_ptr<>
), yine de deterministik yıkımı sürdürüyorsunuz. RAII için zor olan bir şey döngüsel referanslardır; Sahiplik grafiği bir Yönlendirilmiş Asiklik Grafik ise RAII temiz çalışır.
C ++ 'ın işlevsel bir dil olduğunu düşünürseniz (lambdas'ı vardır), o zaman çöp toplama kullanılmayan bir dilin örneğidir.
Sorunun biraz kötü tanımlandığını söylemeliyim çünkü standart bir "fonksiyonel dil" koleksiyonu olduğunu varsayıyor. Hemen hemen her programlama dili, bir miktar işlevsel programlamayı destekler. Ve hemen hemen her programlama dili bir miktar zorunlu programlamayı destekler. Kültürel önyargılar ve popüler dogmanın rehberliğinde, hangisinin işlevsel bir dil olduğunu ve zorunlu bir dil olduğunu söyleme çizgisi nerede çiziliyor?
Soruyu ifade etmenin daha iyi bir yolu, "yığın destekli bellekte fonksiyonel programlamayı desteklemek mümkün mü" olacaktır. Cevap, daha önce de belirtildiği gibi çok zor. İşlevsel programlama stili, bir yığın bellek gerektiren özyinelemeli veri yapılarının tahsis edilmesini teşvik eder (çöp toplanır veya referans sayılır). Ancak, derleyicinin yığını yığın tahsisine benzer şekilde otomatik olarak tahsis edilip tahsis edilebilecek büyük bloklara bölebileceği bölge bazlı bellek analizi adı verilen oldukça karmaşık bir derleyici analiz tekniği vardır . Wikipedia sayfası, hem "işlevsel" hem de "zorunlu" diller için tekniğin çeşitli uygulamalarını listeler.