Bir lambda ifadesi ne zaman keskin alıntı yapmalı?


30

S: Ne zaman, eğer varsa, keskin bir şekilde alıntı yapmak faydalı olur lambdave ne zaman, eğer varsa, keskin bir şekilde alıntı yapmamalı mıyız lambda?

İnsanlar s'ı lambdaüç şekilde kullanır:

  1. sade: (lambda (x) x)
  2. alıntı: '(lambda (x) x)
  3. Sivri alıntılanan: #'(lambda (x) x)

Bu SO iş parçacığı üç türü tartışır, bu SO iş parçacığı neden alıntı yapmamayı açıklar (NB: Keskin Alıntı Yapmaz ) lambdas ve bu SO iş parçacığı da alıntılama ve keskin alıntılama arasındaki farkları tartışır.

Şimdi, anonim işlevler üzerindeki manuel düğüm ve kendi kendine alıntı yapan lambdanot için belgeleme lambda:

Form çağrısı (lambda ARGS DOCSTRING INTERACTIVE BODY)kendiliğinden alıntı yapar; lambda ifadesini değerlendirmenin sonucu ifadenin kendisidir. Lambda ifadesi daha sonra bir fonksiyon olarak ...

Yani, öyle görünüyor (lambda (x) x)ve #'(lambda (x) x)eşdeğer, ancak '(lambda (x) x)değil (en önemlisi, bayt-derleme yaparken).

Biri nadiren bir alıntı yapmak ister gibi görünüyor lambda, fakat ne zaman, keskin bir alıntı yapmalıyız, yapmamalıyız veya yapmamalıyız.

  • Keskin alıntı lambdabasit bir seçenek midir, yoksa keskin alıntılamanın gerçekten yararlı olduğu durumlar var mı?
  • Biz gereken hangi orada şartlar Are değil keskin alıntı lambdaolduğunu, kodun anlamını değiştirecek bunu yaparken?

Yanıtlar:


28

Bir zamanlar , keskin alıntı, lambdalar için gerekliydi, artık durum böyle değil.

Dolayısıyla, (lambda (x) x) ve # '(lambda (x) x) eşdeğerdir, ancak' (lambda (x) x), (en önemlisi, bayt-derlerken) değildir.

Evet. Aslında, ilk ikisi değerlendirildiğinde tamamen aynıdır. Bağladığınız kılavuz sayfasında açıklandığı gibi :

Aşağıdaki formların hepsi eşdeğerdir:

(lambda (x) (* x x)) 
(function (lambda (x) (* x x))) 
#'(lambda (x) (* x x))

Yirmi yıl önceki Emacs versiyonlarını desteklemeye çalışmaktan başka bir lambdadan alıntı yapmak için hiçbir sebep yoktur.

Öyleyse yapma.


