-
Notifications
You must be signed in to change notification settings - Fork 173
Open
Milestone
Description
The current definition of Control.iterate-until
is as such:
(sig iterate-until (Fn [(Ref (Fn [b] b c) d), (Ref (Fn [b] Bool c) e), b] b))
(defn iterate-until [f pred start]
(let-do [result start]
(while (not (~pred result))
(set! result (~f result)))
result))
This definition hands the ownership of the result
variable to the pred
function, then reuses it for f
, meaning that the variable result
is undefined by the time an attempt to transform it is made.
The compiler gladly warns us about this, but only when used:
You’re using a given-away value `result` at line 20, column 26 in '<$HOME>/.carp/core/Control.carp'.
You’ll have to copy the value using `@`. at <Irrelevant file where I used it>
As per fixing this there are two options, to my understanding:
- Handing a reference to
pred
. This avoids requiring theresult
be able to be copied, but at the expense of changing the function signature. I have made this alteration locally to core, and can confirm it works as expected.
(doc iterate-until "Like `iterate`, but f is applied repeatedly until the predicate `pred` is true.")
(sig iterate-until (Fn [(Ref (Fn [b] b c) d), (Ref (Fn [(Ref b f)] Bool c) e), b] b))
(defn iterate-until [f pred start]
(let-do [result start]
(while (not (~pred &result))
(set! result (~f result)))
result))
- Copying the
result
internally. This avoids changing the function signature, at the expense of requiring theresult
be copyable, and doing so every iteration.
(doc iterate-until "Like `iterate`, but f is applied repeatedly until the predicate `pred` is true.")
(sig iterate-until (Fn [(Ref (Fn [b] b c) d), (Ref (Fn [b] Bool c) e), b] b))
(defn iterate-until [f pred start]
(let-do [result start]
(while (not (~pred @&result))
(set! result (~f result)))
result))
Given the goals of the language I'd strongly suggest The first option, but that's up to you people.