|Subject:||Re: Announcing the first stable release of guile-for-loops|
|Date:||Sat, 25 Jan 2020 02:26:50 +0800|
---------- 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 leanerRegardsStefanOn 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.
(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))))))
|[Prev in Thread]||Current Thread||[Next in Thread]|