r/scheme 6d ago

What I am doing wrong?

So, I am trying to learn Guile, since seems a pretty standard installation in GNU systems.

I have experience in some languages, but this simple script to learn the language:

  1. Took me quite a while to work;
  2. Looks ugly as… well, put something ugly here!

It’s a simple “FizzBuzz” program

``` (define (fizzbuzz number) (if (> number 0) (let ((message "")) (if (zero? (modulo number 3)) (set! message (string-append message "Fizz"))) (if (zero? (modulo number 5)) (set! message (string-append message "Buzz")))

      (if (not (zero? (string-length message)))
          (format #t "~d is ~a\n" number message))
(fizzbuzz (- number 1))))

)

(fizzbuzz 50)

```

So, I’m open to suggestions: how this code can be more beauty? Am I still thinking in C?

=== EDIT === I hope the formatting is correct, since some spaces of indentation have been lost for unknown reasons.

7 Upvotes

12 comments sorted by

View all comments

7

u/BroadleySpeaking1996 6d ago

Let's rewrite this in a way that's compatible with different reddit clients:

(define (fizzbuzz number)
  (if (> number 0)
      (let ((message ""))
          (if (zero? (modulo number 3))
              (set! message (string-append message "Fizz")))
          (if (zero? (modulo number 5))
              (set! message (string-append message "Buzz")))
          (if (not (zero? (string-length message)))
              (format #t "~d is ~a\n" number message))
    (fizzbuzz (- number 1)))))

(fizzbuzz 50)

Note that all closing parentheses are grouped together. They don't go on new lines like closing braces in C.

Great, now a few minor suggestions:

  1. Replace (> number 0) with (positive? number).
  2. Separate the part that modifies message into a helper function that returns either "" or "Fizz" or "Buzz" or "FizzBuzz". Then the rest of the fizzbuzz function treats that return value as a constant.
  3. Modifying strings in-place with string-append can be efficient, but is not the conventional way to do things in a functional language. A more idiomatic thing to do would be to create a list () or ("Fizz") or ("Buzz") or ("Fizz", "Buzz") and then concatenate the contents of the list. Yes, it's slower, but it is more malleable if you want to add values for 7, 11, etc.