Is recursion the only way to write something like a for-loop in the Racket dialect sdp ("Schreibe dein Programm!"), in which "(for)" isn't a thing or is there a more "efficient" or simpler way to do so?

What would the closest equivalent to the C++ loop for(i = 0 , i < 100, i++) look like in Racket-sdp code?

How I did this up until now was:

(: my-loop (natural -> %a))(define my-loop(lambda (i)(cond[(< i 100) (my-loop (+ i 1))] ; <-- count up by one till 99 is reached[else "done"] ; <-- end)))(my-loop 0)

EDIT:

It's more of a general question. If I were to write lets say a raket library which contains a general function, that might be used like this:

(for 0 (< i 100) (+ i 1) (func i))

in my programs which is a for-loop that runs with a given function as it's "body", would there be a way to implement this properly?

2

Best Answer


[Professor of the mentioned course here.]

Recursion indeed is the only way to express iterated computation in the Racket dialect we are pursuing. (Yes, that's by design.)

Still, higher-order functions (and recursion) provide all you need to create your own "loop-like control structures". Take the following HOF, for example, which models a repeat-until loop:

(: until ((%a -> boolean) (%a -> %a) %a -> %a))(define until(lambda (done? f x)(if (done? x)x(until done? f (f x)))))

Note that the until function is tail-recursive. You can expect it to indeed behave like a loop at runtime — a clever compiler will even translate such a function using plain jump instructions. (We'll discuss the above in the upcoming Chapter 12.)

You can make a high-order for-loop.Here is an simple example:

(define (for start end f)(define (loop i)(when (< i end)(f i)(loop (+ i 1))))(loop start))(for 0 10 (λ (i) (displayln i)))

You can make this more general if you use a next function instead of (+ i 1) and use a while-predicate? function instead of (< i end).