[Top][All Lists]

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

Re: guile studio

From: Kjetil Matheussen
Subject: Re: guile studio
Date: Sat, 19 Jun 2021 14:13:57 +0200

> From: jerry <>
> I am fairly new to guile and scheme. People tell me that I should use a
> functional style.
> I have 3 solutions for project euler problem #1. The first is
> functional, the second is imperative and the third is written in "Little
> Schemer" style.
> I was hoping other guile users would comment on preferences or the
> "correct way". Sorry in advance for any wrapping problems that may occur.
> #!/usr/local/bin/guile  -s
> !#
> (use-modules (srfi srfi-1) (jpd stdio)) ;; for folds
> (define N 1000)
> (define ans
>    (fold + 0
>      (filter
>        (lambda (x) (or (= 0 (modulo x 3)) (= 0 (modulo x 5))))
>        (iota N))))
> (print ans)

For minor calculations, I would say this is fine. It's not hard to
understand what this function does. However, the more complicated a
function is, the harder this style will be to read, compared to a
recursive style (example 3). So in general I would recommend never to
use fold, but that's probably somewhat a matter of taste. Personally I
never use fold.

> (define ans 0)
> (for i N
>    (if (or (= 0 (modulo i 3)) (= 0 (modulo i 5))) (set! ans (+ ans i))))
> (print ans)

Same here. For minor calculations, this is fine. In fact, this way is
probably much easier to read than the first example. However, if you
start using 'set!' on more than one variable, things can get very
messy. Regarding performance, this might be both faster or slower
depending on the scheme implementation.

> (define ans
>    (let loop ((i 1) (ans 0))
>      (cond
>        ((>= i N) ans)
>        ((or (= 0 (modulo i 3)) (= 0 (modulo i 5))) (loop (1+ i) (+ ans i)))
>        (else (loop (1+ i) ans)) )))

Please note that this way is also functional. This way is also more
efficient than example #1 since the program can do tail call
optimization and doesn't have to allocate lists. In addition, if you
had formatted this version properly I would have consider this version
to be easier to read than example #1.

Also note that if N is not too big (so that tail call optimization
doesn't matter), the following version would be even simpler:

(define ans
  (let loop ((i 1))
    (cond ((>= i N)
          ((or (= 0 (modulo i 3))
               (= 0 (modulo i 5)))
           (+ i
              (loop (1+ i))))
           (loop (1+ i))))))

Training yourself to read and write functions this way is probably a
good exercise. After a while you are able to easily make very advanced
functions by using recursive functions. Also note that using less
number of lines in a function does not make the function easier to

reply via email to

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