Junctions, Sets, and Threading.

2005-02-22 Thread Rod Adams
Definitions
===
set (n) : A data container that can hold many elements simultaneously.
The order of elements in a set is meaningless. No two elements in a set
may hold the same value.
junction (n) : The combination of several independent values and an
explicit boolean predicate, to form an object that can behave as a
single entity, until evaluation, when threading will occur.
thread (v) : To take a single statement or expression, and execute it
one or more times, with each iteration using a different value or
element from a junction or set that is participating in that expression.
The results of each execution will be recombined in some fashion.
boolean expression (n) : An expression  evaluated in a boolean context.
Some notable boolean expressions:
1. Any of the comparison operators taken with their operands.
2. The test expression of an C if  or C while  statement.
3. The distant connection between a C given  and it's associated
   C when s.
4. Type checking.
implicit threading (n) : Threading that is done on the user's behalf
with no special syntax in the code declaring when and where it is
happening. It is entirely at the implementation's judgment of the given
circumstances when threading will take place.
explicit threading (n) : Threading done for the user's, on his request.
The form of this request may vary, but there is some syntax that tells
the implementation to thread a given section of code.
function (n) : Any subroutine in capable of returning a value. In Perl
6, this includes: operators, subs, methods, multi-methods, and more.

Junctions
=
The purpose of a junction is to allow for performing several tests at a
given time, with the testing code needing no knowledge of that junctions
are present. While a junction can represent several values at the same
time, such notions as hold and contain should be avoided, and they
can be very misleading, they betray the fact that a junction is a single
entity. As such, junctions are best thought of as Scalar. (Like other
scalars, it may reference to something much more complex, but that's
beside the point). Therefore the result of a junction evaluation should
be Scalar. (We will see later that this scalar value is in fact
boolean).
But what is a junction evaluation? Simply put, it is the results of
threading all values of a junction through an expression and the
recombination of these results back into a scalar, via the logic of the
associated boolean predicate.
Note the fact that it's a _boolean_ predicate. That means that the end
result of any junction evaluation is a single boolean value. Therefore,
the only place that it makes sense to evaluate a junction is in a place
where a boolean value is expected. This brings us to our Prime Junction
Rule:
Junctions can only be evaluated as part of a boolean expression.
Attempting to evaluate a junction anywhere else is an error.
Some comments about what this does for us.
- Threading in this case is purely implicit. This allows a user to drop
a junction into any place a test parameter is called for. Asking for
explicit threading here makes the concept useless.
- Nesting of junctions is not an issue, since each threaded evaluation
is yet another boolean expression.
- Things like C for $j .. 10 {...} , are illegal. They didn't make
much sense in the first place.
- In fact, most code written without junctions in mind will execute
cleanly and as expected, since the result of the threading operation
will be exactly what is expected: boolean.
- As such there should be no limitation as to where a junction can be
stored and passed. Functions will have the ability to explicitly reject
junctions as arguments by typing their parameters with something like
C all(any(Int, Str), none(Junction)) . Yes, that's using junctions to
reject junctions.
- There is still a limited case of Nasty Side Effect Syndrome that can
be caused by having an assignment, output, or other undesirable type of
function/operator as part of a boolean expression. There will therefore
need to be a is unautothreadable trait to be had for functions. All
builtin I/O and assignment functions should have this on. This
protection is shallow. If the call is not in the text of the evaluated
expression, it is not guaranteed to be tested.
- If you wanted to thread a junction in a non-boolean way, you probably
didn't want a junction. You likely either wanted an array or a set, and
some combination of hyper operators. See below.

Boolean Expressions
===
Some common boolean expressions in context, with valid junction usage:
   if $x == any(1,2,3,4) {...}
   given $string {
 when any(/a .* q/, 'santa')  {...}
 when all(is_all_uppercase(), /^ \D+ $/) {...}
   }
   if is_prime(sqrt(any(25,14,32))) {...}
   
Note that in the last case, it's the entire boolean expression that's
threaded. The breakdown would look like:

   is_prime(sqrt(any(25,14,32))) ---
