Repository navigation
Is replication enabled in imperative blocks? #13
Description
Activity
For historical reference:
- In the original design of the language it wasn't. The idea was that in imperative mode you were taking a very explicit control over the execution sequencing.
- In the implementation, this wasn't done quite right, so it often did do replicated dispatch
- For UX, I'm unsure whether the original decision was the right one. In the design experiments where we removed the explicit [Imperative] blocks, it's really bad to have the hidden dependency of the semantics changes. You use an if statement so suddenly all your function calls work differently :(
- However if you have Imperative do replication, there are follow on design issues, such as why doesn't 'if' replicate? Should 'For' replicate? What happens if we're dispatching a closure in Imperative mode?
Looking forwards to seeing what you decide and how it plays out :)
My gut feeling is that replication should be disabled in imperative blocks.
As @lukechurch so kindly pointed out, replication in imperative blocks behaves badly with other language constructs.
Suppose the
whilestatement replicated. We'd have to do one invocation, execute the body for side effects, then the next replication call... For example:i = 1; while ( i < {3,4,5} ){ i = i + 1; }Would this be?
while ( 1 < 3 ){ i = i + 1; }
while ( 2 < 4 ){ i = i + 1; }
while ( 3 < 5 ){ i = i + 1; }
...Side effects and replication are not such good bed partners. Replication should be expected to terminate. If we keep data structures finite*, function call replication should be guaranteed to terminate.
So, let's assume while loops (and similar constructs) do not replicate.
Consider if function calls replicated in imperative blocks. Here's a good one:
a = 0..3; b = [Imperative](a){ i = 1; l = {}; while (i < a){ // A l = Append(l, i); i = i+1; } return l; }The line commented with A looks like this after variable substitution:
while ( 1 < {1,2,3} ){ ... }The result of
1 < {1,2,3}with replication is a compound value. If compound values are considered "truthy" (currently they are), that line would thus bewhile (true) { ... }. Not so intuitive.*There is nothing in the spec indicating data structures should be finite and its nontrivial to enforce.
@pboyer In general I agree.
Side effects and replication are not such good bed partners.
Aside from the alarming metaphor here...
I think it does depend somewhat on the side effect. Just like elsewhere map operators can have very useful side effects (e.g. compressing all the files they're mapped over). I think the point is that for this to be a comprehensible model the side effects shouldn't be visible inside the different executions that of the map operator. This is also important for the aspect of the specification that says that the order of a replicated dispatch is not defined. Sadly this form of isolation is tricky to enforce on top of the .NET object model. So instead I opted to rely on trying to use scoping to nudge people away from global state munging inside replicated calls.
Replication should be expected to terminate. If we keep data structures finite*, function call replication should be guaranteed to terminate.
I think you also need to assume that the functions being called terminate, or do you that for finite data structures the number of function call dispatches that any given replication will generate should be guaranteed to be finite?
Yes, I was more concerned about cyclic data structures here. I'm proposing that the traversal of the data structure, necessary for replication, needs to terminate. That is not totally free.