Why is Flatten implemented the way it is?
Yves Jaradin
yjaradin at info.ucl.ac.be
Thu Mar 24 14:43:57 CET 2005
Hello,
Contrary to my expectations, I found List.flatten to be non-incremental
(no result is available until the whole structure has been processed). I
supposed that Flatten was implemented as:
local
fun{Flatten2 Xs End}
case Xs
of nil then End
[] H|T then {Flatten2 H {Flatten2 T End}} % rather than the
incremental: []H|T then R I in {Flatten2 H I R} {Flatten2 T End I} R
else Xs|End
end
end
in
fun{Flatten Xs}
{Flatten2 Xs nil}
end
end
which is not incremental due to the order of the execution of the two
recursive-calls (first on T, then on H) but Flatten is implemented as:
local
fun {DoFlatten Xs Start End}
case Xs of
X|Xr then S S1 in
if {DoFlatten X S S1}
then S=Start {DoFlatten Xr S1 End}
else S2 in Start=X|S2 {DoFlatten Xr S2 End}
end
[] nil then Start=End true
else false
end
end
in
fun {Flatten X}
Start in if {DoFlatten X Start nil} then Start else X end
end
end
which isn't equivalent :
Test case -> result with first impl. -> result with actual impl.
{Flatten a|[b c d]|nul} -> [a b c d nul] -> a|[b c d]|nul
{Flatten a} -> [a] -> a
How is the actual implementation better than the simple one? (I assume
that there was a reason for this design)
The main problems I see are:
* the result is not guaranteed to be a list (complicates proofs of
correctness)
* impossibility to have a completely incremental implementation
equivalent to the current one (bad for lazy programming)
The current implementation of Flatten is also different from the rest of
the List module in it's treatment of '|'-labeled tuples with a non-list
second member. Those are errors in all the other cases but for Flatten
they are just non-list values.
('|'-labeled tuples with a non-list second member are most probably
erroneous constructs, so we don't really care of how they are
transformed, do we?)
I didn't found any occurrence of Flatten depending on those border cases
in share/lib (I didn't verified the occurrences in contrib, doc,
share/test and share/tools)
Has someone ever written code depending on this behavior? (which isn't
documented, documentation for Flatten isn't precise at all)
Are those problems worth an incompatible change in future releases?
Thanks in advance,
Yves Jaradin
More information about the mozart-hackers
mailing list