Skip to content

Instantly share code, notes, and snippets.

@Yoxem
Last active January 24, 2018 17:40
Show Gist options
  • Save Yoxem/e9255fef767270d2df86dfaee29a6cd6 to your computer and use it in GitHub Desktop.
Save Yoxem/e9255fef767270d2df86dfaee29a6cd6 to your computer and use it in GitHub Desktop.
scheme 系 (define-syntax) (syntax-rule) 的用法舉隅
;; #lang r5rs -> scheme R5Rs
;; scheme 系 (define-syntax) (syntax-rule) 的用法舉隅(有關巨集 macro)
;;; 求算平方和,sqrt-num 是巨集名稱
;; 期望輸出結果
; (sqrt-sum 2) => 4 (回傳值,= 2^2)
; (sqrt-sum 1 3) => 10 (=1^2+3^2)
; (sqrt-sum 1 3 5) => 35 (=1^2+3^2+5^2)
(define-syntax sqrt-sum
(syntax-rules ()
((_ x) ; 一元引數時。底線_代表 sqrt-num 這個函數,當然也可以直接寫成 sqrt-num。下同
(* x x)) ; 處理方法
((_ x y ...) ; 二元以上引數
(+ (_ x)(_ y ...))) ; 處理方法,可遞迴表示
)
)
;; 另一種寫法,利用尾遞迴來避免堆棧耗用過度
(define-syntax sqrt-sum
(syntax-rules ()
((_ x) ; 一元引數時。底線_代表 sqrt-num 這個函數,當然也可以直接寫成 sqrt-num。下同
(* x x)) ; 處理方法
((_ x y ...) ; 二元以上引數
(begin ; 執行多個指令
; 定義尾遞迴表示
(define (sqrt-sum-iter a arg-list)
(if (eq? arg-list '()) a ; 若 arg-list 為空,傳回值
;; else 去 arg-list 頭,將頭的平方和加到 a
(sqrt-sum-iter
(+ a (* (car arg-list) (car arg-list)))
(cdr arg-list))
)
)
(sqrt-sum-iter 0 (list x y ...))) ; 處理方法,可用尾遞迴表示,避免堆棧使用過多
)
)
)
;; syntax-case 的使用,在 racket 可以用,但 Drracket 附隨的 scheme r5rs不行
;(define-syntax sqrt-sum
; (lambda (stx) ;; 要加
; (syntax-case stx ()
; ((_ x)
; (syntax (* x x))) ;; 執行的動作,要包 syntax
; ((_ x y ...)
; (syntax (+ (sqrt-sum x) (sqrt-sum y ...)))) ;; syntax 內不能使用 _ 表示原本函數
; )))
; syntax-case 的使用,在 racket 可以用,但 Drracket 附隨的 scheme r5rs不行
; 另一種寫法,stx 表示 sqrt-num 的參數
;(define-syntax (sqrt-sum stx)
; (syntax-case stx () (
; ((_ x) ; lambda (stx) 等不要加
; (syntax (* x x))) ;; 執行的動作,要包 syntax
; ((_ x y ...)
; (syntax (+ (sqrt-sum x) (sqrt-sum y ...)))) ;; syntax 內不能使用 _ 表示原本函數
; ))
;; 其他關於 macro 可以參考:https://artyom.me/learning-racket-2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment