書いてみると別にどうということはありませんね・・・。
なぜ define-overload という名前かというと、始めて defn を見たときの感想が C# のオーバーロードっぽいなぁだったので。。かっこいい名前が思いつきませんでした。そういや syntax-rules にも似てますよね。
まずはマクロを書く前に展開イメージを
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(use util.match) | |
;; image | |
(define-overload fact | |
((n) | |
(fact n 1)) | |
((n acc) | |
(if (zero? n) | |
acc | |
(fact (- n 1)(* n acc))))) | |
;; expand image | |
(define (fact . args) | |
(match args | |
((n) | |
(fact n 1)) | |
((n acc) | |
(if (zero? n) | |
acc | |
(fact (- n 1)(* n acc)))))) | |
(fact 5) | |
;; 120 | |
(use slib) | |
(require 'trace) | |
(trace fact) | |
(fact 5) | |
;; CALL fact 5 | |
;; CALL fact 5 1 | |
;; CALL fact 4 5 | |
;; CALL fact 3 20 | |
;; CALL fact 2 60 | |
;; RETN fact 120 | |
;; RETN fact 120 | |
;; RETN fact 120 | |
;; RETN fact 120 | |
;; RETN fact 120 | |
;; 120 | |
(untrace fact) | |
(use liv.debugs) | |
(debug :fact) | |
(define (fact . args) | |
(match args | |
((n) | |
(dbg :fact ";; fact n = ~a" n) | |
(fact n 1)) | |
((n acc) | |
(dbg :fact ";; fact n = ~a, acc = ~a" n acc) | |
(if (zero? n) | |
acc | |
(fact (- n 1)(* n acc)))))) | |
(fact 5) | |
;; fact n = 5 | |
;; fact n = 5, acc = 1 | |
;; fact n = 4, acc = 5 | |
;; fact n = 3, acc = 20 | |
;; fact n = 2, acc = 60 | |
;; fact n = 1, acc = 120 | |
;; fact n = 0, acc = 120 | |
120 |
以下マクロ本体
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(use util.match) | |
(define-syntax define-overload | |
(syntax-rules () | |
((_ name ((arg ...) body ...) ...) | |
(define (name . args) | |
(match args | |
((arg ...) body ...) ...))))) | |
(macroexpand '(define-overload fact | |
((n) | |
(fact n 1)) | |
((n acc) | |
(if (zero? n) | |
acc | |
(fact (- n 1)(* n acc)))))) | |
;; (#<identifier user#define> | |
;; (fact . #0=#<identifier user#args>) | |
;; (#<identifier user#match> #0# | |
;; ((n) | |
;; (fact n 1)) | |
;; ((n acc) | |
;; (if (zero? n) | |
;; acc | |
;; (fact (- n 1) (* n acc)))))) | |
(fact 5) | |
;; 5 | |
(define-overload greeting | |
(()(greeting "world")) | |
((name)(print #`"Hello, ,|name|!!"))) | |
(greeting) | |
;; Hello, world!! | |
;; #<undef> | |
(greeting 'valvallow) | |
;; Hello, valvallow!! | |
;; #<undef> | |
0 件のコメント:
コメントを投稿