Luke Palmer wrote:
Rod Adams writes:I'm trying to salvage what I can, since people seem to be rejecting everything I offer.
If the set of these "other statements" is limited, consider creating aJunctions are intended to be used mainly within conditionals and other statements;
Junction class (which needs a "use Junction;" to activate), which
overloads the various comparison operators for when a Junction is
involved, and defines any/all/none/one as constructors? Throw in some
overloading or bindings for |/^/&, and it looks like you get
everything your asking for. Having a method evaluate: C< 5 ==
any(4,5,6) > means that the interpreter doesn't need to autothread.
This also makes it where only functions that were explicitly designed
to use Junctions, or ones which didn't declare their signature, and
thus are making no assumptions about what they are given, will perform
the Junctive evaluations.
Okay, I think your proposal is thinning.
Perl is a dynamically typed
language. I have no doubts that people will continue to ignore the type
system even though it's there. I probably will.
So will I.
What on earth does C< for (2..sqrt(3|5)) {...} > mean in the current state of junctions?Let me demonstrate something:
sub is_prime($x) { my @primes; for 2..sqrt($x) { if $_ % none(@primes) == 0 { push @primes, $_; } } return 1 if $x % none(@primes) == 0; }
Run through your mind how this would be done with a junction in $x. Particularly focus on:
2..sqrt($x)
What the hell does that mean? Do you get a junction of lists out? Or
does sqrt die because it's not expecting a junction?
But as written, yes, sqrt() would likely throw an exception under my proposal.
When I say:
if is_prime(any(@stuff)) {...}
I expect to run the codeblock if any of my stuff is prime. Instead I
get an error, always. I could always do this:
if @stuff.grep:{ is_prime($_) } {...}
Should also be able to overload Junction ~~ CodeRef to make this work:
if any(@stuff) ~~ &is_prime {...}
In this manner, you are explicitly controlling when and how the autothreading happens. There is no way for is_prime to slurp up the junction and pass it on in this case.
However, in the current scheme, if is_prime() is written to accept a slurpy list of parameters (either by design, or just a habit from the P5 days), we can have:
sub is_prime { my @primes; for 2..sqrt(@_[0]) { if $_ % none(@primes) == 0 { push @primes, $_; } } return 1 if $x % none(@primes) == 0; }
Pushing the autothreading directly onto the C< for (2..sqrt(3|5)) {...} >, which as you pointed out earlier, is almost definitely _not_ what was wanted, whatever it means. (btw, My current analysis says it will stop at the lowest value in the junction.)
I view it as a definite plus to make the autothreading explicit. I doesn't need it to be ugly, just present.
In fact, that's all I need to shut up on this whole issue.
Something that says: "autothreading into functions only happens when you slap (whatever) in there."
I can live with auto-autothreading over operators (I'd rather not, though). But calling into a function needs something stronger. Yes, operators are functions, too, but if you're fancy enough to be writing you're own operators, you're fancy enough to take junctions into account.
Something like:
if is_prime(Âany(@stuff)Â) {...}
Would more than suffice. It says that you're not attempting to pass the junction, but instead doing something in parallel, which is what the hyper operators are all about, anyways.
It's been the side effects of autothreading that has been my big hold up. If you make it happen explicitly, it's just another looping construct ( a very odd one, but one nonetheless ). If it happens implicitly, it's way too magical and dangerous for my tastes. Give me that, and I'll probably start liking Junctions. I've never argued that they weren't powerful.
You get into this problem when you allow any form of overloading of built in operators, not just with junctions. It'd be trivial to create an AlwaysTrue class, which overloads all forms of comparison against it to always return true. The utility of such a class is left as an exercise to the reader.But the whole point of junctions is to get rid of obscure expressions like that. Brent makes a fantastic case here.
The point is that when you say "makes no assumptions", you're giving the sub writers too much credit. I think a reasonable assumption (especially for these alledged "novices" you keep talking about) that these two code segments are equivalent:
if $x == 2 {...} elsif $x == 3 {...}
And:
if $x == 2 {...} if $x == 3 {...}
No matter what the value of $x.
Yet in the presence of junctions, they are not. Also note that this is
a practical example. I like the former, I know people who like the
latter. It's a matter of style, and it's one that will bite you if you
don't know about junctions.
I am most specifically _not_ suggesting getting rid of operator overloads. Just implicit autothreading.
So what's it going to be? Avoiding the evil side of autothreading, or
not crippling the usefulness of junctions in the presence of unwary
code? It is a trade-off indeed.
I strongly suspect there is a middle ground to be had.
-- Rod Adams