unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* 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).