any(is_prime(sqrt(25)),
is_prime(sqrt(14)),

Re: Junctions, Sets, and Threading.

2005-02-22 Thread Damian Conway
Rod Adams wrote:
 The purpose of a junction is to allow for performing several tests at a
 given time, with the testing code needing no knowledge of that junctions
 are present. While a junction can represent several values at the same
 time, such notions as hold and contain should be avoided, and they
 can be very misleading, they betray the fact that a junction is a single
 entity. As such, junctions are best thought of as Scalar. (Like other
 scalars, it may reference to something much more complex, but that's
 beside the point). Therefore the result of a junction evaluation should
 be Scalar.
Everything is okay to here.
 (We will see later that this scalar value is in fact boolean).
Err...no. See below.
 But what is a junction evaluation? Simply put, it is the results of
 threading all values of a junction through an expression and the
 recombination of these results back into a scalar, via the logic of the
 associated boolean predicate.
Correct.
 Note the fact that it's a _boolean_ predicate. That means that the end
 result of any junction evaluation is a single boolean value.
No. For example:
# Print a list of substrings...
my $substring = substr(junctions, any(1..3), any(3..6));
say $substring.values();
 Therefore, the only place that it makes sense to evaluate a junction
 is in a place where a boolean value is expected. This brings us to our
 Prime Junction Rule:

 Junctions can only be evaluated as part of a boolean expression.
No.
 Attempting to evaluate a junction anywhere else is an error.
No.
 Some comments about what this does for us.

 - Threading in this case is purely implicit. This allows a user to drop
 a junction into any place a test parameter is called for. Asking for
 explicit threading here makes the concept useless.
Correct.
 - Nesting of junctions is not an issue, since each threaded evaluation
 is yet another boolean expression.
Not necessarily, but boolean evaluation of does indeed work that way.
 - Things like C for $j .. 10 {...} , are illegal. They didn't make
 much sense in the first place.
Probably.
 - In fact, most code written without junctions in mind will execute
 cleanly and as expected, since the result of the threading operation
 will be exactly what is expected: boolean.
It doesn't have to be boolean, but the point is basically correct.
 - As such there should be no limitation as to where a junction can be
 stored and passed. Functions will have the ability to explicitly reject
 junctions as arguments by typing their parameters with something like
 C all(any(Int, Str), none(Junction)) . Yes, that's using junctions to
 reject junctions.
Yes.
 - There is still a limited case of Nasty Side Effect Syndrome that can
 be caused by having an assignment, output, or other undesirable type of
 function/operator as part of a boolean expression. There will therefore
 need to be a is unautothreadable trait to be had for functions. All
 builtin I/O and assignment functions should have this on. This
 protection is shallow. If the call is not in the text of the evaluated
 expression, it is not guaranteed to be tested.
I need to think about this. I'm not sure I'm convinced this isn't covered by
none(Junction) typing on parameters.
 - If you wanted to thread a junction in a non-boolean way, you probably
 didn't want a junction. You likely either wanted an array or a set, and
 some combination of hyper operators. See below.
Not convinced of this.
 Sets
 

 Despite several surface similarities between a set and a junction, they
 are quite different. Sets actually contain other things. Junctions hold
 several values at once, and can even hold the same value more than once
 at once.
Err, no. Junctions *are* values, and those values are unique.
 Sets are inherently plural in thought process. Junctions are
 inherently singular. The operations one wishes to perform on a set are
 radically different from those performed on a junction.
True.
 Sets and hashes are an odd pair. Hashes are not a good basis for Sets
 due to the restriction that the keys are strings. Even if this is not
 the case,
It's not.
 In addition, a set evaluated in a list context returns it's members.
Err...then how do you create a list of sets???
 In addition to C ~~  for membership, we will borrow the {}
 subscripters from hashes (not sure about the  or «» variants).
You'd have to take them, I'm afraid. Introducing gratuitous
inconsistencies would be a Bad Idea.
 In this form, a C $set{$key}  reference will look for the element
 that matches the place in the sort identified by $key (in other
 words, the element with the matching .key() or value). If something
 is there, it then returns C .value||$_ , assuming $_ is the element
 at that place.

 This seemingly bizarre set of semantics gives us something very
 powerful. One can make a Set of Pairs, which behaves much like a hash,
 only with the ability to use any data type as the key.
Hashes already have this ability. I don't think overloading the hash 

Re: Junctions, Sets, and Threading.

2005-02-22 Thread Juerd
Damian Conway skribis 2005-02-22 22:13 (+1100):
 @x = func($a, [EMAIL PROTECTED]);
 That's:
  @x = »func«($a, @y);
 But, y'know, this one almost convinces me. Especially when you consider:
  sub func ($i, $j, $k) {...}
  @x = func($a, [EMAIL PROTECTED], @z);

Naievely, I'd expect

my @a = @b = 1..3;
»foo«(@a, @b)

to result in

foo(@a[0], @b[0]),
foo(@a[1], @b[1]),
foo(@a[2], @b[2]);

but

foo([EMAIL PROTECTED], [EMAIL PROTECTED])

with the same arrays in

foo(@a[0], @b[0]),
foo(@a[0], @b[1]),
foo(@a[0], @b[2]),
foo(@a[1], @b[0]),
foo(@a[1], @b[1]),
foo(@a[1], @b[2]),
foo(@a[2], @b[0]),
foo(@a[2], @b[1]),
foo(@a[2], @b[2]);

Likewise,

@foo »+« @bar

would iterate in parallel, resulting in min([EMAIL PROTECTED], [EMAIL 
PROTECTED]) elements,
while

[EMAIL PROTECTED] + [EMAIL PROTECTED]

would return [EMAIL PROTECTED] * [EMAIL PROTECTED] elements.

I'd then expect

$foo +« @bar

and

$foo + [EMAIL PROTECTED]

to be equivalent (æsthetically, the latter is more pleasing, imo).


Juerd
-- 
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html 
http://convolution.nl/gajigu_juerd_n.html


Re: Junctions, Sets, and Threading.

2005-02-22 Thread Damian Conway
Juerd wrote:
Naievely, I'd expect
my @a = @b = 1..3;
»foo«(@a, @b)
to result in
foo(@a[0], @b[0]),
foo(@a[1], @b[1]),
foo(@a[2], @b[2]);
but
foo([EMAIL PROTECTED], [EMAIL PROTECTED])
with the same arrays in
foo(@a[0], @b[0]),
foo(@a[0], @b[1]),
foo(@a[0], @b[2]),
foo(@a[1], @b[0]),
foo(@a[1], @b[1]),
foo(@a[1], @b[2]),
foo(@a[2], @b[0]),
foo(@a[2], @b[1]),
foo(@a[2], @b[2]);
Yeah, that was the bit that nearly has me convinced. ;-)
Damian


