1 puan yazan GN⁺ 2024-10-18 | 1 yorum | WhatsApp'ta paylaş
  • Douglas Hofstadter’in 1983 tarihli yazısı, yapay zeka araştırmalarında yaygın olarak kullanılan Lisp’i küçük bir matematiksel çekirdek üzerine kurulmuş zarif ve esnek bir dil olarak tanıtıyor
  • Lisp’in etkileşimliliği read-eval-print loop içinde ortaya çıkar; kullanıcı bir ifade girdiğinde yorumlayıcı bunu okur, değerlendirir, çıktısını verir ve ardından bir sonraki girdiyi bekler
  • Lisp nesneleri esas olarak atom ve liste etrafında kurulur; nil ise hem boş liste hem de atom olmasıyla istisnai bir konuma sahiptir
  • quote, eval, car, cdr, cons, setq, set, lambda, def, cond; kod ile veriyi aynı liste yapısı içinde ele almayı mümkün kılar ve yeni işlevlerin kademeli olarak oluşturulmasına izin verir
  • İşlev bileşimi, koşul ifadeleri, yan etkiler ve applicative stil ile özyinelemeli düşünce örnekler üzerinden birbirine bağlanır; sondaki power işlevi ve “porpuquine” benzetmesi Lisp tarzı özyinelemeye işaret eder

Yapay zeka araştırmalarında Lisp’in yeri

  • 1983 itibarıyla yapay zeka; esneklik, sağduyu, içgörü, yaratıcılık, öz farkındalık ve mizah gibi davranışları bilgisayarda gerçekleştirmeyi amaçlayan bir araştırma alanıydı
  • ABD’de yapay zekayla profesyonel olarak ilgilenen yaklaşık 2 bin kişi vardı; yurtdışında da benzer ölçekte araştırmacı bulunuyordu
  • Yapay zeka araştırmacıları, yapay zekaya giden en iyi yol konusunda ciddi biçimde ayrışmış olsalar da, programlama dili seçiminde neredeyse ortak biçimde Lisp kullanıyordu
  • Lisp adı “list processing” ifadesinden gelir; tam anlamıyla bir kısaltma değildir
  • Lisp’in çekiciliği, “crisp” ve “elegant” bir dil olmasında yatar
    • Pek çok dil çok sayıda keyfi özelliği içine toplarken, Lisp ve Algol gibi bazı diller matematiğin bir dalı gibi doğal bir çekirdek etrafında kurulur
    • Lisp’in çekirdeği “crystalline purity” taşır; bu saflık yalnızca estetik duyguya değil, esnekliğe de katkı sağlar

Matematiksel mantıktan liste işleme diline

  • Lisp’in derin kökleri matematiksel mantık içindedir
    • Thoralf Skolem, Kurt Godel ve Alonzo Church’ün 1920’ler ve 1930’larda mantığa bıraktığı fikirler daha sonra Lisp’e dahil edildi
  • Asıl bilgisayar programlama 1940’larda başladı; Lisp gibi yüksek seviyeli diller ise 1950’lerde ortaya çıktı
  • İlk liste işleme dili Lisp değil, IPL (Information Processing Language) idi
    • IPL, 1950’lerin ortasında Herbert Simon, Allen Newell ve J. C. Shaw tarafından geliştirildi
  • John McCarthy, 1956–1958 arasında mevcut fikirler üzerine kurulu cebirsel bir liste işleme dili olarak Lisp’i yarattı
    • Lisp, MIT Artificial Intelligence Project çevresindeki genç araştırmacılar arasında hızla yayıldı
    • IBM 704 üzerinde gerçeklendi ve diğer yapay zeka gruplarına da yayıldı
    • Çeşitli lehçeleri ortaya çıktı ama zarif merkezî çekirdek ortak kaldı

