Luke Palmer wrote:
forall was about concurrency, not order of evaluation. There is a difference
between running in an arbitrary order serially and running in parallel.
for %bag {
.say;
}
If the bag had elements "hello", "world", I think printing:
helworld
lo
Would definitely count as violating the principle of least surprise.
For the specific case of C<say>, I think that its implementation should
probably be "is critical" -- The C<say> method is designed for simple
user messages, and atomicity is probably as useful as the auto-newline
for its intended usage. But your general message still stands:
concurrency can surprise if not handled properly.
Just thinking out load, perhaps one could say that the following
constructs are broadly equivalent:
* for %bag { .say };
* forall %bag { is locally_critical; .say };
(lets assume for now that "is locally_critical" is like "is critical"
but protects only against child-threads of the ::OUTER scope)
Now lets change the definition of curlies such that they always imply
this modified "is locally_critical" trait. Now, the following would be
equivalent:
* for %bag { .say };
* forall %bag { isnt locally_critical; .say };
From here I'll just make one more proposal: a new form of curley:
* for %bag { .say }; // unordered sequential ("locally_critical")
* for %bag {{ .say }}; // unordered concurrent (not "locally_critical")
With these modified forms of braces it becomes much easier to define
safe concurrent control structures: the default curlies force the
additional safety yet there's a simple alternative that increases
concurrency without requiring a new statement (but one would still need
a special form of splat operator to morph a sequential container for
unordered iteration -- so maybe the general unordered "forall" statement
would still be useful)