Re: Junctions, Sets, and Threading.

2005-02-22 Thread Luke Palmer
Juerd writes:
 Damian Conway skribis 2005-02-22 22:13 (+1100):
  @x = func($a, [EMAIL PROTECTED]);
  That's:
   @x = func($a, @y);
  But, y'know, this one almost convinces me. Especially when you consider:
   sub func ($i, $j, $k) {...}
   @x = func($a, [EMAIL PROTECTED], @z);
 
 Naievely, I'd expect
 
 my @a = @b = 1..3;
 foo(@a, @b)
 
 to result in
 
 foo(@a[0], @b[0]),
 foo(@a[1], @b[1]),
 foo(@a[2], @b[2]);
 
 but
 
 foo([EMAIL PROTECTED], [EMAIL PROTECTED])
 
 with the same arrays in
 
 foo(@a[0], @b[0]),
 foo(@a[0], @b[1]),
 foo(@a[0], @b[2]),
 foo(@a[1], @b[0]),
 foo(@a[1], @b[1]),
 foo(@a[1], @b[2]),
 foo(@a[2], @b[0]),
 foo(@a[2], @b[1]),
 foo(@a[2], @b[2]);

Hmm, this all makes me think of my proposal a few weeks back:

 foo(@a[$^i], @b[$^i]) 

 foo(@a[$^i], @b[$^j]) 

