Skip to content

Instantly share code, notes, and snippets.

@brv00
Created August 28, 2018 05:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brv00/077485a1b40aede64cbd94da28459613 to your computer and use it in GitHub Desktop.
Save brv00/077485a1b40aede64cbd94da28459613 to your computer and use it in GitHub Desktop.
;
; receive.scm
;
;; 多くの Scheme 処理系では、receive の伝統的なマクロによる定義は次のようにすれ
;; ば十分である。
;
; (define-macro (receive formals expression . body)
; `(call-with-values (lambda () ,expression) (lambda ,formals . ,body)))
;
;; しかし JScheme でこのように定義すると、おそらく期待されたとおりには動かない。
;; SRFI-8 のドキュメントには書かれていないが、SRFI-1 での receive の使われ方を
;; 見ると body は 末尾コンテキストに置かれることが期待されているようである。
;; body が末尾コンテキストにない場合、例えば
;; https://github.com/scheme-requests-for-implementation/srfi-1/blob/master/srfi-1-reference.scm#L833-L836
;; のループの回数が制限される。
;; そして、JScheme では、call-with-values 呼び出し時の継続と call-with-values の
;; 第2引数呼び出し時の継続が異なるため、上の receive の定義では body が末尾コン
;; テキストに置かれない。
;; そこで、下のように body を call-with-values の外に出して、let シンタックスの
;; 末尾に置いた。let シンタックスの末尾は末尾コンテキストである。
(use-module "/storage/emulated/0/scheme/another-symbol.scm")
;; another-symbol.scm の中身は↓
;; https://gist.github.com/brv00/c0df5b6ad7f58f9158f3fa547f576a2e
(define-macro (receive formals expression . body)
(define lis (another-symbol expression body)) ; gensym の代わり
`(let ((,lis (call-with-values (lambda () ,expression) list)))
(let ,(let lp ((formals formals) (i 0))
(cond ((symbol? formals) `((,formals (list-tail ,lis ,i))))
((null? formals) '())
(else `((,(car formals) (list-ref ,lis ,i))
. ,(lp (cdr formals) (+ i 1))))))
. ,body)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment