Source code
Jakub T. Jankiewicz
(23 Jan 2024 00:59 UTC)
|
Re: Source code
Jens Axel Søgaard
(23 Jan 2024 01:24 UTC)
|
Re: Source code
Jens Axel Søgaard
(23 Jan 2024 01:48 UTC)
|
Re: Source code Jakub T. Jankiewicz (23 Jan 2024 19:48 UTC)
|
Re: Source code
Wolfgang Corcoran-Mathe
(23 Jan 2024 19:17 UTC)
|
Re: Source code
Jakub T. Jankiewicz
(23 Jan 2024 19:46 UTC)
|
Re: Source code
Wolfgang Corcoran-Mathe
(23 Jan 2024 22:10 UTC)
|
Thanks for the explanation, now I understand. I was looking at the pattern and expansion in isolation. Didn't realized that arg1 was a binding in let-values at full expansion. On Tue, 23 Jan 2024 02:48:26 +0100 Jens Axel Søgaard <xxxxxx@soegaard.net> wrote: > Oh! I forgot about the `args1` in the next clause: > > ((aux %consumer (%producer1 producer2 :::) (temp :::)) > (aux %consumer (producer2 :::) (temp ::: (%producer1 args1)))) > > Here the `args1` appears only in the template. This means that the > identifier `args1` > is (hygienically) introduced here. We see that the template consists of > a call to `aux`. The identifier `args1` will end up as a variable name > in the `let-values` form. > > The round about way the macro is defined, introduces one `args1` per > producer > present in the original macro call. Since each `args1` is introduced in > its own call to `aux` they will get different scopes. That is, > the `let-values` expression will not complain about duplicate identifiers > in the binding clauses. > > /Jens Axel Søgaard > > > Den tirs. 23. jan. 2024 kl. 02.24 skrev Jens Axel Søgaard < > xxxxxx@soegaard.net>: > > > Hi, > > > > Here is the `call/mv` macro: > > > > (define-syntax call/mv > > (syntax-rules () > > ((call/mv consumer producer1 ...) > > (letrec-syntax > > ((aux (syntax-rules ::: () > > ((aux %consumer () ((%producer1 args1) :::)) > > > > (let-values (((proc) %consumer) > > (args1 %producer1) :::) > > (apply proc (append args1 :::)))) > > ((aux %consumer (%producer1 producer2 :::) (temp :::)) > > (aux %consumer (producer2 :::) (temp ::: (%producer1 > > args1))))))) > > (aux consumer (producer1 ...) ()))))) > > > > We are dealing with a macro `call/mv` that expands into a `letrec-syntax` > > form, > > which defines a local macro `aux`. > > > > From > > ((aux (syntax-rules ::: () > > > > we see that `:::` will be used as an ellipsis in both the pattern and > > template of the aux-macro. > > > > The pattern is `(aux %consumer () ((%producer1 args1) :::))` > > and the template is `(let-values ...)`. > > > > We see now that `args1` appears in the pattern - and thus `args1` > > is bound as a pattern variable in the template that follows. > > > > /Jens Axel Søgaard > > > > Den tirs. 23. jan. 2024 kl. 01.59 skrev Jakub T. Jankiewicz < > > xxxxxx@onet.pl>: > > > >> Hi, > >> > >> I have a question about the provided implementation: > >> > >> (define-syntax apply/mv > >> (syntax-rules () > >> ((apply/mv operator operand1 ... producer) > >> (letrec-syntax > >> ((aux (syntax-rules ::: () > >> ((aux %operator () ((%operand1 arg1) :::) %producer) > >> (let-values (((proc) %operator) > >> ((arg1) %operand1) ::: > >> (args %producer)) > >> (apply proc arg1 ::: args))) > >> ((aux %operator (%operand1 operand2 :::) > >> (temp :::) %producer) > >> ;; args1 is not defined > >> (aux %operator (operand2 :::) (temp ::: (%operand1 > >> arg1)) > >> %producer))))) > >> (aux operator (operand1 ...) () producer))))) > >> > >> (define-syntax call/mv > >> (syntax-rules () > >> ((call/mv consumer producer1 ...) > >> (letrec-syntax > >> ((aux (syntax-rules ::: () > >> ((aux %consumer () ((%producer1 args1) :::)) > >> (let-values (((proc) %consumer) > >> (args1 %producer1) :::) > >> (apply proc (append args1 :::)))) > >> ((aux %consumer (%producer1 producer2 :::) (temp :::)) > >> (aux %consumer (producer2 :::) > >> ;; args1 is not defined > >> (temp ::: (%producer1 args1))))))) > >> (aux consumer (producer1 ...) ()))))) > >> > >> > >> It looks like args1 in both macros is unbound. I'm not an expert in > >> Scheme hygienic macros but I'm pretty comfortable with them, and it > >> looks like an error. The macros did work, but I'm not sure if the code > >> is correct. I'm also > >> not sure if I fully understand how those macros work. > >> > >> Where the args1 name (from last nested syntax) come from? > >> > >> The same happen with set!-values macro but with temp1 symbol: > >> > >> (define-syntax set!-values > >> (syntax-rules () > >> ((set!-values (var1 ...) producer) > >> (letrec-syntax > >> ((aux (syntax-rules ::: () > >> ((aux () ((%var1 temp1) :::) %producer) > >> (let-values (((temp1 ::: . temp*) %producer)) > >> (set! %var1 temp1) :::)) > >> ((aux (%var1 var2 :::) (temp :::) %producer) > >> ;; temp1 is not defined here > >> (aux (var2 :::) (temp ::: (%var1 temp1)) %producer))))) > >> (aux (var1 ... ) () producer))) > >> ((set!-values (var1 ... . var*) producer) > >> (letrec-syntax > >> ((aux (syntax-rules ::: () > >> ((aux () ((%var1 temp1) ::: (%var* temp*)) %producer) > >> (let-values (((temp1 ::: . temp*) %producer)) > >> (set! %var1 temp1) ::: > >> (set! %var* temp*))) > >> ((aux (%var1 var2 :::) (temp :::) %producer) > >> ;; temp1 is not defined here > >> (aux (var2 :::) (temp ::: (%var1 temp1)) %producer))))) > >> (aux (var1 ... var*) () producer))) > >> ((set!-values var* producer) > >> (let-values ((temp*) producer) > >> (set! var* temp*))))) > >> > >> I hope that this is not something that yet to learn about Hygienic > >> macros. > >> > >> -- > >> Jakub T. Jankiewicz, Senior Front-End Developer > >> https://jcubic.pl/me > >> https://lips.js.org > >> https://koduj.org > >> > > > > > > -- > > -- > > Jens Axel Søgaard > > > > > -- Jakub T. Jankiewicz, Senior Front-End Developer https://jcubic.pl/me https://lips.js.org https://koduj.org