I've grown to believe that my proposal had some kinks in it,
particularly in the area of what kind of thing [EMAIL PROTECTED] is.  But I'm 
also
believing that something like it is becoming warranted.

Luke


Re: Junctions, Sets, and Threading.

2005-02-22 Thread Rod Adams
Damian Conway wrote:
Rod Adams wrote:
 The purpose of a junction is to allow for performing several tests at a
 given time, with the testing code needing no knowledge of that 
junctions
 are present. While a junction can represent several values at the same
 time, such notions as hold and contain should be avoided, and they
 can be very misleading, they betray the fact that a junction is a 
single
 entity. As such, junctions are best thought of as Scalar. (Like other
 scalars, it may reference to something much more complex, but that's
 beside the point). Therefore the result of a junction evaluation should
 be Scalar.

Everything is okay to here.
[snip]
 Therefore, the only place that it makes sense to evaluate a junction
 is in a place where a boolean value is expected. This brings us to our
 Prime Junction Rule:

 Junctions can only be evaluated as part of a boolean expression.
No.
 Attempting to evaluate a junction anywhere else is an error.
No.

This is my major point of the post. In my opinion, your example of:
   # Print a list of substrings...
   my $substring = substr(junctions, any(1..3), any(3..6));
   say $substring.values();
Is a perfect example of a place where saying:
   # Print a list of substrings...
   my @substring = substr(junctions, »1..3«, »3..6«);
   say @substring;
Is far more in line with what you're doing. Not to mention you likely 
wanted it to do:

   my @substring = substr(junctions, »1..3«, »3..6«);
   say [EMAIL PROTECTED];
instead, putting nice \ns between values. My way also guarentees a 
certain order to the output.

Simply put, you're ignoring the fact that junctions have a boolean 
predicate. Which they do.
In this example, it didn't matter if you had used any/all/one/none.

 - There is still a limited case of Nasty Side Effect Syndrome that 
can
 be caused by having an assignment, output, or other undesirable type of
 function/operator as part of a boolean expression. There will therefore
 need to be a is unautothreadable trait to be had for functions. All
 builtin I/O and assignment functions should have this on. This
 protection is shallow. If the call is not in the text of the evaluated
 expression, it is not guaranteed to be tested.

I need to think about this. I'm not sure I'm convinced this isn't 
covered by
none(Junction) typing on parameters.
It is not.
By my proposal:
   $j = any(1,2,3);
   unless say($j) { die '...' }
The say would thread, because of the boolean expression in the 'unless'. 
C say  does not get the junction as a parameter. But C say  needs to 
be marked that it's a no-no to thread over it.

 - If you wanted to thread a junction in a non-boolean way, you probably
 didn't want a junction. You likely either wanted an array or a set, and
 some combination of hyper operators. See below.
Not convinced of this.
I am completely convinced of this. Please express your reservations so I 
can address them.



 Sets
 

 Despite several surface similarities between a set and a junction, they
 are quite different. Sets actually contain other things. Junctions hold
 several values at once, and can even hold the same value more than once
 at once.
Err, no. Junctions *are* values, and those values are unique.
$x = one(2,3,3);
squishing the duplicate 3 is not allowed here.

 Sets are inherently plural in thought process. Junctions are
 inherently singular. The operations one wishes to perform on a set are
 radically different from those performed on a junction.
True.
 Sets and hashes are an odd pair. Hashes are not a good basis for Sets
 due to the restriction that the keys are strings. Even if this is not
 the case,
It's not.
Changing the index type of hashes away from Str makes as much sense to 
me as changing the index type of arrays to something non-integral. None.

 In addition, a set evaluated in a list context returns it's members.
Err...then how do you create a list of sets???
grumble. Didn't think of that. I was looking for a simple way to say:
   for $set {...}
without throwing all kinds of special cases around.

 In addition to C ~~  for membership, we will borrow the {}
 subscripters from hashes (not sure about the  or «» variants).
