unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* Announcing the first stable release of guile-for-loops
@ 2020-01-23 12:03 Linus Björnstam
       [not found] ` <CAGua6m3=DU=G3jkPqMxX5Bw6r4p394Uh3fV6KeUbrf-_iqxAeQ@mail.gmail.com>
  0 siblings, 1 reply; 4+ messages in thread
From: Linus Björnstam @ 2020-01-23 12:03 UTC (permalink / raw)
  To: guile-devel

Hiya everybody!

I have spent some time implementing efficient for loops for guile, and they are baked and ready to go. I have worked the last weeks at implementing generalized support for non-tail-recursive loops and am happy to announce for/foldr. It is a generic right fold, with support for delaying it's arguments as either thunks or promises. 

The syntax is more or less the same as racket's loops, and they are generally compatible. The code generated is for almost all cases as fast as hand-rolled code. They are all expressed as left or right folds, and are as such (apart from for/list, but read about that in the documentation) free of mutation. They are all converted to named lets. 

Some examples:

(for/list ((a (in-range 1 6)))
  (* a a)) ;; => (1 4 9 16 25)

(for*/list ((a (in-string "ab")) (b (in-range 1 3)))
  (list a b)) 
;; => ((#\a 1) (#\a 2) (#\b 1) (#\b 2))

There are many more looping constructs, among others: 
for/sum, for/vector, for/or, for/and, for/first, for/last and a side-effecting simple for.

Here is a sieve of erathostenes:

(define (erathostenes n)
  (define vec (make-vector n #t))
  (for/list ([i (in-range 2 n)] #:when (vector-ref vec i))
    (for ([j (in-range/incr (* 2 i) n i)])
      (vector-set! vec j #f))
    i))

The code and documentation is available here: 
https://hg.sr.ht/~bjoli/guile-for-loops

A web-friendly documentation can be found here: 
https://man.sr.ht/%7Ebjoli/for-loops-docs/for-loops.md

The thing I had been waiting for is right fold. That allows us to write loops like guile's map: non-tail recursive:
(for/foldr ((identity '())) ((a (in-list '(1 2 3))))
  (cons (* a a) identity))

becomes equivalent to:

(let loop ((random-identifier '(1 2 3)))
  (if (null? random-identifier)
      '()
      (let ((a (car random-identifier)))
        (cons (* a a) (loop (cdr random-identifier))))))

Happy hacking
Linus Björnstam



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-01-24 21:23 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-23 12:03 Announcing the first stable release of guile-for-loops Linus Björnstam
     [not found] ` <CAGua6m3=DU=G3jkPqMxX5Bw6r4p394Uh3fV6KeUbrf-_iqxAeQ@mail.gmail.com>
2020-01-24 12:13   ` Fwd: " Stefan Israelsson Tampe
2020-01-24 18:26     ` Nala Ginrut
2020-01-24 21:23     ` Fwd: " Linus Björnstam

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