Open marcoct opened 8 years ago
That's actually intentional, and aligns with usage in other languages. Here's the mnemonic:
(for_each <short expression giving collection>
(lambda (x) (do
<long
expression
defining
action>))) ; Like a for loop in another language
versus
(mapM <short expression giving action function>
<long
expression
defining
collection,
maybe
as
a
chain
of
filters>)
Or, in English, "For each one of these, do this thing", vs "Map this operation over this collection".
The one confusing comparable is Scheme, whose for_each
has the action-collection argument order, which I have been constantly annoyed by because the action argument tends to be a big lambda expression, and then the tiny expression for the collection dangles off the end, disconnected from the for_each
token itself.
Now that you know the rationale, do you think anything needs to be done? Do you still think it's appropriate to change the argument order? Do you think it should be documented better in some way? Or should we just close the ticket?
One issue is that there are actually two differences between mapM and foreach, the other one being that mapM returns the list of results. Should we actually have four of them (like in Haskell, mapM/mapM/forM/forM_)? Should they just always construct the list of results, at some runtime overhead that may or may not be significant compared to the action body? Should they somehow automatically infer whether or not the list is needed?
Perhaps adding the mnemonic to the documentation would assist in learnability of the language? I'm not sure where this sort of non-spec documentation is supposed to go.
Because the order is different, I can never remember which one is which order, and I have to look it up every time:
for_each(objs : list<a>, act : proc(a) -> <inference action>)
mapM(act : proc(a) -> <inference action returning b>, objs : list<a>)