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?
CodePudding user response:
[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.)
CodePudding user response:
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)
.