Damian Conway wrote:

Rod Adams wrote:

All I want now is for autothreading to be explicit.


It already *is*.

The only way that:

    is_prime($x)

can ever autothread is if $x holds a junction. But that can now only happen if there's an explicit C<use junctions> in scope where $x was assigned to (or the explicit use of some other module that also activates C<use junctions>). So $x having a junction must be a known possibility at that point.

Of course, literal junctions *will* autothread in all circumstances:

    is_prime(any(6,7,8))

is_prime(6|7|8)

I had not caught the difference between:

   use junctions;
   $x = 6|7|8;
   if is_prime($x) {...}

and

   if is_prime(6|7|8) {...}

before. Is this new, or yet another important detail I missed along the way? Or is this a side effect of not being able to store a Junction, and can go away if C< use Junctions > is turned on?


But they're both explicit too: you're explicitly using junction constructors, so the autothreading can hardly come as a surprise.

*If* we are guaranteed than an explicitly created junctions will always autothread, I'll agree with this.


I will, however, question if this is optimal. Compare two simple cases: C< $x == any(4,5,6) > and C< $x < all(4,5,6) >. Both of them are prime candidates to some optimizations, but the optimizations are likely rather different. If we pass the junction into the operator, then it can perform some custom tailored code, to make things much more efficient, instead of relying on a more generalized junction optimizer to handle things.

What this also means is that if you wish to pass an anonymous junction, you can't. You have to do something like:

{
   use junctions;
   some_func(my $x = any(4|5|6));
}

Which just seems silly.


And if:

    is_prime($x)

does happen to autothread when you weren't expecting it to, then one of two things will happen. Either the subroutine will be 'pure' in which case there's no problem in autothreading it; or else the subroutine will have side effects, in which case you'll get an explicit warning when the autothreading occurs.

I addressed earlier concept of how does perl know when there are side effects, particularly with the execution path can weave to parts written in pure-parrot. In particular, if the Patrick responded by implying that there was no such side effect protection. see:


http://www.nntp.perl.org/group/perl.perl6.language/19210 (my post)
http://www.nntp.perl.org/group/perl.perl6.language/19212 (Patrick's response)


I see your statements on the subject, and Patrick's to be at odds. But then again, it might be that I've misread something again, though I'm doing my best to avoid it now.

I request some clarification on this. If nothing else, to make sure you and Patrick have the same understanding of what's happening.

This problem goes away completely with explicit autothreading. perl would no longer be making assumptions about what to autothread, and what to carp over.

Personally, I think it's completely fascist to require a C<use junctions> pragma in order for junctions to even be stored in variables. It's as bizarre as requiring C<use strings> or C<use references> or C<use undef> or C<use infinities> would be. Yes, it *is* possible to get unexpected behaviour from passing a junction where it isn't expected, but it's already possible to get unexpected behaviour by passing a string or an undef or a reference or an object where it isn't expected. Junctions are nothing new in that respect.

I had it in my head that if I were to get my »Junction« explicit threading idea, I was going to follow up by saying the block against storing junctions was a case of diminishing returns at that point, and should probably go away. I appreciate the stop-gap measure that it was, but I'd prefer to solve the real problem at hand.



Ironically, by using the Awesome Power of Junctions:

I hope I never gave the impression that I felt Junctions were not powerful... That was not the case. If anything, I was arguing that they were *too* powerful... But in the end, I realized it's just the implicit autothreading I didn't like.



Look, I do understand the arguments in the other direction. I've understood them for the past five years that I've been developing the concept of superpositional data-types. I've thought them through numerous times myself, and in the end: I just don't buy them.


The whole point of junctions is to make the threading of operations on datasets both automatic and implicit; to make it Do The Right Thing without the hassles of explicit threading. If you don't want that, that's fine: just don't use junctions. Use arrays and hyperoperators instead. And we'll happily give you a C<no junctions> pragma so you can be emphatic about not wanting them.

I can certainly understand the "hassles of explicit threading" if one is thinking:


   $y = func(any(3|4|5));

has to be explicitly written as:

   $y = any(any(3|4|5).values().map(func($_)));

or some such, but is it really a hassle to say:

   $y = func(»any(3|4|5)«);

instead? I'm proffering up some pretty heavy syntactic sugar here to make explicit threading really easy.

As you stated earlier, one typically knows what they've got as they're writing code. I'll proffer that in addition, people generally know what a function can take, or not take (or they can read the docs to find out), when they call it.
Coders also know what kind of side effects a given call is expected to generate. Those side effects are probably why they're calling it in the first place. They also know if they are expecting the language to thread over the function, or pass the junction along. All of this knowledge, which comes almost innately during the process of writing code, can become almost Halting Problem hard for the compiler or runtime to figure out.


What I'm offering is a way for the programmer to impart this innate knowledge onto the language, in what I consider a fairly non-obstructive fashion. In doing so, I believe I've resolved all the concerns over "magical side effects" and "unexpected results". If the programmer is in that innate knowledge, there are almost definitely other errors in their code, that no amount of "Do the Right Thing" or "Do What I Mean" will resolve.



But bowdlerizing the concept of junctions isn't the answer.

I'm no longer doing that.

Or at least, I'm no doing anything anywhere close to as extreme as some of my other ideas over the last week or two. Which I can see perfectly well, in retrospect, how you felt I was gutting the power away from junctions, and how frustrating that must have been for you.

In dissecting junctions left and right, trying to get rid of them, I did come to a pretty good appreciation of what they can do. And overall, I like them now. They are very weird, and likely to be misunderstood more often than not, but overall they add some interesting properties to the language. (I still argue that they are not supported by linguistics, it's Sets that are supported that way, but _that's_ a different topic than what form junctions should take, if any)

But I still don't like implicit autothreading, and likely never will. I don't know how to explain it, but it just feels very wrong. It's down there with using typeglobs to pass filehandles, which is thankfully history.

-- Rod Adams



Reply via email to