なぜLISPで独自言語が作れるのか

具体例:簡単な独自言語を作ってみる

目標:レシピ管理言語

;; こんな感じで書きたい(独自言語)
(recipe カレー
  (材料
    (玉ねぎ 2個)
    (にんじん 1本)
    (じゃがいも 2個))
  (手順
    (切る 玉ねぎ さいの目)
    (炒める 玉ねぎ "キツネ色になるまで")
    (加える 水 500ml)))
;; 展開後の一般的なLISPコード
(defun カレー ()
  (let ((ingredients 
         '((onion 2 :unit "個")
           (carrot 1 :unit "本")
           (potato 2 :unit "個"))))
    (prepare-recipe
      (cut :target 'onion :style 'dice)
      (saute :target 'onion :until "キツネ色になるまで")
      (add :item 'water :amount 500 :unit "ml"))))

マクロの実装

(defmacro recipe (name &rest body)
  `(defun ,name ()
     ...))
(defmacro 材料 (&rest items)
  ...)
(defmacro 手順 (&rest steps)
  ...)

独自言語設計のポイント

発展例:実用的な独自言語

Lispマクロの基本構文

マクロ定義の基本形

defmacro マクロ名 (引数リスト) 本体

引数リストで使える特殊記号

バッククォート記法

バッククォートの例

(let ((x 5) (lst '(2 3)))
  `(1 ,x ,@lst))
;; => (1 5 2 3)

実践的なマクロ例

(defmacro my-when (condition &rest body)
  `(if ,condition
       (progn ,@body)))

展開例

;; マクロ使用
(my-when (> x 0)
  (print "正の数")
  (print x))
;; 展開結果
(if (> x 0)
    (progn 
      (print "正の数")
      (print x)))

マクロ展開の注意点

マクロ使用時のデバッグ

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS