guile-user
[Top][All Lists]
Advanced

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

Announcing the first actually stable release of guile-for-loops


From: Linus Björnstam
Subject: Announcing the first actually stable release of guile-for-loops
Date: Thu, 23 Jan 2020 13:10:46 +0100
User-agent: Cyrus-JMAP/3.1.7-775-g74f2d12-fmstable-20200121v1

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



reply via email to

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