[Top][All Lists]

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

Fwd: Announcing the first stable release of guile-for-loops

From: Stefan Israelsson Tampe
Subject: Fwd: Announcing the first stable release of guile-for-loops
Date: Fri, 24 Jan 2020 13:13:08 +0100

---------- Forwarded message ---------
From: Stefan Israelsson Tampe <address@hidden>
Date: Fri, Jan 24, 2020 at 12:42 PM
Subject: Re: Announcing the first stable release of guile-for-loops
To: Linus Björnstam <address@hidden>

Would be cool to have those implemented in guile, that would make my guile-syntax-parse a bit leaner


On Thu, Jan 23, 2020 at 3:03 PM Linus Björnstam <address@hidden> wrote:
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))

The code and documentation is available here:

A web-friendly documentation can be found here:

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

reply via email to

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