Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Junction short-circuiting clarification #2120

Closed
loops opened this issue Jun 24, 2018 · 7 comments
Closed

Junction short-circuiting clarification #2120

loops opened this issue Jun 24, 2018 · 7 comments

Comments

@loops
Copy link

loops commented Jun 24, 2018

The problem

https://docs.perl6.org/type/Junction says:

"The type of a Junction does not affect the number of items in the resultant Junction after autothreading."

but in the next sentence it says "the compiler is allowed to short-circuit autothreading".
If a Junction result is always the same size until put into boolean context, where would it ever get short-circuited? Every element must always be evaluated and not short-circuited in order to produce the full junction -- correct? There doesn't seem to be an opportunity for a compiler to short circuit.

Suggestions

Either remove the mention of short circuiting if it is indeed impossible, or give an example of where short-circuiting can happen with junctions.

@zoffixznet
Copy link
Contributor

I updated in 2c92134

See if it makes it clearer and if yes, then close the issue.

Thanks.

@loops
Copy link
Author

loops commented Jun 24, 2018

Hi zoffixznet,

Thanks so much for taking a look at this. So it is now clear that short-circuiting can happen in a boolean context. Testing seems to show it is not currently the case with Rakudo, but I understand the possibility remains and needs to be considered.

But to be clear, is short-circuiting guaranteed to not be a problem here:
my $x = a() | b() | c()
are a, b, and c, guaranteed to be called since the junction is not in a boolean context?

Is it correct to say that most Junctions do not have a problem with short-circuiting. Junctions "none", "all", and "one", must evaluate every element in the junction to determine their boolean value so could never be short-circuited by any compiler.

Can this be stated explicitly in the docs if it is true?

Edit: Ooops, the "none" junction could short circuit as soon as it sees any true value. And as mentioned below, the others can as well. Thanks pmichaud.

@pmichaud
Copy link
Collaborator

[...] Junctions "none", "all", and "one", must evaluate every element in the junction to determine their boolean value so could never be short-circuited by any compiler.

Not so:
A "none" junction can short circuit as false once it encounters a true result.
A "all" junction can short circuit as false once it encounters a false result.
A "one" junction can short circuit as false once it encounters a second true result.

Pm

@zoffixznet
Copy link
Contributor

zoffixznet commented Jun 24, 2018

Testing seems to show it is not currently the case with Rakudo
are a, b, and c, guaranteed to be called since the junction is not in a boolean context?

Now that I think more of it, we should remove the short-curcuiting portion entirely. It's already implemented in Rakudo, but it's really just a regular optimization in the Junction.defined/Junction.Boolmethods, with no real impact on users' code, unlike, say, short-curcuiting with and/or operators.

Unless there's some extra design planned I'm not aware of?

my $x = a() | b() | c()

The above just creates an any Junction. The a, b, and c calls are always gonna be called to get the values to create the Junction with.

<Zoffix__> m: sub z { say "called with $^v" }; z 1 | 2 | 3
<camelia> rakudo-moar e9351cbaa: OUTPUT: «called with 1␤called with 2␤called with 3␤»

The above will always call sub z three times, to get the values to construct the return Junction with.

<Zoffix__> m: sub z { $^v }; say so z 1 | 2 | 3
<camelia> rakudo-moar e9351cbaa: OUTPUT: «True␤»

The above will always call sub z three times, but when we call the &so sub, and it calls .Bool on the Junction returned from sub z, that method call will NOT try to see if all elements are true, it'll stop as soon as it finds one that is.


So really, I'm unsure whether that should even be mentioned in the docs...

@loops
Copy link
Author

loops commented Jun 25, 2018

Thanks for that great explanation zoffixznet.

This is what I was fighting to understand. Worried that a term wouldn't be evaluated because of short-circuiting as in the || or && cases. All of my side effects are parallel safe, but I do need them all executed, not removed by an optimization.

I'd vote for removing that short-circuit mention from the documentation unless someone can see a way that short-circuiting can bite you.

@pmichaud
Copy link
Collaborator

Historical note: For as long as I can remember, S09 has always contemplated the possibility that junctions would be multi-threaded somehow to evaluate things in parallel, and that it would be possible for some threads to be terminated early once an answer had been determined within the appropriate context.

So, in the case of a boolean context, I think it's possible that if ( a() | b() | c() ) might someday short-circuit. And even with something like my $x = a() | b() | c() the junctions might be allowed to do some lazy evaluation of things (this was contemplated in S09), so even that might not be a guarantee at this point.

So either language designers decide on a specific interpretation now (and we document it), or the documentation gets listed as "short circuiting behavior is currently undefined; programs should not rely on short-circuiting or non-short-circuiting behavior in Junctions". (If this sounds onerous, I think it's not too far off the mark of what is already said about other lazy constructs.)

Anyway, that's my remembrance/contribution here.

Pm

@zoffixznet
Copy link
Contributor

or the documentation gets listed as "short circuiting behavior is currently undefined;

👍 on this. Let's leave the possibility of this type of short-circuiting open. Once we have an implementation of actual auto-threaded Junctions it might be easier to evaluate whether this sort of short-circuiting is feasible and desirable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants