Lisp topluluğu neden fonksiyonun sonunda tüm parantezleri toplamayı tercih ediyor?


26

Lisp topluluğu neden fonksiyonun sonunda tüm parantezleri toplamayı tercih ediyor:

(defn defer-expensive [cheap expensive]
  (if-let [good-enough (force cheap)]
    good-enough
    (force expensive)))

Neden C veya Java gibi bir sözleşme kullanmıyorsunuz?
Pekala, Lisp bu dillerden çok daha eski, ama ben çağdaş Lispers'tan bahsediyorum.

(defn defer-expensive [cheap expensive]
  (if-let [good-enough (force cheap)]
    good-enough
    (force expensive)
  )
)

Not: Kod pasajı "Clojure'un Sevinci" kitabındandır.


13
Delgeç kartlarının günlerinde, programdaki tüm açık parantezleri eşleştirecek kadar yeterli olduğundan emin olmak için üzerinde fazladan bir kartla Lisp programını sonlandırmanın yaygın bir uygulama olduğu söylendi. .
Alger

2
Vay beğendim. Parantezden her zaman nefret ettim, ancak ikinci örneğiniz bana hoş geliyor. Python kadar hoş değil, ancak iyileştirme.
Eric Wilson

5
çünkü yapabilirler?
Muad'Dib

Bir Clojure lehçesi çentik kod yapısı olarak terfi ettirmek güzel olurdu. Bu tamamen parantez içinde olur (F # gibi, vb.). Elbette, istenirse parantez yine de yasal olacaktır.
intrepidis

Yanıtlar:


28

Algol tabanlı dillerin, destekleri kendi çizgileri üzerinde teşvik etmelerinin bir nedeni, destekleri hareket ettirmek zorunda kalmadan tutucu desteklerin arasına daha fazla çizgi eklemeyi teşvik etmektir. Yani, biriyle başlarsa

if (pred)
{
  printf("yes");
}

gelip kaşlı ayraç içine başka bir deyim eklemek kolaydır :

if (pred)
{
  printf("yes");
  ++yes_votes;
}

Orijinal form olsaydı

if (pred)
{ printf("yes"); }

o zaman iki parantezi "hareket ettirmek " zorunda kalırdık, ancak örneğim ikincisiyle daha fazla ilgileniyor. Burada, parantezler , çoğunlukla yan etki için çağrılan bir dizi ifade olarak tasarlananı sınırlandırmaktadır .

Tersine, Lisp ifadelerinden yoksundur; her form ifadedir , bir miktar değer verir - bazı nadir durumlarda (Common Lisp düşünürken) bile, bu değer kasıtlı olarak boş bir (values)form aracılığıyla "değer yok" olarak seçilir . İç içe ifadelerin aksine , ifade dizilerini bulmak daha az yaygındır . "Kapanış sınırlayıcısına kadar bir adım dizisi açma" arzusu sık sık ortaya çıkmaz, çünkü ifadeler uzadıkça ve geri dönüş değerleri daha yaygın bir para birimi olduğunda, ifadenin geri dönüş değerini yok saymak daha nadirdir ve Sadece yan etki için bir ifade dizisini değerlendirmek için nadirdir.

Common Lisp'te prognform bir istisnadır (kardeşleri gibi):

(progn
  (exp-ignored-return-1)
  (exp-ignored-return-2)
  (exp-taken-return))

Burada, prognüç ifadeyi sırayla değerlendirir, ancak ilk ikisinin dönüş değerlerini atar. Son kapanış parantezini kendi satırına yazmayı hayal edebilirsiniz, ancak şunu da belirtmelisiniz ki, son form burada özel olduğundan (Ortak Lisp'in özel olması anlamında değil ), ancak farklı muamele ile, birinin yeni eklemenin daha muhtemel olduğunu sekansın ortasındaki ifadeler, arayanlar olarak "sonuna bir tane daha eklemek" yerine, yalnızca yeni bir yan etkiden değil, geri dönüş değerindeki muhtemel bir değişiklikten etkilenecektir.

Brüt basitleştirilmesi yapma, bir Lisp programı birçok yerinde parantez-sadece fonksiyonlar C benzeri dillerde-ve benzeri geçirilen argümanları sınırlayan değil deyim bloklarını sınırlayan. Aynı nedenlerden ötürü parantez içinde C de bir fonksiyon çağrısını sınırlayan argümanları argümanların yakınında tutmaya meyilliyiz, bu yüzden aynı şeyi Lisp'te de yaparız, bu yakın gruplamadan sapmak için daha az motivasyonla.

Parantezlerin kapatılması, açıldıkları form girintilerinden çok daha az ithaldir. Zaman içinde parantezleri görmezden gelmeyi ve Python programcılarının yaptığı gibi şekil yazmayı ve okumayı öğrenir. Ancak, bu analojinin parantezleri kaldırmanın tamamen faydalı olacağını düşünmenize yol açmasına izin vermeyin . Hayır, bu en iyi kurtarılan bir tartışma comp.lang.lisp.


2
sonunda eklemenin o kadar nadir olmadığını düşünüyorum, mesela (let ((var1 expr1) more-bindings-to-be-added) ...), veya(list element1 more-elements-to-be-added)
Alexey

14

Çünkü yardımcı olmuyor. Kod yapısını göstermek için girintiyi kullanırız. Kod bloklarını ayırmak istiyorsak, gerçekten boş satırlar kullanırız.

Lisp sözdizimi çok tutarlı olduğu için, parantezler hem programcı hem de editör için girintiye dair kesin kılavuzdur.

(Benim için soru, C ve Java programcılarının diş tellerinin etrafına atmak istemelerinin sebebidir.)

Sadece bu operatörlerin C benzeri bir dilde mevcut olduğunu varsayarak göstermek için:

Foo defer_expensive (Thunk cheap, Thunk expensive) {
    if (Foo good_enough = force (cheap)) {
        return good_enough; }
    else {
        return force (expensive); }}

İki kapanış parantezi iki yuva seviyesini kapatır. Sözdizimi açıkça doğrudur. Python sözdizimine benzeyen parantezler sadece açık INDENT ve DEDENT belirteçleridir.

Tabii ki, bu "tek gerçek ayraç tarzı" TM olmayabilir , ama bunun sadece tarihi bir kaza ve alışkanlık olduğuna inanıyorum.


2
(Bazıları da doğru kapatırken Ayrıca hemen hemen tüm lisp editörler eşleşen parantez işaretlemek )için ]veya tam tersine) size girinti seviyelerini kontrol bile doğru miktarda kapalı bilmeleri.
konfigüratör

