guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: macro helpers


From: Matt Wette
Subject: Re: macro helpers
Date: Tue, 12 Sep 2017 18:10:01 -0700

> On Sep 12, 2017, at 11:09 AM, Stefan Israelsson Tampe <address@hidden> wrote:
> 
> Writing efficient macros is a bit difficult. Let me explain by using an 
> example. The background
> is that I maintaining a python compiler and python like object system and 
> would like to program
> a scheme macro that would be the scheme counterpart to various python 
> construct. For fun
> consider pythons for loop. it's looping depending on iterators and have break 
> and continue.
> 
> Here is a hypothetical for loop:
> 
> (for lp ((x : I)) ((c 1))
>      (lp #:continue (+ x c))
> 
>      #:final
>      c)
> 
> The python iterators signals the end of the loop with raising en exception 
> which is not too costly and we will return the #:final as a value at that 
> point. This is a mix of scheme and python. Now what we
> can do further is to introduce break,continue and break and final as
> 
> (lp #:continue c)   e.g. continue with c
> (lp #:break      c)   e.g. break with c
> (lp #:final)             e.g. execute final with current c
> 
> This has a great potential of a easy generalization of python for loops an 
> implementation could be like, its very slow though, here is a take on the 
> implementation which describes the macro 
> (more work is needed, not a propper pattern here)
> 
> (define-syntax for
>   (lambda (x)
>     (syntax-case x ()
>       ((for lp ((x ... : E) ... (c n) ...) code ... #:final fin ...)
>        (with-syntax (((It ...)       (generate-temporaries #'(O ...)))
>                      ((cc ...)       (generate-temporaries #'(c ...)))
>                      (((x1 ...) ...) (generate-temporaries #'((x ...) ...)))
>                      (((x2 ...) ...) (generate-temporaries #'((x ...) ...))))
>          #'(let ((It E) ... (c n) ... (x 'None) ... ...)
>              (let/ec lp-break
>                (catch IteratorException
>                  (lambda ()
>                    (letrec ((enclosing
>                              (lambda (cc ...)
>                                (set! c cc) ...
>                                (call-with-values
>                                    (lambda () (next It))
>                                  (lambda (x2 ...)
>                                    (set! x1 x2) ...))
>                                ...
>                                (set! x x1)
>                                ... ...
>                                (call-with-values
>                                    (lambda ()
>                                      (let/ec lp-continue
>                                        (define (lp tag . args)
>                                          (cond
>                                           ((eq? tag #:continue)
>                                            (apply lp-continue args))
>                                           ((eq? tag #:break)
>                                            (apply lp-break args))
>                                            ((eq? tag #:final)
>                                              (lp-continuation #:final))))
>                                           code ...))))
>                                  (lambda args
>                                    (if (eq? (car args) #:final)
>                                        (throw IteratorException)
>                                        (apply enclosing (cdr args))))))))
>                      (enclosing c ...)))
>                  (lambda q fin ...)))))))))
>    
> The value of tail position is transfered to the next iteration of the loop. 
> It's not functional. But this is for the full featured version in which lp 
> may be transferred to another function and there inside a loop called e.g.all 
> crazy things, the easy steps would be to have full control in multiple loops.
> Note how this enables great refactoring of functions with many loops inside 
> loops. Anyway for normal loops this is really really slow, and one would 
> really like to have streamlined code when (lp #:continue ...) is used at tail 
> positions and for cases where we can prove that lp is never used in any 
> advanced configuration, we would like to know if lp, (lp #:continue ..) (in 
> tail position) and finally if (lp #:break ...) is used or not. But how to do 
> this at the macro level? I don't think that we
> have any good history of optimizing this case!
> 
> WDYT

I don't quite understand why this is a macro issue.  Is there efficient code, 
in this patterh, you could 
write by hand that is not done by macro?  My guess is you are looking for a 
clean pattern for efficient
execution of python for-loops.  Why not start with a list of possible 
implementations, try them out, and 
then work to develop your syntax-pattern?  You could try prompts or 
continuations maybe.  I make :( when
I see set! in your pattern, BTW.

Matt

CC to guile-user as this may be of interest there.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]