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.
setfiş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-stringayrıca makro içindeki kodun anlambilimini de değiştirir. Benzer şekilde with-current-bufferve 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-libPaket, eieiopaket 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-bindsadece 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ı contextargümanı art arda çağrılması gereken bir grup işleve geçirmesi gerekiyorsa, bunları contextargü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)+1ya da 0ya 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.