You'd have to take them, I'm afraid. Introducing gratuitous
inconsistencies would be a Bad Idea.
That's acceptable.
 In this form, a C $set{$key}  reference will look for the element
 that matches the place in the sort identified by $key (in other
 words, the element with the matching .key() or value). If something
 is there, it then returns C .value||$_ , assuming $_ is the element
 at that place.

 This seemingly bizarre set of semantics gives us something very
 powerful. One can make a Set of Pairs, which behaves much like a hash,
 only with the ability to use any data type as the key.
Hashes already have this ability. I don't think overloading the hash 
access
syntax on Sets is worth the trouble.
And the same hash function would nicely handle non-strings?
And I'll have to ask: Can you also change the index of 

Re: Junctions, Sets, and Threading.

2005-02-22 Thread Damian Conway
Aldo Calpini wrote:
Damian Conway wrote:
 @s = 'item' _ [EMAIL PROTECTED];
That's:
 @s = 'item »_« @x;

(just checking that my unerstanding is correct, don't want to be 
nitpicking :-)

assuming that you meant to prepend the string item to each element of 
@x, isn't that:

   @s = 'item' »~« @x;
If Rod meant concatenation, yes it should be C~. I was just reproducing what 
he wrote.


furthermore, given that the operator hyperates on one side only, 
shouldn't this be:

@s = 'item' ~« @x;
The rule, as I understand it, is that unaries have one hypermarker and 
binaries have two.

Damian


Re: Junctions, Sets, and Threading.

2005-02-22 Thread Damian Conway
Rod Adams wrote:
This is my major point of the post. In my opinion, your example of:
   # Print a list of substrings...
   my $substring = substr(junctions, any(1..3), any(3..6));
   say $substring.values();
Is a perfect example of a place where saying:
   # Print a list of substrings...
   my @substring = substr(junctions, »1..3«, »3..6«);
   say @substring;
Is far more in line with what you're doing. 
But much less obvious. This is the core of my qualms. You're proposing we have 
all three of:

»foo«  @x,   @y;
 foo  [EMAIL PROTECTED], [EMAIL PROTECTED];
 foo  [EMAIL PROTECTED]@y»;
all meaning very different things. That really worries me. I'd especially 
prefer that we didn't overload »« to mean both linear vector and 
cross-product.

I certainly like the idea of having both abilities available; I'm just think 
the syntaxes need to be better differentiated.


Not to mention you likely wanted it to do:
   my @substring = substr(junctions, »1..3«, »3..6«);
   say [EMAIL PROTECTED];
instead, putting nice \ns between values.
No, if I'd wanted to do that, I'd have written:
 say for $substring.values;

Simply put, you're ignoring the fact that junctions have a boolean 
predicate. Which they do.
Yep. Isn't it useful that you can do that, and get more functionality out of a 
single construct?


I need to think about this. I'm not sure I'm convinced this isn't 
covered by none(Junction) typing on parameters.

It is not.
By my proposal:
   $j = any(1,2,3);
   unless say($j) { die '...' }
The say would thread, because of the boolean expression in the 'unless'. 
C say  does not get the junction as a parameter. But C say  needs to 
be marked that it's a no-no to thread over it.
But that was precisely my point:
sub say (none(Junction) [EMAIL PROTECTED]) {...}

I am completely convinced of this. Please express your reservations so I 
can address them.
sub get_matches {
 my @in  = split /ws/, prompt 'search for: ';
 my @out = split /ws/, prompt 'but not: ';
 return %data{any(@in)  none(@out)};
}
my $data = get_matches();
No booleans anywhere in sight.


Err, no. Junctions *are* values, and those values are unique.


$x = one(2,3,3);
squishing the duplicate 3 is not allowed here.
True. one() is special in that regard. The other junctions squish/ignore 
duplicates.


Changing the index type of hashes away from Str makes as much sense to 
me as changing the index type of arrays to something non-integral. None.
Then perhaps you need to think about it a little more. A hash is a mapping. In 
Perl 5 that mapping is restricted to Str-Any. In Perl 6 it's normally the 
same, but can be Any-Any. Which finally realizes the full power of the 
concept of mappings. For example:

my %seen is shape(IO) of Bool;  # %seen maps IO objects to boolean values
while get_next_input_stream() - $in {
next if %seen{$in};
$text ~= slurp $in;
%seen{$in} = 1;
}

 In addition, a set evaluated in a list context returns it's members.
