used write a lambda using it prepending a ,opt and you will see what the macros expand to like
,opt (lambda (x) (let/ec ret (when x (ret x)) (+ x x))) On Thu, Sep 30, 2021 at 10:46 AM Damien Mattei <[email protected]> wrote: > i do not remember well the technic of this commented code, in this case > note that it is 'break' keyword that cause the current continuation being > called and escaping from the loop to the continuing code... > there is no 'return' here but 'break'. > Damien > > On Thu, Sep 30, 2021 at 5:38 AM adriano <[email protected]> wrote: > > > Il giorno lun, 28/06/2021 alle 03.15 +0200, Taylan Kammer ha scritto: > > > On 28.06.2021 01:10, Damien Mattei wrote: > > > > 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? > > > > > > Hi Damien, > > > > > > This is because of the "hygiene" rule of Scheme, where the notion of > > > "lexical > > > scope" is taken very seriously: for an identifier to be bound, it > > > must be > > > visible in the lexical (textual) surroundings where it has been > > > bound. > > > > > > So for instance, in the following example code: > > > > > > (def (test x) > > > (cond > > > ((= x 3) (return 7)) > > > ((= x 2) (return 5)))) > > > > > > We can't see a binding for "return" anywhere in the text, therefore > > > it cannot > > > be bound. > > > > > > This is good "default" behavior because it makes code more flexible > > > and easier > > > to understand. > > > > > > An easy way of overcoming this issue is to let the user explicitly > > > name the > > > return identifier however they like: > > > > > > (define-syntax def > > > (syntax-rules () > > > ((_ (name ret arg ...) body body* ...) > > > (define (name arg ...) > > > (call/cc (lambda (ret) body body* ...)))))) > > > > > > Now you could define: > > > > > > (def (test return x) > > > (cond > > > ((= x 3) (return 7)) > > > ((= x 2) (return 5)))) > > > > > > Or for instance: > > > > > > (def (test blubba x) > > > (cond > > > ((= x 3) (blubba 7)) > > > ((= x 2) (blubba 5)))) > > > > > > However, sometimes you're sure that you want to make an implicit > > > binding for > > > an identifier, and for those cases you need to write an "unhygienic" > > > macro > > > which can be achieved with the more complex macro system "syntax- > > > case". > > > > > > Here's how your desired macro could be defined. I will use > > > identifiers like > > > "<foo>" just for easier readability; they don't have any special > > > meaning: > > > > > > (define-syntax def > > > (lambda (stx) > > > (syntax-case stx () > > > ((_ (<name> <arg> ...) <body> <body>* ...) > > > (let ((ret-id (datum->syntax stx 'return))) > > > #`(define (<name> <arg> ...) > > > (call/cc (lambda (#,ret-id) <body> <body>* ...)))))))) > > > > > > There's a few things here to take note of: > > > > > > - Unlike with syntax-rules, the syntax-case is contained in a lambda > > > which > > > takes a single argument: a "syntax object" which is passed to > > > syntax-case > > > > > > - Unlike with syntax-rules, the "body" of the macro (where it begins > > > with a > > > 'let') is not immediately part of the generated code; that 'let' is > > > actually > > > executed during compile-time. The body of the macro must result in > > > an > > > object of the type "syntax object" that represents the generated > > > code. > > > > > > - You see that I define a variable called "ret-id" which I bind to > > > the result > > > of the expression: > > > > > > (datum->syntax stx 'return) > > > > > > which means "create a syntax object in the same lexical environment > > > as stx, > > > and is represented by the symbol 'return'." > > > > > > - The actual code generation begins within the #`(...) which is a > > > shorthand > > > for (quasisyntax (...)) just like '(...) is short for (quote > > > (...)). The > > > result of a quasisyntax expression is a syntax object. Basically, > > > it's the > > > most convenient way of creating a syntax object, but like syntax- > > > rules it's > > > also hygienic by default and you need to insert "unhygienic" syntax > > > objects > > > into it explicitly. > > > > > > - Within the quasisyntax, I use #,ret-id which is short for (unsyntax > > > ret-id) > > > to inject the unhygienic syntax object that holds the symbol > > > 'return' into > > > the generated code. > > > > > > For someone used to macros in the Common Lisp or Elisp style, this > > > may seem > > > over-complicated. It's the cost of the "hygienic by default" > > > behavior. > > > > > > By the way I assume that you're just toying around with the language > > > to learn. > > > If you were thinking of using a 'def' macro like this in real code, I > > > would > > > discourage it because there's already a built-in mechanism that > > > allows the > > > programmer something very similar, called 'let/ec': > > > > > > (import (ice-9 control)) > > > > > > (define (test x) > > > (let/ec return > > > (cond > > > ((= x 3) (return 7)) > > > ((= x 2) (return 5))))) > > > > > > > > What does this return (defined with let/ec) do ? > > > > In the orevious versions I could see the call to call/cc so I could > > (somewhat) figure out the "jump" imlpied by calling return > > > > But in this last case, where is the return behaviour defined ? > > > > > > > > >
