* Mixing syntax-rule and indentifier-syntax
@ 2012-01-16 23:11 Tobias Brandt
2012-01-17 9:22 ` Andy Wingo
2012-01-17 21:53 ` Ian Price
0 siblings, 2 replies; 5+ messages in thread
From: Tobias Brandt @ 2012-01-16 23:11 UTC (permalink / raw)
To: guile-user
Hi,
is it possible to define a macro that does one thing when
it's in operator position and another when it's not?
I want to define a macro `with-vectors` that transforms this:
(with-vectors (v)
(v 0)
(set! (v 0) 'foo)
(some-procedure v))
into this:
(begin
(vector-ref v 0)
(vector-set! v 0 'foo)
(some-procedure v))
So far I have this:
(define-syntax with-vectors
(syntax-rules ()
((_ (id ...) exp ...)
(let-syntax ((id* (syntax-rules ()
((_ idx) (vector-ref id idx)))) ...)
exp ...))))
But that obviously only works for the first case: (v 0).
Regards,
Tobias
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Mixing syntax-rule and indentifier-syntax
2012-01-16 23:11 Mixing syntax-rule and indentifier-syntax Tobias Brandt
@ 2012-01-17 9:22 ` Andy Wingo
2012-01-17 21:53 ` Ian Price
1 sibling, 0 replies; 5+ messages in thread
From: Andy Wingo @ 2012-01-17 9:22 UTC (permalink / raw)
To: Tobias Brandt; +Cc: guile-user
On Tue 17 Jan 2012 00:11, Tobias Brandt <tob.brandt@googlemail.com> writes:
> I want to define a macro `with-vectors` that transforms this:
>
> (with-vectors (v)
> (v 0)
> (set! (v 0) 'foo)
> (some-procedure v))
We currently don't have good support in the expander for variable
transformers that take arguments.
You can use a procedure-with-setter, perhaps.
Another option would be to alias specific elements of your vector to
identifiers:
http://thread.gmane.org/gmane.lisp.guile.user/8724/focus=9100
Andy
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Mixing syntax-rule and indentifier-syntax
2012-01-16 23:11 Mixing syntax-rule and indentifier-syntax Tobias Brandt
2012-01-17 9:22 ` Andy Wingo
@ 2012-01-17 21:53 ` Ian Price
2012-01-17 23:26 ` Tobias Brandt
1 sibling, 1 reply; 5+ messages in thread
From: Ian Price @ 2012-01-17 21:53 UTC (permalink / raw)
To: Tobias Brandt; +Cc: guile-user
Tobias Brandt <tob.brandt@googlemail.com> writes:
> Hi,
>
> is it possible to define a macro that does one thing when
> it's in operator position and another when it's not?
It depends what you mean by that. If you mean operator-position/set!
position/ variable position, then that is id-syntax. If you mean
something like
(define-syntax foo
(syntax-rules ()
[(bar foo baz)
(baz bar)]))
(9 foo sqrt) => (sqrt 9)
then no.
> I want to define a macro `with-vectors` that transforms this:
>
> (with-vectors (v)
> (v 0)
> (set! (v 0) 'foo)
> (some-procedure v))
>
> into this:
>
> (begin
> (vector-ref v 0)
> (vector-set! v 0 'foo)
> (some-procedure v))
>
> So far I have this:
>
> (define-syntax with-vectors
> (syntax-rules ()
> ((_ (id ...) exp ...)
> (let-syntax ((id* (syntax-rules ()
> ((_ idx) (vector-ref id idx)))) ...)
> exp ...))))
(define-syntax with-vectors
(syntax-rules ()
((_ (id ...) exp ...)
(let-syntax ((id (make-variable-transformer
(lambda (stx)
(syntax-case stx ()
[(_ idx) #'(vector-ref id idx)]
[idx #'id])))) ...)
exp ...))))
will cover
scheme@(guile−user)> (with-vectors (k) (k 0))
$8 = 1
scheme@(guile−user)> (with-vectors (k) (vector-map (lambda (x) (* x x)) k))
$9 = #(1 4 9)
but not the set!, which is slightly trickier. Since the second argument
to set! must be (in an id-macro) an identifier, we need to do that
conversion first, and AFAICS[0] that means turning the macro inside out,
and walking it for set! forms.
What I do is, walk the inner bodies for set! forms, if they are of the
form (set! (foo bar) baz) where foo is a bound vector, I replace them
with (set! foo (bar baz)). I later correct this in the identifier macro
for foo.
(define-syntax with-vectors
(lambda (stx)
(syntax-case stx ()
((_ (id ...) exp ...)
#`(with-vectors-helper (id ...)
#,@(map (lambda (clause)
(syntax-case clause (set!)
((set! (arg idx) val)
;; if arg is a bound vector
(exists (lambda (x) (bound-identifier=? x #'arg))
#'(id ...))
;; uses original set!, and package up
;; index and value, which we destructure
;; in the id-macro
#'(set! arg (idx val)))
(id #'id)))
#'(exp ...)))))))
(define-syntax with-vectors-helper
(syntax-rules ()
((_ (id ...) exp ...)
(let-syntax ((id (make-variable-transformer
(lambda (stx)
(syntax-case stx (set!)
[(_ idx) #'(vector-ref id idx)]
[(set! id* (idx val))
;; note, it is structured as above
#'(vector-set! id idx val)]
[idx #'id]))))
...)
exp ...))))
scheme@(guile−user)> (define k (vector 1 2 3))
scheme@(guile−user)> (with-vectors (k) (list (k 0) (k (k 1))))
$2 = (1 3)
scheme@(guile−user)> (with-vectors (k) (list k (k 1)))
$3 = (#(1 2 3) 2)
scheme@(guile−user)> (with-vectors (k) (set! (k 0) #f) (list (k 0) k))
$4 = (#f #(#f 2 3))
scheme@(guile−user)> k
$5 = #(#f 2 3)
this set! modification only works at the first level of the with-vectors
form, fixing that is left as an exercise :)
0. I'm sure there is another way, but my mind blanks at the moment
--
Ian Price
"Programming is like pinball. The reward for doing it well is
the opportunity to do it again" - from "The Wizardy Compiled"
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Mixing syntax-rule and indentifier-syntax
2012-01-17 21:53 ` Ian Price
@ 2012-01-17 23:26 ` Tobias Brandt
2012-01-18 16:23 ` Andy Wingo
0 siblings, 1 reply; 5+ messages in thread
From: Tobias Brandt @ 2012-01-17 23:26 UTC (permalink / raw)
To: Ian Price; +Cc: guile-user
> 0. I'm sure there is another way, but my mind blanks at the moment
After you got me started, I was able to simplify and generalize it a bit.
(-> is a GOOPS generic accessor I defined elsewhere. It works with
vectors, arrays, strings, etc ...)
(define-syntax with-accessors (lambda (stx) (syntax-case stx ()
((_ (id ...) exp ...) #`(begin #,@(let (;; checks if
arg is in the list of identifiers (id ...)
(in-list? (lambda (arg) (exists
(lambda (x) (bound-identifier=? x arg))
#'(id ...))))) ;; transform each expression in
exp ... (map (lambda (clause)
(syntax-case clause (set!) ;; setter
((set! (arg idx ...) val)
(in-list? #'arg) #'((setter ->) arg idx ...
val)) ;; getter ((arg
idx ...) (in-list? #'arg)
#'(-> arg idx ...)) (id #'id)))
#'(exp ...))))))))
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Mixing syntax-rule and indentifier-syntax
2012-01-17 23:26 ` Tobias Brandt
@ 2012-01-18 16:23 ` Andy Wingo
0 siblings, 0 replies; 5+ messages in thread
From: Andy Wingo @ 2012-01-18 16:23 UTC (permalink / raw)
To: Tobias Brandt; +Cc: guile-user, Ian Price
On Wed 18 Jan 2012 00:26, Tobias Brandt <tob.brandt@googlemail.com> writes:
>> 0. I'm sure there is another way, but my mind blanks at the moment
>
> After you got me started, I was able to simplify and generalize it a bit.
> (-> is a GOOPS generic accessor I defined elsewhere. It works with
> vectors, arrays, strings, etc ...)
> (define-syntax with-accessors (lambda (stx) (syntax-case stx ()
> ((_ (id ...) exp ...) #`(begin #,@(let (;; checks if
My eyes!!!
;-)
Can you repost, but without having your editor wrap the lines?
Thanks :)
Andy
--
http://wingolog.org/
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-01-18 16:23 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-16 23:11 Mixing syntax-rule and indentifier-syntax Tobias Brandt
2012-01-17 9:22 ` Andy Wingo
2012-01-17 21:53 ` Ian Price
2012-01-17 23:26 ` Tobias Brandt
2012-01-18 16:23 ` Andy Wingo
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).