Şartlar için “ve” - “ne zaman”


13

Bu, bu cevabın yorumlarının bir devamıdır . Aşağıdaki kod parçaları eşdeğer gibi görünüyor:

(and a b)

(when a b)

Tabii anddaha koşullar koymak sağlar: (and a b c d)araçları(when (and a b c) d)

Ben whensadece dallanmayı ifade etme eğilimindeyim . Gerçek farklılıklar var mı? Birini veya diğerini kullanmak daha mı iyi?

Emacs'ın C kaynağı elimde değil; andbir C fonksiyonudur; when, genişleyen bir makrodur if, kendisi de C işlevidir.


"Elbette ve sağlar" olmalıdır "Elbette" ve "sağlar", ancak bu sadece 2 karakterlik bir değişikliktir ve izin verilen bir düzenleme değildir. Geçersiz kılma yok.
Harvey

Yanıtlar:


18

TL; DR: when yan etkilerle ilgilidir, andsaf boole ifadeleri içindir.

Fark ettiğiniz gibi andve whensadece sözdiziminde farklılık gösterir, ancak aksi takdirde tamamen eşdeğerdir.

Sözdizimsel fark oldukça önemlidir, ancak: ilk argüman formları whendışındaki prognherkese örtülü olarak sarılır . progndoğası gereği zorunlu bir özelliktir: En son vücut formu dışındaki her şeyi sadece yan etkileri açısından değerlendirir ve geri döndürdükleri değeri atar.

Bu nedenle, whenzorunlu bir formdur: Ana amacı, yan etkili formları sarmaktır, çünkü sadece son formun değeri vücut için gerçekten önemlidir.

andÖte yandan, asıl amacı verilen argüman formlarının dönüş değerlerine bakmak olan saf bir işlevdir: Bağımsız değişkenlerinden prognherhangi birini açıkça sarmadıkça , her argüman formunun değeri önemlidir ve hiçbir değer göz ardı edilmez. .

Bu nedenle andve whenstilistik arasındaki gerçek fark : andSaf boole ifadeleri için ve whenyan etkili formların etrafına bir koruma koymak için kullanılır.

Bu nedenle, bunlar kötü stil:

;; `when' used for a pure boolean expression
(let ((use-buffer (when (buffer-live-p buffer)
                    (file-exists-p (buffer-file-name buffer)))))
  ...)

;; `and' used as guard around a side-effecting form
(and (buffer-file-name buffer) (write-region nil nil (buffer-file-name buffer)))

Ve bunlar iyi:

(let ((use-buffer (and (buffer-live-p buffer)
                       (file-exists-p (buffer-file-name buffer)))))
  ...)

(when (buffer-file-name buffer)
 (write-region nil nil (buffer-file-name buffer)))

Bazı insanların buna katılmadıklarını ve andyan etkileri korumak için mutlu bir şekilde kullandıklarını biliyorum , ancak bunun gerçekten kötü bir stil olduğunu düşünüyorum. Bir nedenden ötürü şu farklı formlara sahibiz: Sözdizimi önemlidir . Olmasaydı, hepimiz kullanacağız if, ki bu Emacs Lisp'de semantik olarak gerçekten ihtiyacınız olan tek koşullu form. Diğer tüm boolean ve koşullu formlar açısından yazılabilir if.


2
IMO (yani, stil ı kullanımda), andyaklaşık dönüş değeri hakkında bakmakta . Yan etkileri kullanmakla ilgili değildir. Programım dönüş değerini önemsiyorsa o zaman kullanıyorum and. Eğer değilse o zaman kullanırım when. IOW, when sadece yan etkiler için kullanıyorum , ancak prognargümanlardan birinde bir de kullanabilirim and. Dönüş değerinin önemli olup olmadığı, tek başına önemli olup olmadığı değil .
Drew

5
andbildiğim Lisp'lerde bir işlev değil. Emacs Lisp'te bu özel bir form, Common Lisp'te bir makro, çünkü kısa devre davranışına sahip olması bekleniyor (işlevlerle başarılması imkansız, çünkü her zaman argümanlarını değerlendiriyorlar).
Mark Karpov

2
@lunaryorn, Evet, gerçekten alakalı değil, ama bu doğru, bu yüzden andbir fonksiyonun, yanlış olduğunda yazmak yanlış olduğunu düşünüyorum . Sorunun gerçekle ne kadar alakalı olduğu önemli değil, her zaman doğru terimleri kullanmalıyız, hepsi bu.
Mark Karpov

2
“Her argüman formunun değeri önemli” olduğunu düşünmüyorum, bu yorumun ne olduğu ile tutarlı. Hiçbir formun sadece değerinin atılması için değerlendirilmediğini söyleyerek daha iyi ifade edilebilirdi.
Harald Hanche-Olsen

3
Biraz OT, ama: Fark Lisps'te, niltüm "yanlış", "boş liste", "geçersiz" vb . Anlamına gelmeyen, stilistik olmaktan daha fazlasıdır . Örneğin, Şema ve Racket'te whenolduğu void(yani, "bir anlamı") için ise ando #f( "sahte"). Bu Elisp için N / A olmasına rağmen, Lisp generalinin düşünebileceği bir şey.
Greg Hendershott

4

Bunu söyleyerek başlayayım (and a b)ve (when a b)örneğinizde aynı şeyi yapın: Birincisi adeğerlendirilir. beğer değerlendirilir aolduğunu doğrudur # .

Ancak and ve whenfarklı şeyler için kullanılır.

  • Sen kullanırsınız (and a b)dönmek için gerçek # eğer İKİ ave bolan gerçek # (veya olmayan nil); ve nilbaşka türlü.

  • Kullanırsınız (when a b)veya daha doğru olursanız,

    (when a
       ;; do something like b
       )
    

    Eğer "B" kod yürütmek istediğinizde ancak ve ancak abir gerçek # .


Birlikte whenve andbirlikte kullandığınız bir örnek :

(when (and a b)
   (do-c))

Yukarıda, fonksiyon do-cSADECE İKİ eğer denir ave bvardır doğrudur # .


Çalışma için referanslar

# True ile ilgili tüm başvurular Boole TRUE değerine başvurur.


3
andttüm argümanları sıfır değilse döndürmez , ancak son argümanın değeri döndürmez .
Anlamlı Kullanıcı Adı

1
By t, ben Boole TRUE veya olmayan nil anlamına geliyordu. Teşekkürler, cevabımda bunu açıklığa kavuşturacağım.
Kaushal Modi

Cevabınızın soruda daha önce belirttiğimden çok daha ileri gittiğini düşünmüyorum; Her ikisinin de ne yaptığını biliyorum ve verdiğiniz son örnek zaten sorumda ( (when (and a b) c)) görünüyor. Buna ek olarak, genel olarak bu şekilde nasıl kullanıldıklarını andve whenönerdiklerini, ancak bu sorunun temelini, sık sık farklı kullandıklarını gördüm (örneğin soruma bağlandığım cevaba bakınız).
Clément

Sadece fonksiyonel bir yapı noktası görüntüsü, kaynaktan olmayan sonlandırma değerlendirmeler için olup ve doğrudan sembol ve Boole mantık içindir. Fonksiyonel programlama bu ayrımı gerektirir; zorunlu programlama bunu ortadan kaldırıyor.
Emacs Kullanıcısı

1
"Boolean true" nun "true" dan daha açık olduğunu düşünmüyorum.
YoungFrog
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.