which uses a Javascript for loop to calculate the final accumulator value.
It is not obvious to me how this short circuits. Is there some underlying Javascript optimisation that discovers that the accumulator will stay False once it becomes False in the for loop? If yes, how does it work? If no, what is it that makes it possible to short circuit?
I think the accumulator soFar becomes False and then the expression soFar && isOkay element never evaluates the isOkay element bit sionce && short circuits. But it will still loop over the entire array, all the way to the end.
You could experiement by changing the all code to:
all : (element -> Bool) -> (Array element -> Bool)
all isOkay =
Array.foldl
(\element soFar -> isOkay element && soFar)
True
This makes perfekt sense. The && operator short circuits but not the foldl itself.
I got curious in the first place, since folds usually have not way of short circuiting. But, since I only introduced log messages in the ìsOkay function I wrongly got the impression of the whole Array.Extra.all short circuiting.
If I really want/need a short circuit version of Array.Extra.all I guess I will have roll my own recursive function like this:
all : (a -> Bool) -> Array a -> Bool
all isOkay array =
let
step index =
case Array.get index array |> Maybe.map isOkay of
Just True ->
step (index + 1)
Just False ->
False
Nothing ->
True
in
step 0
Turns out this has already been tested and evaluated by the Array.Extra developers. Since arrays in Elm are implemented using som kind of trees (for sharing of immutable data) array look up in Elm is not O(1). Read more here.
You can always write a version of fold that has an optional break in it:
type Next a = Cont a | Break a
foldl : (a -> b -> Next b) -> b -> List a -> b
foldl fn acc vals =
case vals of
[] -> acc
v :: vs ->
case fn v ac of
Cont newAcc -> foldl fn newAcc vs
Break newAcc -> newAcc
With Arrays I iterated over a slice using Array.get:
This was used to implement a GapBuffer for a text editor. I certainly found that doing it this way was efficient enough to get a UI that scrolled smoothly. But yes, the Array.get access is O(Log n), so not as fast as it could be: