Açık sözlü olacağım: "sözdizimi için kullan, anlambilim için değil" ne anlama geliyor. Bu yüzden bu cevabın bir kısmı lunaryonun cevabı ile, diğer kısmı ise orijinal soruyu cevaplama girişimim olacak.
Programlamada "anlambilim" kelimesi kullanıldığında, dil yazarının dillerini yorumlamayı seçtiği yolu ifade eder. Bu, tipik olarak dilin dilbilgisi kurallarını, okuyucunun aşina olduğu varsayılan diğer bazı kurallara dönüştüren bir dizi formüle dayanır. Örneğin, Plotkin, Operasyonel Semanti'ye Yapısal Yaklaşım adlı kitabında soyut sözdiziminin neyi değerlendirdiğini açıklamak için mantıksal türev dili kullanır (bir programı çalıştırmak ne anlama gelir). Diğer bir deyişle, sözdizimi bir düzeyde programlama dilini oluşturan şeyse, o zaman bazı semantiğe sahip olmalıdır, aksi takdirde, bir ... programlama dili değildir.
Ancak, şimdilik resmi tanımları unutalım, sonuçta, niyeti anlamak önemlidir. Öyleyse, lunaryon, programa yeni bir anlam eklenmeyeceği zaman okuyucularını makro kullanmaya teşvik edecek gibi görünüyor, ama sadece bir tür kısaltma. Bana göre bu, makroların gerçekte nasıl kullanıldığına garip ve keskin bir tezat oluşturuyor. Aşağıda açıkça yeni anlamlar yaratan örnekler verilmiştir:
defun
ve dilin önemli bir parçası olan arkadaşlar, işlev çağrılarını tanımladığınız terimlerle açıklanamaz.
setf
işlevlerin nasıl çalıştığını açıklayan kurallar, bir ifadenin etkilerini tanımlamak için yetersizdir (setf (aref x y) z)
.
with-output-to-string
ayrıca makro içindeki kodun anlambilimini de değiştirir. Benzer şekilde with-current-buffer
ve bir grup diğer with-
makrolar.
dotimes
ve benzeri fonksiyonlar açısından tarif edilemez.
ignore-errors
kaydırdığı kodun anlambilimini değiştirir.
cl-lib
Paket, eieio
paket ve Emacs Lisp'de kullanılan neredeyse her yerde bulunan kütüphanelerde tanımlanmış bir sürü makro var, ancak fonksiyon formları farklı yorumlara sahip olabilir.
Yani, herhangi bir şey varsa, makrolar bir dile yeni anlambilim kazandırmak için kullanılan araçtır. Bunu yapmanın alternatif bir yolunu düşünemiyorum (en azından Emacs Lisp'te değil).
Ne zaman makro kullanmak olmaz:
Yeni semantiklerle yeni bir yapı getirmediklerinde (yani işlev işi iyi yapar).
Bu sadece bir tür kolaylık olduğunda (yani mvb
, cl-multiple-value-bind
sadece kısaltmak için genişleyen bir makro oluşturmak ).
Hata işleme kod makro tarafından gizlenmesi çok beklediğimde (belirtildiği gibi makroları hata ayıklamak zordur).
Ne zaman güçlü fonksiyonları yerine makroları tercih ederim:
Etki alanına özgü kavramlar işlev çağrıları tarafından gizlendiğinde. Örneğin, aynı context
argümanı art arda çağrılması gereken bir grup işleve geçirmesi gerekiyorsa, bunları context
argümanın gizlendiği bir makroya sarmayı tercih ederim .
İşlev biçimindeki genel kod aşırı ayrıntılı olduğunda (Emacs Lisp'teki çıplak yineleme yapıları benim zevkime göre çok ayrıntılıdır ve gereksiz yere programcıyı düşük düzeyli uygulama ayrıntılarına maruz bırakır).
örnekleme
Aşağıda, bilgisayar bilimlerinde anlambilim ile neyin kastedildiğine dair bir sezgi vermek için tasarlanmış sulandırılmış versiyon bulunmaktadır.
Yalnızca bu sözdizimi kurallarıyla son derece basit bir programlama diliniz olduğunu varsayalım:
variable := 1 | 0
operation := +
expression := variable | (expression operation expression)
Bu dille biz gibi "programları" inşa edebilir (1+0)+1
ya da 0
ya da ((0+0))
vb
Fakat semantik kurallar sağlamadığımız sürece, bu "programlar" anlamsızdır.
Şimdi dilimizi (anlamsal) kurallarla donattığımızı varsayalım:
0+0 0+1 1+0 1+1 (exp)
---, ---, ---, ---, -----
0 1+0 1 0 exp
Şimdi bu dili kullanarak hesaplayabiliriz. Yani, sözdizimsel temsili alabilir, soyut olarak anlayabiliriz (başka bir deyişle, soyut sözdizimine dönüşebilir), sonra bu temsili manipüle etmek için anlamsal kuralları kullanabiliriz.
Lisp dil ailesi hakkında konuştuğumuzda, işlev değerlendirmenin temel semantik kuralları kabaca lambda-hesabıdır:
(f x) (lambda x y) x
-----, ------------, ---
fx ^x.y x
Alıntı ve makro genişletme mekanizmaları meta-programlama araçları olarak da bilinir, yani sadece programlama yerine program hakkında konuşmaya izin verirler . Bunu "meta katmanı" kullanarak yeni anlambilim oluşturarak başarırlar. Böyle basit bir makro örneği:
(a . b)
-------
(cons a b)
Bu aslında Emacs Lisp'de bir makro değil, olabilirdi. Ben sadece basitlik uğruna seçtim. En yakın adayın bir işlev olarak (f x)
yorumladığı , ancak mutlaka bir işlev olmadığı için f
, yukarıda tanımlanan anlamsal kuralların hiçbirinin bu durum için geçerli olmayacağına dikkat edin a
.