This example would fail
import sequtils
proc sum*(values: openarray[float]): float = values.foldl(a + b)
echo sum(@[1.0, 2.0])
Although it seems like it should work as foldl implemented with for loop and it should work same way for openarray?
foldl is a template and template arguments are evaluated lazily. To force them to be evaluated it needs to be assigned to a value. This is where the problem occurs, openArray is a "magic" type that can only be used for parameters.
I would like this to be able to work, but I'm not sure how to fix it.
in the case of expensiveProc().foldl(a+b) foldl will not evaluate expensiveProc() len times. Instead, it assigns the sequence to a local variable and performs the operation on that copy but an openArray is not a firstclass type (yet?) and can't be copied.
many ways to make this work:
proc sum*(values: openArray[float]):float = values.toSeq.foldl(a+b)
template sum*(values: openArray[float]):float = values.foldl(a+b)
template sum*(values: untyped): untyped = values.foldl(a+b)
Thanks, these two solutions looks good
values.foldl(a + b, 0)
values.toSeq.foldl(a+b)
As for the template version - hmm, don't like it, as it would continue to contaminate the source code with even more "special" functions. For example if implemented that way the following code would fail.
import sequtils
template sum*(values: openArray[float]):float = values.foldl(a+b)
proc mean(values: openArray[float]):float = values.sum / values.len.to_float
echo mean(@[1.0, 2.0])
generics could work
proc sum*[Cont](values: Cont): float = values.foldl(a + b)
If you want, you could add a concept
type Container[T] = concept cont
cont.len is int
cont[int] is T
for t in items(cont):
t is T
proc sum*(values: Container[float]): float = values.foldl(a+b)
Now it will instantiate a proc that should work correctly for anything that is supplied.
and yep, it'd need to be templates all the way down
But that's not good, a complexities that could be avoided. It would be much better to totally avoid foldl in the first place and just using for loop :).
A case when the cure is worse than the disease.
not good knew you wouldn't like it, and i can't blame you: this incompatibility of foldl with openArray is rubbish (more about openArray's limitations imho)
others will have different use cases, different comfort zones and thus different preferences, i think there's enough options in this thread to suit all tastes
templates are maybe a tiny bit red/blue but they're pretty badass. you'll come around :)