hi,
i wanted to create a macro that is used like a function definition and allow return using call/cc:
(define-syntax def
(syntax-rules (return)
((_ (name args ...) body body* ...)
(define name (lambda (args ...)
(call/cc (lambda (return) body body* ...)))))
((_ name expr) (define name expr))))
unfortunaly i got error:
scheme@(guile-user)> (def (test x) (cond ((= x 3) 7) ((= x 2) (return 5)) (else 3)))
;;; <stdin>:2:42: warning: possibly unbound variable `return' scheme@(guile-user)> (test 2)
ice-9/boot-9.scm:1685:16: In procedure raise-exception:
Unbound variable: return
any idea?
Damien
Hi Damien,
first, a preliminary remark: that you have added the identifier `return' to the list of literals of the `syntax-rules' instance is useless; this would only be useful if `return' appeared in the patterns of the left-hand side of the `syntax-rules' rules.
Now to the problem: When a `syntax-rules' macro writes its output, identifiers not coming from the macro call are "renamed" so that they don't interfere with identifiers bound at the macro use site by accident. This is called "macro hygiene". Forexample,
(let ((return (lambda (x) 42)))an ordinary procedure (a continuation, to be more precise); in the second, it is a syntactic keyword.
(def (test) (return 52))
(test))
evaluates to 42.
To write a macro like yours, you can either drop hygiene by injecting `return' in the syntactic environment of the macro call, or you can make `return' a syntax parameter.
The first solution is:
(define-syntax def
(lambda (x)
(syntax-case x ()
((k (name . arg*) body body* ...)
(identifier? #'name)
(with-syntax ((return (datum->syntax #'k 'return)))
#'(define (name . arg*) (call/cc (lambda (return) body body* ...)))))
((_ name expr)
(identifier? #'name)
#'(define name expr)))))
The second solution is hygienic but needs syntax parameters. You can find a full solution here: https://www.gnu.org/software/guile/manual/html_node/Syntax-Parameters.html.
Note that the semantics are different. In the first solution, `return' is lexically bound; in the second solution, `return' is not rebound, but its meaning changes during the expansion of the procedure body. Moreover, in the first solution, `return' is
When the Scheme system has syntax parameters (like Guile), the second solution is probably the better one.
Marc
damien...@gmail.com schrieb am Montag, 28. Juni 2021 um 01:01:53 UTC+2:
hi,
i wanted to create a macro that is used like a function definition and allow return using call/cc:
(define-syntax def
(syntax-rules (return)
((_ (name args ...) body body* ...)
(define name (lambda (args ...)
(call/cc (lambda (return) body body* ...)))))
((_ name expr) (define name expr))))
unfortunaly i got error:
scheme@(guile-user)> (def (test x) (cond ((= x 3) 7) ((= x 2) (return 5)) (else 3)))
;;; <stdin>:2:42: warning: possibly unbound variable `return' scheme@(guile-user)> (test 2)
ice-9/boot-9.scm:1685:16: In procedure raise-exception:
Unbound variable: return
any idea?
Damien
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 296 |
Nodes: | 16 (2 / 14) |
Uptime: | 74:32:22 |
Calls: | 6,657 |
Calls today: | 3 |
Files: | 12,203 |
Messages: | 5,332,523 |
Posted today: | 1 |