StackOverflow ve bu sitede belirsiz "Scheme vs Common LISP" soru sıkıntısı yoktur, bu yüzden bu bir daha odaklanmış yapmak istiyorum. Soru her iki dilde de kod yazmış kişiler içindir:
Mutlaka sadece dil özellikleri demek istemiyorum. Soru ile ilgili olarak aşağıdakilerin kaçırılması gereken geçerli şeyler şunlardır:
Beklediğim cevap türlerine örnekler:
Bu yüzden, "Şema daha basit bir dildir" vb. Genel düşüncelerden ziyade savaş hikayeleri bekliyorum.
Lisans derecem Bilişsel Bilimler ve Yapay Zeka idi. Bundan sonra LISP'e tek derslik bir giriş yaptım. Dilin ilginç olduğunu düşündüm ("zarif" te olduğu gibi), ancak Greenspun'un Onuncu Kuralına çok geç gelene kadar çok fazla düşünmedim:
Yeterince karmaşık olan herhangi bir C veya Fortran programı, Ortak LISP'nin yarısının geçici, gayri resmi olarak belirtilmiş, hata basmış, yavaş bir uygulamasını içerir.
Greenspun'un amacı (kısmen) birçok karmaşık programın dahili tercümanlara sahip olmasıdır. Bir tercümanı bir dile inşa etmek yerine, önceden bir tercüman (veya derleyici) bulunan LISP gibi bir dil kullanmanın daha anlamlı olabileceğini önerdi.
O zamanlar, özel bir dil için özel bir yorumlayıcı kullanarak kullanıcı tanımlı hesaplamalar yapan oldukça büyük bir uygulama üzerinde çalışıyordum. LISP'deki çekirdeğini büyük ölçekli bir deney olarak yeniden yazmaya karar verdim.
Yaklaşık altı hafta sürdü. Orijinal kod yaklaşık 100.000 satırlık Delphi (Pascal varyantı) idi. LISP'de bu ~ 10.000 satıra indirildi. Yine de daha şaşırtıcı olan, LISP motorunun 3-6 kat daha hızlı olmasıydı. Ve bunun bir LISP neofitinin işi olduğunu unutmayın! Tüm bu deneyim benim için göz açıcıydı; ilk kez performans ve ifadeyi tek bir dilde birleştirme olanağını gördüm.
Bir süre sonra web tabanlı bir proje üzerinde çalışmaya başladığımda bir dizi dili seçtim. LISP ve Şemayı karışıma dahil ettim. Sonunda bir Şema uygulaması seçtim -- Chez Şeması . Sonuçlardan çok memnun kaldım.
Web tabanlı proje yüksek performanslı bir "seçim motoru" . Şemayı, veri işlemeden veri sorgulamaya ve sayfa oluşturmaya kadar birçok farklı şekilde kullanıyoruz. Birçok noktada aslında farklı bir dil ile başladık, ancak aşağıda kısaca anlatacağım nedenlerden dolayı Şemaya göç ettik.
Şimdi sorunuza cevap verebilirim (en azından kısmen).
Seçmeler sırasında çeşitli LISP ve Scheme uygulamalarına baktık. LISP tarafında Allegro CL, CMUCL, SBCL ve LispWorks'e baktık (inanıyorum). Şema tarafında Bigloo, Tavuk, Chez, Gambit'e (inanıyorum) baktık. (Dil seçimi uzun zaman önceydi; bu yüzden biraz pusluyum. Önemliyse bazı notlar çıkarabilirim.)
Yarasadan hemen sonra a) yerli iş parçacıkları ve b) Linux, Mac ve Windows desteği arıyorduk. Bu iki koşul birlikte Allegro ve Chez hariç herkesi çaldı - değerlendirmeye devam edebilmek için çok iş parçacığı gereksinimini gevşetmek zorunda kaldık.
Bir dizi küçük program oluşturduk ve bunları değerlendirme ve test için kullandık. Bu bir takım sorunları ortaya çıkardı. Örneğin: bazı uygulamalarda bazı testlerin tamamlanmasını tamamlayan hatalar vardı; bazı uygulamalar çalışma zamanında kod derleyemedi; bazı uygulamalar, çalışma zamanı derlenmiş kodunu önceden derlenmiş kodla kolayca entegre edemedi; bazı uygulamalarda, diğerlerinden açıkça daha iyi (veya açıkça daha kötü) çöp toplayıcıları vardı; vb.
İhtiyaçlarımız için sadece üç ticari uygulama - Allegro, Chez ve Lispworks - birincil testlerimizi geçti. Sadece üçü Chez tüm testleri uçan renklerle geçti. O zamanlar Lispworks'ün herhangi bir platformda yerel iş parçacığı olmadığını düşünüyorum (sanırım şimdi yapıyorlar) ve Allegro'nun bazı platformlarda sadece yerel iş parçacıkları olduğunu düşünüyorum. Dahası, Allegro'nun çok sevmediğim bir "bizi arayın" çalışma zamanı lisans ücreti vardı. Lispworks'ün çalışma zamanı ücreti olmadığına ve Chez'in basit (ve çok makul) bir düzenlemeye sahip olduğuna inanıyorum (ve yalnızca derleyiciyi çalışma zamanında kullandıysanız başladı).
Hem LISP hem de Şemada biraz önemli kod parçaları üretmiş olan bazı karşılaştırma ve kontrast noktaları şunlardır:
LISP ortamları çok daha olgunlaşır. Kova için çok daha fazla patlama elde edersiniz. (Bunu söyledikten sonra, daha fazla kod aynı zamanda daha fazla hataya eşittir.)
LISP ortamlarını öğrenmek çok daha zordur. Yetkin olmak için çok daha fazla zamana ihtiyacınız var; Ortak LISP büyük bir dildir - ve bu, ticari uygulamaların üzerine eklediği kütüphanelere gitmeden önce. (Şema'nın sözdizimi vakasının LISP'deki herhangi bir şeyden çok daha ince ve karmaşık olduğunu söylemiştik.)
LISP ortamları, ikili dosyalar üretmek için biraz daha zor olabilir. Gereksiz bitleri kaldırmak için görüntünüzü "sallamanız" gerekir ve bu işlem sırasında programınızı doğru şekilde kullanmazsanız, daha sonra çalışma zamanı hatalarıyla karşılaşabilirsiniz. . Buna karşılık, Chez ile ihtiyaç duyduğu diğer tüm dosyaları içeren üst düzey bir dosya derliyoruz ve işimiz bitti.
Daha önce, başlangıçta niyetinde olmadığımız birkaç yerde Şema'yı kullandığımızı söyledim. Neden? Başımın üstünden üç sebep düşünebilirim.
İlk olarak, Chez'e (ve geliştiricisi Cadence) güvenmeyi öğrendik. Araçtan çok şey sorduk ve sürekli olarak teslim edildi. Örneğin, Chez tarihsel olarak çok az sayıda kusura sahipti ve bellek yöneticisi çok, çok iyi oldu.
İkincisi, Chez'den aldığımız performansı sevmeyi öğrendik. Komut dosyası dili gibi hissettiren bir şey kullanıyorduk - ve ondan yerel kod hızı alıyorduk. Önemli olmayan bazı şeyler için - ama asla acıtmadı ve bazen çok fazla yardımcı oldu.
Üçüncüsü, Şema'nın sağlayabileceği soyutlamayı sevmeyi öğrendik. Bu arada sadece makrolardan bahsetmiyorum; Kapanışlar, lambdalar, kuyruk çağrıları, vb.
Şema mükemmel mi? Hayır; bir değiş tokuş. Birincisi, bireysel geliştiricilerin daha etkili olmasına izin verir - ancak geliştiricilerin birbirlerinin kodlarını almaları daha zordur, çünkü çoğu dilin sahip olduğu tabelalar (örneğin, döngüler için) Şemada eksiktir (örneğin, bir milyon yol vardır) a için döngü). İkincisi, konuşmak, kiralamak, ödünç almak vb. İçin çok daha küçük bir geliştirici havuzu var.
Özetlemek gerekirse, şunu söyleyebilirim: LISP ve Scheme başka hiçbir yerde bulunmayan bazı yetenekler sunuyor. Bu yetenek bir değiş tokuştur, bu yüzden sizin durumunuzda mantıklı olan daha iyi olmalıydı. Bizim durumumuzda, LISP veya Scheme ile gidip gitmeme arasındaki belirleyici faktörlerin, dil veya kütüphane özellikleri ile olduğundan çok temel özelliklerle (platform desteği, platform iş parçacıkları, çalışma zamanı derlemesi, çalışma zamanı lisanslama) daha fazla ilgisi vardı. Yine, bizim durumumuzda da bir değiş tokuş vardı: Chez ile istediğimiz temel özelliklere sahibiz, ancak ticari LISP ortamlarının sahip olduğu geniş kütüphaneleri kaybettik.
Ayrıca, sadece tekrarlamak için: uzun zaman önce çeşitli Lisps ve Şemalarına baktık; o zamandan beri hepsi gelişti ve gelişti.
Genellikle bir bağlantıyı cevap olarak yapıştırmaktan hoşlanmam, ancak bu konuda bir blog makalesi yazdım. Kapsamlı değil, ancak bazı önemli noktaları ele alıyor.
Düzenle: Temel noktalar şunlardır:
TERPRI,
PROGNvb. Şema genellikle çok mantıklı isimlere sahip. Bu CL'de kaçırılan bir şey.
list" ila "
lst" gibi adları karıştırmanız gerekir.
syntax-rulesgerçekten bazı şeyleri kesmek istiyorum kadar iyi ve züppe. Öte yandan, hijyenik makrolar bazen CL'de gözden kaçırılır. Bunları yapmak için standart bir yol olmaması, tekerleği yeniden icat etmek anlamına gelir.
Ben sadece biraz yukarıda birinci kişiyle konuştuğum halde, neyi özlediğimi ve neyi özlemediğimi netleştirmeliyim.
[Bunlar çok genelse özür dilerim. Görünüşe göre çok daha ayrıntılı bilgi isteyebilirsiniz. Yayında bazı özellikler var.]
Kısa bir süre önce C sürümü ve Java sürümü olan bir kütüphane kullanarak bir ev projesi başlattım. Proje için LISP kullanmak istedim ve Common LISP, Scheme kullanma arasında yaklaşık bir ay boş zaman harcadım Ya da üçünde de biraz deneyime sahibim, ama sadece oyuncak projelerimde.
PLT Raketi, yalnızca editörden gelen ifadeleri değerlendirmenize izin vermekle kalmaz, aynı zamanda parantezler yerine parantezler yazmanıza ve uygun olan yerlerde parenlere geri döndürmenize izin veren bir Nice IDE) içerir. yükleme ile kütüphane ve daha da indirilebilir .. Görsel hata ayıklayıcı da yararlıdır.
Ortak LISP uygulamamın (SBCL) bir IDE'si yok, ancak Emacs ve SLIME kullanmak için açık kaynaklı CL uygulamaları ile alışılmış. Bu kombinasyon çok verimli olabilir. İfadeleri kaynak dosyaya yazarken değerlendirme özelliğinin yanı sıra, emac'lerin tüm düzenleme komutlarını içeren bir REPL) vardır, böylece kod kopyalama her iki yönde de verimli bir şekilde gidebilir. REPL arabelleğinde görüntülenen nesneler kopyalanabilir ve yapıştırılabilir.
Alt+( ve
Alt+) eşleşen parantez ve girinti ile uğraşmak için etkilidir.
Yukarıdaki Emacs özelliklerinin tümü Clojure için de mevcuttur. Clojure ile ilgili düzenleme deneyimim, LISP deneyimine benzer. Java birlikte çalışma iyi çalıştı ve olgunlaştığında bir Clojure projesi yapmak istiyorum.
Üçüne de (Common LISP, Racket ve Clojure) kullanarak kütüphaneye erişebildim, ancak proje için Common LISP'yi seçtim. Karar verici faktör, FFI'nın Ortak LISP'de kullanımının çok daha kolay olmasıdır. CFFI, örnek kod ve her yöntemin ayrıntılı açıklamalarıyla birlikte çok iyi bir el kitabına sahiptir. Bir öğleden sonra 20 C fonksiyonunu kapatabildim ve o zamandan beri koda dokunmak zorunda kalmadım.
Diğer faktör, Ortak LISP'yi Clojure veya R6RS Şemasına göre daha iyi tanımamdı. Pratik Ortak LISP ve Graham'ın kitaplarının çoğunu okudum ve Hyperspec ile rahatım. Henüz çok "lispy" kodu değil, ama daha fazla deneyim kazandıkça değişecektir eminim.
Hem CL'de hem de Rakette programlıyorum.
Şimdi Common LISP'de bir Web sitesi geliştiriyorum ve Racket'teki önceki işverenim için bir dizi kurum içi program yazdım.
Şirket içi kod için, işveren bir Windows mağazası olduğu için Racket'i (daha sonra PLT Şeması olarak bilinir) seçtim ve LispWorks için ödeme yapamadım. Windows için tek iyi açık kaynaklı CL uygulaması, SSE işlemcide destek gerektiren CCL) idi (ve hala da öyle). Taş Devri donanımı İşveren iyi bir donanıma sahip olsa bile, Common LISP'deki sonuçların tek GUI kütüphanesi sadece Unix üzerinde çalışan McCLIM'dir.Retet, Unix ve Windows üzerinde çalışan iyi bir GUI kütüphanesine sahiptir. projenin başarısı.
Bir yıldan fazla bir süredir ilkel DrRacket editörüne katıldım. EMACS, daha sonra MrEd olarak bilinen Racket'in GUI sürümünü Windows'ta daha düşük bir LISP'ye dönüştüremedi. Tek bir tuşa basarak imleçteki ifadeyi değerlendirmeden yapmam gerekiyordu. Bunun yerine, S-ifadesini el ile seçmek, kopyalamak, REPL penceresine (çünkü geçiş yapmak için herhangi bir tuş vuruşu olmadığından) tıklamak ve sonra S-ifadesini yapıştırmak zorunda kaldım. bana kullandığım işlevin veya makronun beklenen argümanlarını gösterebilecek bir editör olmadan yapmak zorundaydı DrRacket SLIME yerine geçmez.
İşveren, SELECT sorgusu sürümüne yanıt verebilmek için gereksiz görünen birçok bilgi gerektiren karmaşık bir XML API'sine sahip özel bir veritabanı kullanıyordu. HTMLPrag'ı hem bu API'ya XML yaymak hem de yanıtları ayrıştırmak için kullanmaya karar verdim. Harika çalıştı.
SQL gibi görünen formları yazarak aşırı karmaşık XML API ile etkileşime izin verecek bir makro yazmak için Racket'in aşırı karmaşık "sözdizimi-case" makro sistemini öğrenmek zorunda kaldım. Elimde DEFMACRO olsaydı bu kısım çok daha kolay olurdu. Bununla birlikte, sonuç elde etmek için daha fazla çaba harcanmasına rağmen hala sorunsuzdu.
Ayrıca, Common LISP'in LOOP makrosu olmadan yapmak zorunda kaldım. Racket, ancak kodun çoğunu yazdıktan sonra bir alternatif sunmaya başladı ve alternatif, LOOP ile karşılaştırıldığında hala berbat (Racket'in geliştirme ekibi daha iyi olduğu konusunda ısrar etse de - sadece yanlışlar). Listeleri yinelemek için "araba" ve "cdr" kullanan bir çok adlandırılmış LET formu yazdım.
Araba ve cdr'den bahsetmişken, hiçbir şey Scheme'nin (car '())' yi bir hata olarak yorumlamasından daha sinir bozucu değildir. Racket'in büyük/küçük harf duyarlılığından yararlandım ve Common LISP'nin semantiğine sahip olan CAR ve CDR'yi uyguladım. Ancak, '() ve #f ayrılması varsayılan değer olarak' () döndürülmesini çok daha az kullanışlı hale getirir.
Ayrıca UNWIND-PROTECT'i yeniden uyguladım ve Racket'in bıraktığı boşluğu doldurmak için kendi yeniden başlatma sistemimi icat ettim. Racket topluluğunun yeniden başlatmanın çok yararlı ve uygulaması kolay olduğunu öğrenmesi gerekiyor.
Raketin izin değerleri formu aşırı ayrıntılıydı, bu yüzden MULTIPLE-VALUE-BIND uyguladım. Bu kesinlikle gerekliydi, çünkü Raket gerektiriyor siz kullansanız da kullanmasanız da üretilen değerleri tümü almanız gerekir.
Daha sonra, sadece HTMLPrag gibi bir şey olmadığını bulmak için Common LISP'de bir eBay XML API istemcisi yazmaya çalıştım. HTMLPrag işe yaramaz. Bu projeyi Racket'te yaptım. Racket'in Okuryazar Programlama olanaklarını denedim, sadece dünya üzerinde sıradan koddan daha zor yazılmış düzgün bir okuryazar kod ya da yanlış yazılmış "aşırı yorumlar" okuryazar kodunu bulan tek programcı olduğumu keşfetmek için denedim.
Yeni projem doğru seçim olan Common LISP'de yapılıyor çünkü Racket topluluğu bu proje için gerekli olan paralelliğe inanmıyor. Racket'ten kaçırmış olabileceğimi düşündüğüm tek şey devam ediyordu. Ancak, yeniden başlatmaları kullanarak ihtiyacım olanı yapabildim ve geçmişe bakıldığında, muhtemelen basit bir kapanışla yapabilirdim.
Şema ayrı bir derleme düşünülerek tasarlanmıştır. Sonuç olarak, makrolarının gücü, zayıf, sınırlayıcı hijyenik makro sistem yerine Ortak LISP tarzı bir defmacroya izin veren uzantılarla bile genellikle ciddi şekilde sınırlıdır. Bir sonraki kod satırında hemen kullanılmak üzere tasarlanan başka bir makro tanımlayan bir makro tanımlamak her zaman mümkün değildir. Ve böyle bir olasılık, verimli eDSL derleyicilerinin uygulanması için gereklidir.
Metaprogramlama tarzım hijyene yeterince çevrilemediğinden, yalnızca R5RS hijyenik makrolarına sahip Scheme uygulamalarının benim için neredeyse hiç yararlı olmadığını belirtmeye gerek yok.
Neyse ki, bu sınırlamaya sahip olmayan Şema uygulamaları (ör. Raket) vardır.