Değişken isimlerinden önce tek bir alıntıyı ne zaman veya ne zaman kullanmayacağımı nasıl bilebilirim?


31

Bende aşağıdaki var:

(setq some-variable "less")

Ben tek alıntı kullanmak zorunda neden karıştı boundpama birlikte bound-and-true-p.

Örnek 1:

(when (boundp 'some-variable) 
   (message "some-variable is %s" some-variable))

Sonuç:

"bazı değişken daha az"

Örnek 2a:

(when (bound-and-true-p some-variable) ;; Note that using single-quote causes error
   (message "some-variable is %s" some-variable))

Sonuç:

"bazı değişken daha az"

Örnek 2b:

(when (bound-and-true-p 'some-variable) ;; Note that using single-quote causes error
   (message "some-variable is %s" some-variable))

Sonuç:

ve: Yanlış tip argümanı: symbolp, (bir değişkenli alıntı)


5
Bunun setqanlamına geldiğini set quotedve aslında içine genişleyen bir makro olduğunu söylemeye değer (set 'some-variable "less"). Genel olarak, Elisp alıntı ve alıntı olmayan argümanlar hakkında oldukça tutarlı değildir, ancak bir değer yerine bir değişkenle etkileşime girmesi gereken herhangi bir fonksiyon (makro değil) alıntılanacaktır ( setqbüyük bir istisna olmak).
shosti

2
FWIW, bound-and-true-paptal bir makro. Veya daha doğrusu adı aptaldır. Zamanın% 99,99'unu yapmak (and (boundp 'FOO) FOO)istediğinizde değerini kullanmak içinFOO yaparsınız . Bunu sadece gerçeğe uygun bir değer elde etmek için yapmazsınız. (1) Makro gerekli değildir - değiştirdiği kod önemsiz ve küçüktür. (2) Ad yanıltıcı - sadece değişken değerin olup olmadığını test etmek yerine değişken değerle ilgilidir nil.
Drew,

Yanıtlar:


24

Kısa cevap

Değişkenin kendisini kullanmaya çalışıyorsanız, kullanın 'some-variable. Değişkende depolanan değeri kullanmaya çalışıyorsanız, kullanın some-variable.

  • boundp sembol kullanır, böylece fonksiyonlar dahil olmak üzere bağlanabilecek her şeye bakar. Bu sadece değerin ne olduğunu değil, eşleşen bir sembol olup olmadığını önemser.
  • bağlı ve truep var kullanır ve değeri döndürür. Bu durumda, işleve sembolün değerini sağlamanız gerekir. Bir sembol değişkeni bağlı değilse veya değer sıfır ise, sıfır değerini döndürür.

açıklama

Manuel tanım için lütfen kılavuza bakınız .

've (quote ...)her ikisi de emacs-lisp'ta aynı amacı yerine getirir.

Bunun amacı, değerlendirilmemiş formu, değerlendirmek yerine çevredeki ortama aktarmaktır.

Örneğinizde, aşağıdakileri yükselttiğimizi varsayın

(setq some-variable "less") ;; Rather than just 't for clarity

Ardından değerlendirme şu şekilde yapılır:

(when (boundp 'some-variable) 
   (message "some-variable is %s" some-variable))
;; ==> (boundp 'some-variable) ; 't
;; ==> some-variable is "less"

Alıntı yapmadan:

(when (boundp some-variable) ;; Note that using single-quote causes error
   (message "some-variable is %s" some-variable))
;; ==> (boundp "less") ; "less" is not a variable. -> Error

Lisp, gerçek değişken (veya liste veya işlev adı) iletilmek üzere değerlendirmeyi önlediğiniz formu alıntı yaparak formları ulaşıldıkça değerlendirir.


Teşekkürler! Cevabınız ikisinin de kaynağına atlamamı sağladı ve çözüme ulaşmamda bana yardımcı oldu. Ayrıca sorumu net örneklerle güncelledim.
Kaushal Modi

6
Bu amaca yardım ettiğine sevindim, ancak aslında soruyu yanıtlamıyor (aynı soruyu diğer insanlar için yararlı bir şekilde). Sadece sembollerin kote edilmesi gerektiğini ya da değerlendirildiklerini açıklarsınız. Bunun neden böyle olmadığını açıklamıyorsunuz bound-and-truepve soru neden kullanırken kullanırken alıntı yapmam boundpgerektiğini soruyorum bound-and-truep.
tarsius

@ tarsius Ben aslında boundpbir sembol (değerlenmemiş) istemekle ve madde imleç bound-and-truepnoktalarındaki değişkenin değerine ihtiyaç duymak (ilk cevaptan sonra düzenlenen ) arasındaki ayrımı içerir
Jonathan Leech-Pepin

Bunun neden böyle olduğunu söylemenin zorunlu olduğunu düşünüyorum (makrolar değerlendirme yapmamayı seçebilir) sadece doc-string'in söylediğini söylemek yerine. Bence bu çok iyi bir soru ve bununla sınırlı ve gerçek-s arasındaki sınır sadece bir örnek. Sorunun asıl meselesi, değerlendirme kuralları hakkında bilgi edinme isteğidir.
tarsius

@ tarsius Bu cevap tarafından açıklanan değerlendirme kuralları değil mi? En azından sadece alıntı içeren basit cevaplar ... Cevabınız kesinlikle daha eksiksiz, ama konunun çok ötesine gidiyor, değil mi?
T. Verron,

16

İşlevsiz pozisyonda olan bir sembol değişken değişken adı olarak kabul edilir. In (function variable) functionfonksiyonu pozisyonunda (parantezin açılmasından sonra) ve variabledeğil. Açıkça belirtilmediği sürece değişkenler değerleri ile değiştirilir.

Eğer yazacak (boundp my-variable)olsaydınız, "değişken olarak my-variablesınırlanan değişken değerinde saklanan sembol" anlamına gelmez, " değişken değil olarak bağlanan sembol" anlamına gelir my-variable.

Peki neden bound-and-truepfarklı davranıyor?

Bu bir makrodur ve normal (işlev) değerlendirme kuralları burada uygulanmaz, makrolar argümanlarının değerlendirilip değerlendirilmediğine ve ne zaman değerlendirileceğine karar vermede serbesttir. Makroların gerçekte yaptığı şey, bir şekilde argümanları dönüştürmek ve sonucu, ardından değerlendirilen bir liste olarak döndürmektir. Dönüşüm ve nihai değerlendirme, makro genişleme zamanı ve değerlendirme zamanı olarak adlandırılan farklı zamanlarda gerçekleşir.

bound-and-true-pGörünüşün tanımı şöyle:

(defmacro bound-and-true-p (var)
  "Return the value of symbol VAR if it is bound, else nil."
  `(and (boundp (quote ,var)) ,var))

Bu, lisp makrolarından farklı olan okuyucu makrolarını kullanır (aşağıda daha fazlası). Bunu daha da karmaşıklaştırmamak, okuyucu makrolarını kullanmamakta:

(defmacro bound-and-true-p (var)
  "Return the value of symbol VAR if it is bound, else nil."
  (list 'and (list 'boundp (list 'quote var)) var))

Eğer yazarsan

(bound-and-true-p my-variable)

Bu ilk "tercüme" edilir

(and (boundp 'my-variable) my-variable)

ve daha sonra, geri dönüş değerlendirilir nilhalinde my-variabledeğil boundpdeğeri ya da başka bir my-variable(tabii ki, aynı zamanda olabilen nil).


Genişlemenin olmadığını fark etmiş olabilirsiniz.

(and (boundp (quote my-variable)) my-variable)

Beklediğimiz gibi. quoteözel bir formdur, makro veya işlev değildir. Makrolar gibi, özel formlar argümanlarıyla ne yapabilirlerse. Bu özel özel form, argümanını, burada sembolün değişken değeri yerine bir sembol olarak döndürür. Aslında bu özel formun tek amacı bu: Değerlendirmeyi engellemek! Makrolar bunu kendi başlarına yapamazlar quote, bunu yapmak için kullanmaları gerekir .

Peki neyin var '? Yukarıda da belirtildiği gibi bir lisp makrosu ile aynı olmayan bir okuyucu makrosudur . Makrolar kodu / verileri dönüştürmek için kullanılırken, metinleri okurken daha önce bu metni kod / verilere dönüştürmek için okuyucu makrolar kullanılır.

'something

kısaca

(quote something)

`Asıl tanımında kullanılan bound-and-true-pbir okuyucu makrosu. Bir sembolün içinde `symbololduğu gibi bir eşittir 'symbol, ancak bir listeyi alıntı yapmak için kullanıldığında `(foo bar ,baz), öneki olan formlarda farklı davranır ,.

`(constant ,variable)

eşittir

(list (quote constant) variable))

Bu, işaretsiz sembollerin neden bazen değerlendirildiğini (değerleriyle değiştirildiğini) bazen de sorulmadığı sorusuna cevap vermelidir; quoteBir sembolün değerlendirilmesini önlemek için makrolar kullanılabilir .

Fakat neden bound-and-true-pbir makro boundpolmasın? Çalışma zamanına kadar bilinmeyen rastgele sembollerin sembol olarak bağlanıp bağlanmadığını belirleyebilmeliyiz. boundpArgüman otomatik olarak alıntılandıysa, bu mümkün olmazdı .

bound-and-true-pBilinen bir değişkenin tanımlanıp tanımlanmadığını belirlemek için kullanılır ve öyleyse değerini kullanın. Bir kitaplığın, aşağıdaki gibi üçüncü taraf bir kitaplığa isteğe bağlı bir bağımlılığı varsa, kullanışlıdır :

(defun foo-get-value ()
  (or (bound-and-true-p bar-value)
      ;; we have to calculate the value ourselves
      (our own inefficient or otherwise undesirable variant)))

bound-and-true-pbir işlev olarak tanımlanabilir ve argümanın alıntılanmasını gerektirebilir, ancak bir makroya ne tür bir değer verdiğinizi önceden bildiğiniz durumlar için tasarlandığından, sizi yazmaktan kurtarmak için kullanılır '.


İnanılmaz derecede iyi cevap verdi.
Charles Ritchie

2

Kaynak kodundan boundp:

DEFUN ("boundp", Fboundp, Sboundp, 1, 1, 0,
      doc: /* Return t if SYMBOL's value is not void.
Note that if `lexical-binding' is in effect, this refers to the
global value outside of any lexical scope.  */)

boundpsymbolgirdi olarak bir a bekler . 'some-variabledeğişkene bir semboldür some-variable.

Kaynak kodundan bound-and-true-p:

(defmacro bound-and-true-p (var)
  "Return the value of symbol VAR if it is bound, else nil."
  `(and (boundp (quote ,var)) ,var))

bound-and-true-pvariablegirdi olarak bir a bekler .

İçinde bound-and-true-pmakro, bu yaparak sembolü alır (quote ,var). Giriş Yani eğer some-variable, (quote ,var)sonuç içinde olacak 'some-variable.

Ben girdi verince Ama 'some-variableüzere bound-and-true-p, ben hata alıyorum: and: Wrong type argument: symbolp, (quote some-variable)Makro bir sembolü (bekliyor DEĞİLDİR çünkü 'some-variablegirişindeki).


Sadece bir heads-up. ''symbol yapar mantıklı. Anlamına gelir (quote (quote symbol)). Bir hata almanın nedeni bunun geçerli bir argüman olmamasıdır boundp.
Malabarba

@Malabarba Teşekkürler. Düzeltmeyi yaptım.
Kaushal Modi
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.