関数とマクロとスペシャルフォームの違い

http:/www.mail-archive.com/cl-faq@lispniks.com/msg00120.html

関数, マクロ, スペシャルフォーム

関数が呼ばれるとき, その引数は全部評価される. 関数はfuncallされたりapplyされたりできる. 誰でも関数を書くことができる(プログラマでもコンパイラ作者でも).

マクロが呼ばれるとき, その引数は一つも評価されないが, 代わりにそれらの引数は直接マクロにリスト(とかその他なんでも)として渡される. マクロはfuncallされたりapplyされたりはできない. 誰でもマクロを書くことができる(プログラマでもコンパイラ作者でも).

スペシャルフォームが呼ばれるとき, その引数は問題となっているスペシャルフォームに依存して評価されたりされなかったりする. 例えば, ifは第一引数を評価し, その結果に依存して第二引数か第三引数のどちらかを評価する. letはすこし違う. prognもすこし違う. コンパイラ作者だけがスペシャルフォームを書くことができる. すわなち, スペシャルフォームの数々はあらかじめ定義されており, 固定されている. 詳しくはCLHSの3.1.2.1.2.1節の Special Forms を見るとよい. スペシャルフォームはeval-whenやtheのように, 関数ともマクロとも違う変わった(あるいは興味深い)こともできる. どのスペシャルフォームも自身のセマンティクスを定義している.

関数とマクロ

"変数は値を抽象化する. 関数は振舞いを抽象化する. マクロは構文を抽象化する." Joe Marshall, 23 Mar 2004, [EMAIL PROTECTED]

振舞いの抽象化: 同じコードを何回も書く代わりに, 関数を書いてそれを呼ぶ. するとあなたはコードの振舞いを関数へと抽象化したことになる.

例えば, ボタンのあるウインドウが一つあるとする. そのボタンを押すともう一つのウインドウが現れるようにしたい. そういうときは, そのウインドウを出現させるために一つの関数を書き, ユーザがボタンを押したときにその関数を呼ぶようにすればよい. 他の場所から同じウインドウを出現させるときにも同じ関数を使うことができる.

構文の抽象化: "同じように見える"コードを何度も書く代わりに, マクロを書いてそれを呼ぶ. するとあなたはコードの構文を抽象化したことになる. すなわち, コードのようなものからマクロへと抽象化した.

例えば, あなた自身こういうコードをよく書くでしょう.

(let ((x (do-something)))
 (if x
     (do-something-with x)
     (let ((y (do-something-else)))
      (if y
          (do-something-with y)
           ...))))

そしてこう思うでしょう. 「繰り返し多すぎ! 決まり文句すぎ! もっと良い書き方はないのか!」 そしてそれはあるのだ. あなたは when-let マクロを書き, コードを以下のように変えるとよい.

(when-let ((x (do-something))
           (do-something-with x))
          ((y (do-something-else))
           (do-something-with y))
          (...))

こうすると決まり文句はなくなる. 繰り返しはなくなる. ここであなたは新しい構文を導入したのだ. 同じ構文をどこでも他で使うことができ, コードは同じように振る舞うだろう.