Yan not olarak:

  • Bir lambda (ile ') sert alıntı fark yaratır, bayt derlemesini önler. Bunun yararlı olduğu bir senaryo düşünemiyorum, ama kim bilir.

  • Sırtı, lambdalar için gerçekten yararlı olan tek alıntı, ancak sadece nedense sözcüksel bağlayıcı kullanmıyorsanız.


Alıntı derleme üzerindeki alıntılama etkisini açıklayan bir örnek içeren, kılavuzun Anonim İşlevler bölümüne bir bağlantı eklemeyi düşünün .
Constantine

@ Sabit Stajyer Yapıldı. Tembel oldum çünkü bir telefondayım ve OP zaten zaten bağlı.
Malabarba

Sözcüksel bağlama ve geri sarma düğmesini kullanmama derken ne demek istediğinizi açıklayabilir misiniz? Teşekkürler.
saat

@coredump Dinamik bağlamada, bir lambda içinde dış değişkenleri erişilebilir kılmanın tek yolu lambdayı içinde değişken olan bir liste olarak elle oluşturmaktır. Backtics bu tür şeyler için iyidir.
Malabarba

BTW, "bir zamanlar" ın gerçekten geçerli olduğunu sanmıyorum: bu konuyu gözden geçirme tarihinde araştırdığımda , geriye dönebildiğim kadar geri lambdaekleyen bir makro olarak tanımlandığını functiongördüm. Eğer bir #'noktada ihtiyaç duyulursa, çok erken gelişim kodundaydı. Emacs-18'de kesinlikle gerekli olmadığına eminim.
Stefan

5

Yana lambdao tırnak içine yorumlamak içinde, Emacs Lisp takip son sürümleri (ANSI) Ortak Lisp alıntı değilken herhangi bir anlam ifade etmez (lambda...)olarak #'(lambda...). İki gösterim neredeyse tamamen eşdeğerdir (kote edilmiş yapı içinde değildir).

Tercih etmek (lambda...)veya #'(lambda...)bu nedenle tamamen bir stil meselesidir. Bazı insanlar sözdizimsel gürültüyü önleyen çıplak formu tercih ederken, diğerleri (kendim dahil) alıntılanan şekli tercih eder.


Bu, elisp el kitabına aykırıdır: "Emacs Lisp'te böyle bir liste, bir işlev nesnesini değerlendiren geçerli bir ifadedir."
djechlin

8
"Son sürümler", "1990’dan sonraki sürümlerde" olduğu gibi ";-)
Stefan

0

Görme hesabına ek geçmiş biraz ekleme Is # '(lambda ...) tarihsel miras?

https://debbugs.gnu.org/cgi/bugreport.cgi?bug=4290 şunu önermektedir:

Emacs 22 ile başlayarak, lambdabir işlev olarak kullanıldığında, functionveya önce gelip gelmediğine bakılmaksızın bir form byte derlenir #'. 22'den önceki Emacs sürümlerinde, açıkça kullanmanız #' veya functionformun bayt derlemeli olmasını istiyorsanız.

Bayt-derleyici hakkında bir şey bilmiyorum ama en azından 1993 yılına kadar lambdamakroların bir (function (lambda ...))form döndürdüğünü görebiliyorum .

https://www.iro.umontreal.ca/~monnier/hopl-4-emacs-lisp.pdf ayrıca şunları da söylüyor:

İlginç bir şekilde (MacLisp'ten farklı olarak), lambdateknik olarak Emacs-19'un gelişimi sırasında, bir makro olarak eklenene kadar 1991 yılına kadar Elisp dilinin bir parçası değildi. Emacs-18'de, isimsiz fonksiyonlar, formun alıntılanan değerleri olarak yazılmıştır:

'(lambda (..ARGS..) ..BODY..)

İken lambdamakro şimdi neredeyse 30 yıldır gereksiz bu teklifi yaptı, bu uygulamanın birçok örnekleri hala vücudun bayt derleme engeller olsa da, elisp kodunda meydana gelir. Bir miktar ilgili, ancak 1993 yılında Lucid Emacs 19.8, #'...okuyucuyu (function ...)MacLisp'ten kısa yoldan aldı. Emacs takip eden yıl da takım elbise izledi.


0

Sadece backtic lambda ifadesi kullanarak pratik bir örnek vermek istiyorum. Sözcüksel bağlama / değişken gölgeleme ile ilgilidir, bir backtic lambda ifadesi kullanmak ve değişkenleri virgülle referanslamak global değerlerini elde etmeyi mümkün kılar.

;; -*- lexical-binding:t -*-
(let ((my-variable "Random old"))
  (funcall `(lambda()
             (let ((my-variable "Random"))
               (message ,my-variable)))))

M-x [RET] eval-buffer "Rastgele eski" çıktılar

;; -*- lexical-binding:t -*-
(let ((my-variable "Random old"))
  (funcall (lambda()
             (let ((my-variable "Random"))
               (message my-variable)))))

M-x [RET] eval-buffer "Rastgele" çıktılar

Global değişkeni ve değişken değişkeninin yerel değişkenini birleştiren üçüncü bir örnek

;; -*- lexical-binding:t -*-
(let ((my-variable "Random old"))
  (funcall `(lambda()
              (let ((my-variable "Random"))
                (message my-variable)
                (message ,my-variable)))))

M-x [RET] eval-buffer "Rastgele" çıktılar


@npostavs benim örneğimin amacı değildi, ancak bu kötü uygulamayı da engellemek için örneğimi değiştirdim
cjohansson

Daha da iyisi, yine de ikna olmadığım halde, iç bağlanma için sadece farklı bir isim seçmeye göre bir gelişmedir.
npostavs
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.