Err...then how do you create a list of sets???

grumble. Didn't think of that. I was looking for a simple way to say:
   for $set {...}
without throwing all kinds of special cases around.
 for values $set {...}

And the same hash function would nicely handle non-strings?
And I'll have to ask: Can you also change the index of arrays to Double?
No, of course not. But you *can* change the index to any enumerable type:
 my @weekly_rainfall is shape(Day);
 @weekly_rainfall[Day::Wed] = 42;# millimetres

 Sets will borrow at least the following methods from Arrays:
   grep, map, elems
 and these from hashes:
   keys, values, each, delete, exists
Keys? Surely sets only have values???

Sets have elements. Those elements can have .key and .value methods on 
them. Pairs for example. Any element that can't .key or .value will 
default to it's value.

btw, this whole Sets mimic hashes thing can be ripped out of my Sets 
proposal if nobody else likes it.
I certainly don't like it. But that should be a different thread.

@s = 'item' _ [EMAIL PROTECTED];
That's:
 @s = 'item »_« @x;
 
TMTOWTDI is a good thing. Personally I think my way was clearer. Your 
mileage may vary.
It does. Significantly. I like the idea, but hate the syntax. I'd much rather 
something more explicitly named. Like:

@s = 'item' »~« every(@x);
and:
say every(@first_name) ~ every(@surname);

But, y'know, this one almost convinces me. Especially when you consider:
 sub func ($i, $j, $k) {...}
 @x = func($a, [EMAIL PROTECTED], @z);
Which would again be more obvious as:
@x = func($a, every(@y), @z);

 With these and all the other hyper operator, one should be able to easy
 perform the equivalent threading operation that they lost with the 
 Prime Junction Rule.

I very much doubt we're going to lose it. ;-)
I was referring to losing the threading outside of boolean expressions.
Me too.

Well, let me say 

Re: Junctions, Sets, and Threading.

2005-02-22 Thread Uri Guttman
 DC == Damian Conway [EMAIL PROTECTED] writes:

  DC  my %seen is shape(IO) of Bool;  # %seen maps IO objects to boolean 
values

  DC  while get_next_input_stream() - $in {
  DC  next if %seen{$in};
  DC  $text ~= slurp $in;
  DC  %seen{$in} = 1;
  DC  }