6
WRT "soru", çünkü ikinci örneğin tarzında belirteçleri "etrafa fırlatmak" onları kolayca gözlerinizle hizalamanızı ve neyin kapandığını görmenizi sağlar; Vurgulama özellikleri.
Mason Wheeler

1
@Mason Wheeler Evet, Kesinlikle.
Chiron

3
TBH, bunun bana söylediği şey, LISP'deki parenlerin çoğunlukla yedekli olduğu, (C ++ 'da olduğu gibi) girintinin yanlış yönlendirebileceği ihtimaliyle - girinti size derleyiciye de aynı şeyi söylemesi gerektiğini bilmeniz gerektiğini söylerse, Haskell ve Python'da olduğu gibi. BTW - diş tellerinin C ++ ile if / switch / while / whatever ile aynı girinti düzeyinde olması, girintinin yanıltıcı olduğu durumları önlemeye yardımcı olur - LHS'deki görsel bir tarama, her açık desteğin sıkı bağlantıya uyduğunu gösterir ve bu girinti, bu diş telleriyle tutarlıdır.
Steve314

1
@ Steve314: Hayır, girinti gereksiz. Girinti Python ve Haskell'de de yanıltıcı olabilir (bir kereye mahsus girintiyi veya tabloları düşünün), sadece ayrıştırıcının da yanlış yönlendirildiği durumdur. Parantezlerin yazar ve ayrıştırıcı için bir araç olduğunu düşünüyorum, oysa girinti yazar ve (insan) okuyucu için bir araç. Başka bir deyişle, girinti bir yorumdur, parantezler sözdizimidir.
Svante,

11

Kod daha sonra daha kompakt. Editördeki hareket, yine de s ifadeleridir, dolayısıyla düzenleme için o alana ihtiyacınız yoktur. Kod, çoğunlukla sınırlayıcıları izleyerek değil, yapı ve cümleler tarafından okunur.


Sizden bir cevap almak için ne bir şeref :) Teşekkürler.
Chiron

Hangi ifadeler s ifadeleriyle hareket eder? Daha spesifik olarak, bunu nasıl yapabilirim vim?
hasen

2
@HasenJ vimacs.vim Eklentiye ihtiyacınız olabilir . : P
Mark C

5

Lispers, bunu olabilecek hatefully bletcherous, biliyorum, orada olduğu belli quoi sais je ne ikinci örneğe:

(defn defer-expensive [cheap expensive]
  (if-let [good-enough (force cheap)]
    good-enough
    (force expensive)
  )
)

İlk başta, konuşmanın kaynağına parmağımı sokamadım, tabiri caizse, ve sonra sadece bir tetikleyicinin eksik olduğunu fark ettim:

(defn defer-expensive [cheap expensive]      
  (if-let [good-enough (force cheap)]
    good-enough   ;   )
    (force expensive) 
  )
)

Voila

Lisp gangster tutucumu şimdi uygulayacağım!


2
Bu, bu sitede gördüğüm en komik ve en az cevaplanmış cevaplardan biri. Şapkamı eğerim.
byxor

0

Benim durumumda, sınırlayıcılara ayrılmış bir ekran boşluğu alanı buldum ve C kodunu yazdığınızda aynı zamanda

if (pred) {
   printf("yes");
   ++yes_votes;
}

Neden insanlar açıklık parantezini “if” nin aynı satırına yerleştiriyorlar?

Sonunda parantezi bir araya getirerek aynı sonuca ulaşırsınız. C tuhaf görünecektir çünkü ifadeler noktalı virgülle bitiyor ve parantez çifti bu şekilde açılmıyor

{if (pred)
    printf("yes");
}

Sonunda kapanış ayracı gibi görünüyor, yerine bakıyor. böyle açılıyor

if (pred) {
    printf("yes");
}

'{' & '}' ile blok ve sınırlarının net bir görüntüsünü veriyor

Ve parantezleri vim gibi vurgulayarak eşleştiren bir editörün yardımıyla, tüm parantezlerin paketlendiği sonuna kadar gidebilir ve kolayca ilerleyebilir ve tüm açılış parenleriyle eşleşebilir ve yuvalanmış lisp formunu görebilirsiniz.

(defn defer-expensive [cheap expensive]
    _(if-let [good-enough (force cheap)]
    good-enough
    (force expensive)_))

imlecinizi ortadaki kapanış parenine getirebilir ve if-let'in açılış parenini vurgulayabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.