* syntax-rules problem @ 2011-04-03 4:34 David Pirotte 2011-04-03 19:16 ` Andreas Rottmann 0 siblings, 1 reply; 3+ messages in thread From: David Pirotte @ 2011-04-03 4:34 UTC (permalink / raw) To: guile-user Hello, guile version: 2.0.0.160-39be this used to work: (define-syntax push* (syntax-rules () ((push* . ?args) (set! (car (last-pair ?args)) (cons* ?args))) )) scheme@(guile-user)> (define ll '(1 2 3 4 5)) scheme@(guile-user)> (push* 'a 'b ll) ERROR: In procedure setter: ERROR: In procedure setter: Wrong type argument in position 1: #<procedure car (_)> Entering a new prompt. Type `,bt' for a backtrace or `,q' to continue. scheme@(guile-user) [1]> ,bt In current input: 3:0 1 (#<procedure a164730 at <current input>:3:0 ()>) In unknown file: 0 (setter #<procedure car (_)>) scheme@(guile-user) [1]> Cheers, David ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: syntax-rules problem 2011-04-03 4:34 syntax-rules problem David Pirotte @ 2011-04-03 19:16 ` Andreas Rottmann 2011-04-05 1:26 ` David Pirotte 0 siblings, 1 reply; 3+ messages in thread From: Andreas Rottmann @ 2011-04-03 19:16 UTC (permalink / raw) To: David Pirotte; +Cc: guile-user David Pirotte <david@altosw.be> writes: > Hello, > > guile version: 2.0.0.160-39be > > this used to work: > > (define-syntax push* > (syntax-rules () > ((push* . ?args) > (set! (car (last-pair ?args)) > (cons* ?args))))) > Well, that's not well-formed code; there two problems here: (1) The first operand to `set!' has to be an identifier; in the expansion of `push*', it is an expression. Actually, that's the rule in plain R5RS and R6RS, but Guile contains hooks for implementing SRFI-17, which allows for expressions in `set!'s first operand; thus you get, with the above definition: scheme@(guile-user)> (use-modules (language tree-il)) scheme@(guile-user)> (tree-il->scheme (macroexpand '(push* 1 2 lst))) $4 = (((@@ (guile) setter) car) (last-pair (1 2 lst)) (cons* (1 2 lst))) And that, when called, yields the error you got (when SRFI-17 is not loaded, as the default binding for `car' doesn't have a setter). After importing SRFI-17, it still won't do what you intended: scheme@(guile-user)> (use-modules (srfi srfi-17)) scheme@(guile-user)> (push* 1 2 lst) <unnamed port>:67:0: In procedure #<procedure 3dcdf00 at <current input>:68:0 ()>: <unnamed port>:67:0: Wrong type to apply: 1 The reason is the second issue: (2) `?args' is a pattern variable holding a list, and; so having `(last-pair ?args)' is not OK: for `(push* 1 2 lst)', it expands to `(last-pair? (1 2 lst))'. So you might quote `?args', but that doesn't help to do what you want, because of the first issue. That the above code worked in Guile 1.8 can be considered an accident (or even a bug, IMHO). A correct version would be: (define-syntax push* (syntax-rules () ((push* elements ... identifier) (set! identifier (cons* elements ... identifier))))) Note that the above relies on R6RS-specified extensions to `syntax-rules' patterns that are not yet available in Guile 1.8. HTH, Rotty -- Andreas Rottmann -- <http://rotty.yi.org/> ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: syntax-rules problem 2011-04-03 19:16 ` Andreas Rottmann @ 2011-04-05 1:26 ` David Pirotte 0 siblings, 0 replies; 3+ messages in thread From: David Pirotte @ 2011-04-05 1:26 UTC (permalink / raw) To: Andreas Rottmann; +Cc: guile-user Hi Andreas, Thank you very much for the explication, very helpful. At the time I wondered how it did work [guile-1.6] since the definition was quite clear about set! , but it did and then I used it :-) [i am not using guile-1.8 but thanks for the advice, which might help other guilers off course] Thanks, David ;; -- Le Sun, 03 Apr 2011 21:16:00 +0200, Andreas Rottmann <a.rottmann@gmx.at> a écrit : > David Pirotte <david@altosw.be> writes: > > > Hello, > > > > guile version: 2.0.0.160-39be > > > > this used to work: > > > > (define-syntax push* > > (syntax-rules () > > ((push* . ?args) > > (set! (car (last-pair ?args)) > > (cons* ?args))))) > > > Well, that's not well-formed code; there two problems here: > > (1) The first operand to `set!' has to be an identifier; in the > expansion of `push*', it is an expression. Actually, that's the > rule in plain R5RS and R6RS, but Guile contains hooks for > implementing SRFI-17, which allows for expressions in `set!'s first > operand; thus you get, with the above definition: > > scheme@(guile-user)> (use-modules (language tree-il)) > scheme@(guile-user)> (tree-il->scheme (macroexpand '(push* 1 2 lst))) > $4 = (((@@ (guile) setter) car) (last-pair (1 2 lst)) (cons* (1 2 lst))) > > And that, when called, yields the error you got (when SRFI-17 is not > loaded, as the default binding for `car' doesn't have a > setter). After importing SRFI-17, it still won't do what you > intended: > > scheme@(guile-user)> (use-modules (srfi srfi-17)) > scheme@(guile-user)> (push* 1 2 lst) > <unnamed port>:67:0: In procedure #<procedure 3dcdf00 at <current input>:68:0 ()>: > <unnamed port>:67:0: Wrong type to apply: 1 > > The reason is the second issue: > > (2) `?args' is a pattern variable holding a list, and; so having > `(last-pair ?args)' is not OK: for `(push* 1 2 lst)', it expands to > `(last-pair? (1 2 lst))'. So you might quote `?args', but that > doesn't help to do what you want, because of the first issue. > > That the above code worked in Guile 1.8 can be considered an accident > (or even a bug, IMHO). > > A correct version would be: > > (define-syntax push* > (syntax-rules () > ((push* elements ... identifier) > (set! identifier (cons* elements ... identifier))))) > > Note that the above relies on R6RS-specified extensions to > `syntax-rules' patterns that are not yet available in Guile 1.8. > > HTH, Rotty ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2011-04-05 1:26 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-04-03 4:34 syntax-rules problem David Pirotte 2011-04-03 19:16 ` Andreas Rottmann 2011-04-05 1:26 ` David Pirotte
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).