Etkileşimli Lisp ve REPL

  • Lisp, birçok diğer yüksek seviyeli dilden farklı olarak etkileşimli bir dil olarak sunulur
  • Kullanıcı terminalde Lisp’i çalıştırır, istemi görür ve bir ifade girer
    • Örnek: (plus 2 2) girildiğinde 4 yazdırılır ve yeni bir istem görünür
  • Lisp yorumlayıcısının temel davranışı read-eval-print looptur
    • İfadeyi okur
    • İfadeyi değerlendirir
    • Uygun değeri yazdırır
    • Bir sonraki ifadeyi okumaya hazır olduğunu bildirir
  • Bu yapı sayesinde kullanıcı “dileklerini” birer birer girip sonucu hemen görebilir
  • Etkileşimli olmayan birçok dilde önce tüm programın yazılıp sonra çalıştırılması gerekir; bu da çok sayıda adımın kusursuz biçimde birbirine oturmasını gerektirir ve hata düzeltmeyi dolaylı, maliyetli bir sürece dönüştürür
  • Lisp, ifadeleri teker teker çalıştırma yaklaşımıyla kademeli geliştirme ve hata ayıklama olanağı sağlar

Polish notation ve parantezler

  • Lisp’in aritmetik ifadeleri, işlecin işlenenlerden önce geldiği Polish notation kullanır
    • Örnek: (times (plus 6 3) (difference 6 3)) ifadesi 27 olarak değerlendirilir
  • Bu gösterim, Polonyalı mantıkçı Jan Lukasiewicz’in bilgisayarlardan önce geliştirdiği bir notasyondur
  • Lisp ifadelerinde çok sayıda parantez bulunur
    • Uzun ifadelerin birkaç kapanış paranteziyle bitmesi olağandır
    • Başta göz korkutucu gelse de alışınca mantıksal yapı sezgisel biçimde görünür hale gelir
  • Örnekler, yapıyı girintilerle görünür kılan pretty printing biçiminde verilir

Atomlar, listeler, nil

  • Lisp’in özü, üzerinde işlem yapılabilen yapılardır; tüm programlar yapı kurarak, değiştirerek ve yok ederek çalışır
  • Yapılar iki türdür
    • Atom: daha fazla bölünemeyen temel nesne
    • Liste: birden çok öğenin belirli bir sırada toplandığı yapı
  • Tüm Lisp nesneleri ya atomdur ya da listedir; tek istisna **nil**dir
    • nil hem atomdur hem listedir
    • nil, boş listeyi temsil eder
    • () ile nil aynı anlama gelir, ama daha sık nil kullanılır
  • Bir listenin öğeleri atom da olabilir, liste de olabilir
    • Örnek: (zonk blee strill (croak flonk)) dört öğeli bir listedir; son öğe ayrıca iki öğeli başka bir listedir
  • Lisp cümlelerinin kendisi de listedir
    • (plus 2 2) de bir listedir
    • Lisp yorumlayıcısı listeleri ve atomları işleyerek yeni “komutlar” üretebilir ve değerlendirebilir