but that is doable in perl5 as well. $in would stringify to a unique key
and you can test for it. better is if you used those keys as io handles
and that is where perl5 loses. say you had to process a bunch of handles
(say sockets which aren't going to be closed) and wanted to pass the
ones that still need processing. then you would do something like this
(perl5ish syntax which won't really work):

my %handles = map { open( $_, '' ) or die foo = 1 } @files ;

later on some code could clear a handle's flag but leave the file open
and you can find the handles you want easily.

process_handles( grep( $handles{$_}, keys %handles ) ) ;

my current workaround for this problem is to have a hash that maps a ref
to itself! the key is a stringified ref and the value is the real
ref. having the key be any value (but internally strringified for
hashing) is very needed.


   But, y'know, this one almost convinces me. Especially when you consider:
   
   sub func ($i, $j, $k) {...}
   
   @x = func($a, [EMAIL PROTECTED], @z);

  DC Which would again be more obvious as:

  DC  @x = func($a, every(@y), @z);

i agree. i like the names there as it reads better.


  DC PS: I'll be away for the rest of the week, but will happily continue to
  DC  argue when I return. ;-)

so where do you go for an argument when you are away?

uri

-- 
Uri Guttman  --  [EMAIL PROTECTED]   http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs    http://jobs.perl.org


Re: Junctions, Sets, and Threading.

2005-02-22 Thread Rod Adams
Damian Conway wrote:
Rod Adams wrote:
This is my major point of the post. In my opinion, your example of:
   # Print a list of substrings...
   my $substring = substr(junctions, any(1..3), any(3..6));
   say $substring.values();
Is a perfect example of a place where saying:
   # Print a list of substrings...
   my @substring = substr(junctions, »1..3«, »3..6«);
   say @substring;
Is far more in line with what you're doing. 

But much less obvious. This is the core of my qualms. You're proposing 
we have all three of:

»foo«  @x,   @y;
 foo  [EMAIL PROTECTED], [EMAIL PROTECTED];
 foo  [EMAIL PROTECTED]@y»;
all meaning very different things. That really worries me. I'd 
especially prefer that we didn't overload »« to mean both linear 
vector and cross-product.

I certainly like the idea of having both abilities available; I'm just 
think the syntaxes need to be better differentiated.
I'm not pinning everything on the syntax being » «. I just hadn't heard 
the objection to it before so was running with it. If it takes changing 
them to something else, I'll go with that. Though I was hoping for 
something shorter than Cevery(). I also like the use of operators 
here, since they are making a substantial change to the entire 
statement. All of any/all/one/none/every look too much like ordinary 
function calls for my tastes. But we do seem to be mighty short on 
unambiguous punctuation these days.

However, I would have picked the « » as qw// to be the loser in this 
regard. Then the »'s and «'s all mean repetition is happening. I 
personally never found C $x{qw/dog cat foo/}  to be a bother, and I 
use the equivalent in Perl5 very frequently. _If_ that is dropped, then 
you can have « » mean linear vector and » « mean cross product. But 
I won't press this idea.

As for obvious, I was processing two lists of parameters, and got back 
a 2-D array, where I could easily match up each input to result.
You returned something of the form any(any(),any(),any()), where there 
is no way to match which result was from a given input.
(FWIW, we both get garbage for output and/or errors. You're printing raw 
junctions, I'm printing arrayrefs.)

I would wager that most people attempting this sort of thing would find 
a 2-D array to be a much more obvious result than a nested junction.


Simply put, you're ignoring the fact that junctions have a boolean 
predicate. Which they do.

Yep. Isn't it useful that you can do that, and get more functionality 
out of a single construct?
Powerful? Yes.
Scary? Very. I start with something that looks like a scalar, and all 
the code it touches turns all my other variables into juxtapositions. 
Kind of like taint checking.

Useful? No more so that hyperquotes in the same place.
I find it more useful to get even more functionality out of the list 
construct.


I need to think about this. I'm not sure I'm convinced this isn't 
covered by none(Junction) typing on parameters.

It is not.
By my proposal:
   $j = any(1,2,3);
   unless say($j) { die '...' }
The say would thread, because of the boolean expression in the 
'unless'. C say  does not get the junction as a parameter. But C 
say  needs to be marked that it's a no-no to thread over it.

But that was precisely my point:
sub say (none(Junction) [EMAIL PROTECTED]) {...}

In my way, C say  is never given the chance to accept or decline $j as 
an argument. The above would be handled as:

   unless any(say(1), say(2), say(3)) {...}
All C say  sees is scalars, one at a time. I was looking for a way to 
mark C say  with a way to tell the callee that threading over it 
(note: over not through) is a bad idea.


I am completely convinced of this. Please express your reservations 
so I can address them.

sub get_matches {
 my @in  = split /ws/, prompt 'search for: ';
 my @out = split /ws/, prompt 'but not: ';
 return %data{any(@in)  none(@out)};
}
my $data = get_matches();
No booleans anywhere in sight.

So with example data:
   @in = qw/foo bar baz/;
   @out =  qw/baz fiz bop/;
   %data = (foo = 5, bar = 6, baz = 7, fiz = 5, bop = 8);
you return:
   all(any(5,6,7), none(7,5,8))
Which is just 6. If I were a user of this function, I would want foo's 5 
as well. And I'd probably prefer to have had them as a list, not a junction.

By delaying the application of your predicates, you have voided whatever 
it was that made those values have those predicates associated with 
them. Logic would say that each step of processing of the values in the 
junction without the application of the predicate would more often than 
not move you further and further away from the correct meaning of the 
predicate in terms of those values.

This is why I want to stop junction propagation. The more you feed 
code junctions that create other junctions, the more obscure your final 
result is. The predicate is there to explain how to recombine the 
results of threading together to form a single result. Attempting