unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* Re: macro helpers
       [not found] <CAGua6m0YzVx+tvZG7uW4rYbhOHAM_SOdh8Vnot8iHE8nux-Z6w@mail.gmail.com>
@ 2017-09-13  1:10 ` Matt Wette
  0 siblings, 0 replies; only message in thread
From: Matt Wette @ 2017-09-13  1:10 UTC (permalink / raw)
  To: Stefan Israelsson Tampe; +Cc: Guile User Mailing List, guile-devel


> On Sep 12, 2017, at 11:09 AM, Stefan Israelsson Tampe <stefan.itampe@gmail.com> 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.





^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2017-09-13  1:10 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CAGua6m0YzVx+tvZG7uW4rYbhOHAM_SOdh8Vnot8iHE8nux-Z6w@mail.gmail.com>
2017-09-13  1:10 ` macro helpers Matt Wette

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).