Değerler, quote, eval

  • Atomlar bir değere sahip olabilir
    • Sayı atomlarının kalıcı değeri kendileridir
    • nilin değeri nildir
    • t de kalıcı değeri kendisi olan özel bir atomdur
  • setq, bir atoma değer atar
    • (setq pie 4) ifadesi pie değerini 4 yapar
    • (setq pie (plus 2 2)) ifadesi de pie değerini 4 yapar
  • Bir atomun değeri yalnızca sayı değil, herhangi bir Lisp nesnesi olabilir
    • Atom da olabilir, liste de olabilir
  • quote, değerlendirmeyi engeller ve bir liste ya da atomun doğrudan veri olarak ele alınmasını sağlar
    • (setq pie (plus 2 2)) içteki ifadeyi değerlendirip pie içine 4 koyar
    • (setq pi '(plus 2 2)) ise listenin kendisini, yani (plus 2 2) ifadesini pi içine koyar
  • eval, değer olarak saklanmış ifadeyi yeniden değerlendirir
    • pi değerinin (plus 2 2) olması durumunda (eval pi) 4 döndürür
    • Yorumlayıcı normalde yalnızca bir adım değerlendirir; eval ile ek değerlendirme istenebilir

car, cdr, cons

  • nil dışındaki her liste en az bir öğe içerir ve ilk öğesine car denir
    • (eval pi) ifadesinin carı evaldir
    • (plus 2 2) ifadesinin carı plustır
  • car’ın mutlaka bir işlev adı olması gerekmez
    • ((1)(2 2) (3 3 3)) ifadesinin carı (1)dir
  • car çıkarıldığında geride kalan listeye cdr denir
    • (a b c d) ifadesinin cdrı (b c d)dir
    • Ardından (c d), (d), nil olarak küçülür
  • nil için ne car ne cdr vardır; car ya da cdr alınmaya çalışılırsa hata vermelidir
  • cons, mevcut bir listenin önüne yeni bir car ekleyerek yeni bir liste oluşturur
    • x değeri (cake cookie) iken (cons 'pie x) ifadesi (pie cake cookie) üretir
    • Bu sırada mevcut x değişmez
  • quote kullanılıp kullanılmamasına göre sonuç değişir
    • pie değeri 4 ise (cons pie x) ifadesi (4 cake cookie) döndürür
    • (cons 'pie x) ise atom adı olan pieyi başa ekler

setq ile set arasındaki fark

  • Lisp yorumlayıcısı her zaman argümanları değerlendirmez; setq bunun başlıca istisnalarından biridir
  • setq içindeki ilk argüman değerlendirilmez, doğrudan değişken adı olarak ele alınır
    • setq içindeki q, quote anlamına gelir; yani ilk argüman sanki alıntılanmış gibi işlenir
  • set, setqya benzer ama ilk argümanı da değerlendirir
    • x değeri k iken (set x 7) ifadesi xi değil, knın değerini 7 yapar
  • Örnek olarak şu sıra verilir
    • (setq a 'b)
    • (setq b 'c)
    • (setq c 'a)
    • (set a c)
    • (set c b)
  • Bunun ardından a, b, c değerlerinin üçü de a olur
  • set yaygın kullanılmaz; bu tür karışıklıklar da sık yaşanmaz

İşlev tanımı ve lambda

  • Programlamanın büyük gücü, mevcut işlemlerden yeni bileşik işlemler tanımlamakta ve bunu tekrar ederek giderek daha karmaşık bir işlem repertuvarı oluşturmaktadır
  • Lisp’te yeni işlevler, zaten bilinen işlevler kullanılarak tanımlanır
  • rac, bir listenin son öğesini döndüren örnek bir işlevdir
    • Son öğeyi almak için liste ters çevrilir ve ardından car alınır
    • Tanım: (def rac (lambda (lyst) (car (reverse lyst))))
  • lambda sonrasındaki (lyst), işlevin parametresini yani kukla değişkenini gösterir
  • def ile tanımlandıktan sonra rac, car gibi kullanılabilen bir işlev haline gelir
    • (rac '(your brains)) ifadesi brains döndürür
  • readers-digest-condensed-version adlı işlev, uzun bir listeden yalnızca ilk ve son öğeyi içeren kısa bir liste üretir
    • James Joyce’un Finnegans Wake eserinin tamamı bir sözcük listesi kabul edildiğinde (riverrun the) sonucunun elde edildiği örneği verilir
  • rejoyce adlı ters işlem ise başı ve sonu iki sözcükle belirlenmiş bir roman üreten hayalî bir işlevdir; yazımı okura alıştırma olarak bırakılır

Değer döndürme, yan etkiler, applicative stil

  • Bazı insanlar Lisp ve ilgili dillerde iki hedefin hem arzu edilir hem de mümkün olduğunu düşünür
    • Her cümle bir değer döndürmelidir
    • Cümlelerin etkisi yalnızca döndürdükleri değerler aracılığıyla ortaya çıkmalıdır
  • Yazıda ele alınan Lisp lehçeleri ilk koşulu sağlar ama ikinci koşulu zorunlu olarak sağlamaz
  • (reverse x), xin kendisini değiştirmez; onunla aynı ama sırası ters çevrilmiş yeni bir liste üretip döndürür
    • Bu, (plus 2 2) ifadesinin 2’nin değerini değiştirmemesiyle aynı mantıktadır
  • cons da mevcut listeyi değiştirmez, yeni bir liste döndürür
  • Buna karşılık setq, değişken bağını değiştiren bir yan etki bırakan komut örneğidir
    • Yan etkiler, değişken bağlarının değişmesi dışında girdi/çıktıyı da içerebilir
  • Applicative programlamayı savunanlar, yan etki olmadan işlevlerin değer hesaplayıp aktardığı yaklaşımı tercih eder
  • Bu stilde izin verilen bağlar, işlev çağrısı sırasında geçici olarak oluşan lambda bindingdir
    • İşlev hesabı tamamlandığında kukla değişkenin bağı kaybolur
  • Yazının anlatıcısı applicative stili zarif bulsa da, büyük yapay zeka tarzı programlar kurarken pratik olmadığını düşünür
  • Katı applicative programlamada, kalıcı işlev tanımını belleğe yazdığı için def bile izin verilmeyen uç bir örnek sayılır

Koşul ifadesi cond ve karar verme

  • Lisp’in daha ilginç işler yapabilmesi için ara aşamalarda olan bitene göre karar verebilmesi gerekir; bunun için koşul ifadesi gerekir
  • Örnek: (cond ((eq x 1) 'land) ((eq x 2) 'sea))
    • x 1 ise land
    • x 2 ise sea
    • Bunların dışında nil döndürür
  • eq, iki argümanın değeri aynıysa t, farklıysa nil döndüren bir Lisp işlevdir
  • cond ifadesi, cond adlı işlev adıyla başlar ve birden çok madde içerir
    • Her madde, koşul ve sonuçtan oluşan iki öğeli bir listedir
    • Koşullar sırayla sınanır; nil dışında bir değer döndüren ilk koşul bulunduğunda, onun sonucu değerlendirilir ve tüm cond ifadesinin değeri olarak döndürülür
    • Sonraki maddeler artık sınanmaz
  • Sona koşul olarak t konan bir catch-all madde eklenirse, nil yerine varsayılan sonuç döndürülebilir
    • Örnek olarak, hem land hem sea koşulları başarısız olursa air döndüren bir cond verilir

Kuvvet ve özyinelemeli yapı

  • Yazının sonunda belirgin bir örüntü taşıyan işlev tanımları gelir
    • square, k * kdir
    • cube, k * square(k)dir
    • 4th-power, k * cube(k)dir
    • Ve aynı biçimde devam eder
  • Bu örüntünün tamamını bir kerede kapsayan iki parametreli power işlevinin tanımlanıp tanımlanamayacağı soru olarak ortaya konur
    • (power 9 3) 729 olmalıdır
    • (power 7 4) ise 2,401 döndürmelidir
  • Gerekli araçların tümü metin içinde verilmiştir; gerisi okurun zekasına bırakılır
  • Sondaki Glazunkian porpuquine hikâyesi, özyinelemeli yapıyı alegorik biçimde ele alır
    • Porpuquine’in dikenleri daha küçük porpuquine’lerdir
    • Outer Glazunkia’da daima 9, Inner Glazunkia’da daima 7 diken bulunur
    • 0 inçlik porpuquine’de diken olmadığı için sonsuz gerileme durur
  • Bu hayvanın “buying power”ı ya da “power”ı, içinde yer alan küçük 0 inçlik porpuquine burunlarının sayısıyla ilişkilendirilir ve anlatı daha önce verilen power problemiyle bağlantılı bir benzetmeyle sona erer

Orijinal metnin yeniden paylaşım bağlamı

  • Gist’in baş kısmı, bu yazının Douglas Hofstadter’in 1980’lerin ortalarında Scientific American eski sayılarında rastlanan Lisp tanıtım yazısı olduğunu belirtir
  • Örnekler, Emacs içinde birkaç takma ad kurulursa hâlâ çalıştırılabilir
    • plus+
    • quotient/
    • times*
    • difference-
  • Son bölüm, Hofstadter’in bu kendine özgü Lisp rehberinden hoşlananların, benzer yazıları Metamagical Themas kitabında da bulabileceğini söyler

1 yorum

 
GN⁺ 2024-10-18
Hacker News yorumları
  • Örnekteki "oval" ve "snot" fonksiyon adları kafamı karıştırdı; birkaç saniye sonra bunların sırasıyla "eval" ve "snoc" yazım hataları olduğunu fark ettim.
    Asıl kod (cond ((eq (eval pi) pie) (eval (snoc pie pi))) (t (eval (snoc (rac pi) pi)))) şeklinde okunmalı.
    https://www.jstor.org/stable/24968822 adresinden özgün Scientific American yazısını indirip kontrol edince, gerçekten de oval/snotın eval/snoc için yazım hatası olduğunu gördüm.

    • Düzeltmenin düzeltmesi: "oval" ve "snot", gerçekten "eval" ve "snoc" yazım hatası.
      Ayrıca snoc, ters çevrilmiş cons; rac de ters çevrilmiş car gibi görünüyor.
    • OCR hatası da olabilir.
  • Bu yazı, Lisp'in popülerliğinin zayıf kalmasının temel nedeninin Lisp'in anlatılma biçimi olduğunu yeniden gösteriyor.
    Bu tür Lisp yazıları, çocukluğumdaki bana gerçekten kullanabileceğim hiçbir şey öğretmiyor; Assembly/C/Pascal vb. ile karşılaştırıldığında herhangi bir X işini ne kadar kolaylaştırdığını da göstermiyordu.
    Şimdiki ben olsam, “Assembly ile 7 ay süren bir yazım denetleyici mi? Bank-switching bellek kullanan bir mikrobilgisayarda Lisp ile bu neredeyse önemsiz bir iş; çöp toplama da berbat bir CPU'da deterministik hâle getirilebilir” diye gösterirdim.
    Sayısız Lisp yazısı ve ders kitabı sadece listeleri, özyinelemeyi ve yapay zekayı tekrarlayıp durdu; yararlı bir şeyin nasıl yapılacağını göstermediği için, cımbız, pirinç tanesi ve tutkalla program yazmışım gibi geçen zamana üzülüyorum.

    • Common Lisp: A Gentle Introduction to Symbolic Computation bu bağlamda yararlı olabilir: https://www.cs.cmu.edu/~dst/LispBook/
    • Practical Common Lisp de var: https://gigamonkeys.com/book/
    • Hofstadter'in devam yazılarında daha ilginç örnekler vardı.
      Çocukken ilk gördüğüm Byte dergisinde, Lisp ile yazılmış sembolik türev alma ve cebirsel sadeleştirme kodu vardı; takip etmesi zordu ama bir şekilde çekici gelmişti.
      Basic ile daha kolay olmasına imkân yoktu; sonradan o kodun çok da iyi olmadığını gördüm, ama 80'lerin sonlarında PC'de XLisp ve SICP ile tanıştıktan sonra Lisp'e gerçekten kapıldım.
  • Hofstadter'in yazı üslubunu gerçekten seviyorum. Lisp'i keşfettiğimde hissettiklerimi iyi yakalıyor.
    80'lerde programlama öğrenen bir çocuktum; lise ve üniversitenin başlarında BASIC, Fortran, Pascal, COBOL'u zaten biraz denemiştim. Aralarında farklar vardı ama temelde ortak yanları bulunuyordu.
    Fakat UC Berkeley'deki ilk bilgisayar bilimi dersim, bir Lisp lehçesi olan Scheme ile yürütüldü ve bu tamamen sarsıcıydı.
    Hofstadter'in dediği gibi, matematiğe en yakın şey gibi hissettiriyordu; bana sık sık matematik kuramı derslerini hatırlatıyordu ve keşfettiğim ilk güzel dildi.
    “Lisp ve Algol, matematiğin bir dalı gibi doğal bir çekirdek etrafında inşa edilmiştir. Lisp'in çekirdeğinde, yalnızca estetik duyguya hitap etmekle kalmayıp onu çoğu dilden çok daha esnek kılan kristal gibi bir saflık vardır” alıntısını özellikle sevmiştim.

    • Haskell kullanıp kullanmadığını merak ediyorum. Bana göre prosedürlerden değil tanımlardan oluştuğu için matematiğe çok daha yakın hissettiriyor; dış görünüşü de matematik gibi duruyor.
    • Konudan biraz sapma riski var ama buna “matematik” demenin meseleyi biraz bulanıklaştırabileceğini düşünüyorum.
      Cebirsel topolog olmak istemiş biri olarak bile Scheme, dinamik tipler ve çöp toplama kullanan dillerin geneline yayılmış programlama stilinin zarif ve minimal bir ifadesine daha yakın.
      Tamamlanmış gibi görünmesi ve Scheme ile bir problem çözme biçimini düşünüp sonra bunu başka dinamik tipli dillere taşıdığınızda da zarif çözümlere ulaşabilmeniz anlamında “teori” gibi hissettiriyor.
      Scheme, o dönemin geleneksel Lisp'ine kıyasla leksik kapsam, fonksiyonlar ve değişkenler için tek ad alanı gibi yönlerde sadeleştirilmiş ve toparlanmış bir dildi.
  • 1983, bu alanın başlamasından yaklaşık 20 yıl sonrasına denk geliyor; yazı ise bilgisayarları “esneklik, sağduyu, içgörü, yaratıcılık, öz farkındalık, mizah” sahibi olacak şekilde programlamaktan söz ediyor.
    Bu listenin LLM'lerin gerçekten beceremediği şeylerin listesi gibi okunması epey ilginç.
    Yine de en azından o yönde sıfır olmayan bir ilerleme kaydedilmiş sayılır.

    • Karşılaştığım sıradan insanlarla kıyasladığımda LLM'ler sağduyu, içgörü, yaratıcılık, öz farkındalık ve mizahı ortalama bir insan kadar gösteriyor gibi geldi.
      Belki daha fazlasını bile gösterdiklerini hissediyorum; ama böyle söyleyince kulağıma bile biraz tuhaf geliyor.
    • Hofstadter'in araştırma grubunun bu tür sorunlarla uğraşma konusunda uzun bir geçmişi var.
      Çoğu henüz sonuca dönüşmemiş olsa da okumaya değer derecede ilginç.
  • Bu yazıyla birlikte anılan iki eşlikçi yazı, Hofstadter'in Metamagical Themas kitabının 17-19. bölümlerinde yer alıyor; Scientific American'daki aynı dizide yayımlanan diğer yazılar da kitapta bulunuyor.
    [0]: https://www.goodreads.com/book/show/181239.Metamagical_Thema...
    Kitabın başlığı, Martin Gardner'ın Scientific American'da yazdığı “Mathematical Games”in anagramından gelen köşe başlığından türemiş; Hofstadter o köşeyi devralmıştı.

    • Bu kitabı gerçekten seviyorum. Hofstadter'in klasiği Gödel, Escher, Bach'ı sevenlere şiddetle tavsiye ederim.
    • Bu kitap hem okuması hem bakması gerçekten güzel; çok sayıda ilginç illüstrasyon içeriyor.
  • Yazıda nil üzerine car ya da cdr uygulanırsa, sıfıra bölme gibi hata vermesi gerektiği söyleniyor; ancak modern Lisp’te çoğu zaman artık böyle değil
    John McCarthy’nin tanımladığı özgün Lisp’te CAR ve CDR, NIL için tanımlı değildi: <https://dl.acm.org/doi/pdf/10.1145/367177.367199>
    Ancak Common Lisp ve Emacs Lisp, (car nil) ile (cdr nil) ifadelerini nil olarak tanımlar: <https://www.lispworks.com/documentation/HyperSpec/Body/f_car...>, <https://www.gnu.org/software/emacs/manual/html_node/elisp/Li...>

    • Maclisp’te durumun nasıl olduğunu merak edip Lars Brinkhoff’un halka açık ITS’ine telnet ile bağlanarak kontrol ettim
      LISP 2156 içinde (status lispversion) /2156 döndürdü; (car nil) ve (cdr nil) ise ikisi de NIL döndürdü
    • Matematiksel olarak tasarlanmış bir dilin doğuşunda car ve cdr gibi son derece somut uygulama ayrıntılarının merkeze yerleşmiş olması şaşırtıcı
      “List Processor”ın en temel ve en ünlü operatörleri aslında listeler üzerinde değil, Lisp’in veri yapıları oluştururken kullandığı belirli bir makine temsili öğesi olan cons üzerinde çalışacak şekilde tasarlanmıştı
      cons her zaman liste olarak yorumlanmaz; liste özyinelemeli fonksiyonların temel durumu olan çok önemli liste de cons ile temsil edilmez
      60 yıl sonra bile Lisp programlarının çoğu cons işlemleriyle dolu ve belki de daha doğru ad “Cons Processor” olurdu
      Bu, Lisp’in dil ile uygulamanın iç içe geçmek zorunda olduğu bir dönemde doğduğunu hatırlatıyor; bu yüzden bir bilgisayar dilini matematiksel mantığa dayandırma başarısı daha da şaşırtıcı geliyor
    • Scheme’de durum böyle değil. nilin CAR ya da CDRını almak hatadır
    • Ne yazık ki Scheme’de nilin car/cdrı hata olduğu için, benim gibi yeni başlayanlara kod epey ergonomik olmayan bir his veriyor
      Yine de Guile Scheme’i Common Lisp’e tercih ettiğim için bu durum üzücü
    • nile bir şey uygulandığında hata vermeden tekrar nil döndüren bu dil tasarımı tercihinin bir adı olup olmadığını merak ediyorum
      SQL de akla geliyor; kişisel olarak bunun iyi bir tercih olmadığını düşündüğümden, başka bir adı yoksa buna “bleeding nils/NULLs” demek isterim
      Özellikle nil, boolean karşılaştırmalarda false ile aynı değilse daha da kötü
      Ruby ve Elixir’de nil, false gibi ele alınır; Elixir ise yalnızca saf boolean kabul eden and ile nili false sayan && operatörlerini ayrı ayrı sunar
      Bu tür bir tasarım başta kodu temiz gösterebilir; ancak aslında hata olan, yanlış işlenmiş bir nil, birçok çağrı yığınının ardından bambaşka bir yerde ortaya çıkıp hata ayıklamayı çok daha zorlaştırabilir
  • Bu yazıdaki Lisp bilgilerini zaten biliyordum ama yine de keyifle okudum. Hofstadter’ın dil tadı gerçekten çok çekici
    Özellikle readers-digest-condensed-versionın ters işlemi olan rejoyceu icat edip, (rejoyce 'Stately 'Yes) çalıştırıldığında Lisp perisinin James Joyce’un yazmış olabileceği Ulysses’in tamamını baştan ürettiği şakası hoşuma gitti
    Biraz zaman aldı ama sonunda o noktaya ulaştık sayılır; 2024’ün yapay zekası, onun 1983’te hayal ettiği şeyle tamamen aynı olmasa da, kısa bir tohumdan metni yeniden üretmek bugün yapay zekaya oldukça uygun bir iş

  • Lisp’in, Hofstadter’ın ele aldığı tuhaf döngü kavramını ifade edebilen başlıca dillerden biri olarak hâlâ yerini koruduğunu düşünüyorum
    Lisp homoykonik olan tek dil değil, ama insanların gerçekten kullanmayı bildiği diller arasında eval’in ayrıştırması gereken bir metin dizgesi almayan en büyük eksenlerden birine ait
    İnsanların Lisp’i doğrudan fonksiyonel programlamanın tamamıyla özdeşleştirmesinden hoşlanmıyorum
    Fonksiyonel programlamadan hoşlanmıyor değilim, ama Lisp’in sembolik niteliği çok daha ilginç; ayrıca (go tag) bölümleriyle çalışan kod üretip GOTO tarzı programlamayı da çok kolay yapabilmek bana bitmek bilmeyen bir eğlence gibi geliyor

    • 2000’lerde kısa bir süre ana akım benimsenme yaşayan, gerçekten fonksiyonel bir başka homoykonik dil de XSLT idi
      XSLT ve XML kullanarak, tekrarlı kodu elle yazmak yerine XSLT üreten türden metaprogramlama özellikleri epey yaygın kullanıldı
      Ancak sözdizimi Lisp sözdiziminden de daha büyük bir sorundu
      Hem gündelik kullanım için iyi bir sözdizimine sahip olan hem de soyut sözdizim ağacı olarak ele alınması fazla zahmetli olmayan bir dil yapmak kolay değil; Lisp bunun görece başarılı az sayıdaki örneğinden biri
    • Özellikle Scheme’in devamlılık tabanlı programlamasına kadar gidildiğinde, fonksiyonel ve fonksiyonel olmayan programlama arasındaki sınır neredeyse anlamsızlaşacak kadar bulanıklaşıyor
    • 2024’te bir programcının Lisp’ten elde ettiği, Python’ın functools’u ile pek yapılamayan derin düzeydeki homoykonik/sembolik destek gerçekten nedir merak ediyorum: https://docs.python.org/3/library/functools.html
      Lisp olmadan sembolik AGI geliştiriyorum; uzmanlardan ipuçları duymak isterim
      Python tarafında anladığım özellikler; filter(), map(), reduce() gibi başka fonksiyonları yinelenebilir nesnelere uygulayan fonksiyonlar, @singledispatch gibi çağrıları yönlendiren sarmalayıcılar, @cache ve partial() gibi akış denetimi ya da performans kolaylığı sağlayan fonksiyonlar, wraps() gibi fonksiyonları keyfî biçimde sarmalama imkânı civarında
      Bunların çoğu, fonksiyonları alışılmadık şekillerde çağırmaya yarayan kolaylıklar gibi görünüyor ve “öz-yansıtma”yı birinci sınıf bir mesele gibi ele alan Lisp övgülerinin düzeyine ulaşmıyor sanki
      Bu özelliklerde olmayan neyi Lisp’in gerçekten sağladığını bilmek istiyorum
    • Birçok insanın Lisp’le yalnızca akademi üzerinden karşılaşması ve Lisp öğreten akademisyenlerin Lisp ile gerçekten bir şey geliştirmeye pek ilgi duymaması da bunda etkili
      Onlar Lisp’i kavram aktarma aracı olarak kullanıyor; bu kavramlar da genellikle fonksiyonel özyineleme etrafında dönüyor
      Scheme ve çevresindeki kültürün de payı var
      Scheme yalnızca fonksiyonel bir dil olmasa da önceki Lisp ailelerine göre saf programlamayı daha fazla vurgular; temel dil, yineleme yapıları yerine kuyruk özyineleme yapıları sunar ve uygulamalardan kuyruk çağrısı optimizasyonu ister
  • Common Lisp’te de defalias bir makro olarak tanımlanırsa Emacs’in defalias’ı gibi kullanılabilir: https://stackoverflow.com/questions/24252539/defining-aliase...

  • Metamagical Themas’ta yer alan Hofstadter’ın Lisp yazısını sevmiştim; o serinin son yazısındaki kodu da iş yerindeki çalışma grubu için Clojure’a uyarlayıp düzenlemiştim
    [1] http://johnj.com/posts/oodles/

    • Modern Lisp’e uyarlanmış bir çevirisi olup olmadığını da merak ediyorum