Re: Hackathon notes

2005-07-08 Thread Rod Adams

Yuval Kogman wrote:


Rob Kinyon had a strong argument (in #perl6) that anything that
depends on load order is bound to make someone's head hurt.

He has a point.
 



Especially if one in working in something like mod_perl, and the order 
various modules were actually loaded in can vary greatly from the order 
they are listed in the source code.


Unless we have every lexical scope keep track of what order *it* thinks 
all the MMD methods *should* have been loaded in, which overall feels 
very painful.




I thought I've had is whether there should be a "subname" that can be 
defined on a given multi, to identify it as distinct from the others, 
and not having to type the full signature. Something analougous to 
HTTP/HTML # suffixes. One could then use that subname in conjuction with 
the short name to refer to a specific method. This could then let a user 
easily skip MMD when DWIMmery fails. To be useful, it would need to be 
simple syntax. I'll propose forcing "# as comment" to be "\s+# as 
comment" (if it isn't already), and have subnames specified as 
shortname#subname.


   multi method foo#bar (Num x) {...}
   multi method foo#fiz (String x) {...}

   $y = 42;
   $obj.foo#fiz($y); # even though $y looks like a Num
   $obj.foo($z); # let MMD sort it out.

It's unclear if

   $obj.foo($y);

even works, or should work, even if it does.


It be no means solves all of Yuval's problems, but it would be a handy 
workaround to un-multi your calls.


-- Rod Adams



Re: MMD handling (was Re: Hackathon notes)

2005-07-08 Thread Rod Adams

David Storrs wrote:



On Jul 8, 2005, at 4:25 PM, Dave Whipp wrote:


Rod Adams wrote:



   multi method foo#bar (Num x) {...}
   multi method foo#fiz (String x) {...}
   $y = 42;
   $obj.foo#fiz($y); # even though $y looks like a Num
   $obj.foo($z); # let MMD sort it out.




Instead of changing the parse rules for #, why not just use a trait?

multi method foo is short_name('bar') {...}



I thought about that, but then thought that to become commonplace it was 
a bit much to type. I also couldn't come up with a way to call a given 
multi that matches on a given attribute, without adding even more 
complexity to MMD.





Having additional tags might also give us something to hang  priority 
traits off: "foo#bar is more_specific_than(foo#baz);"  might 
influence the order of clauses in the implicit given/when  block. It 
feels like there should be a generalization of operator  precidence 
here (even thought he two are superficially dis-similar,  the 
looser/tighter concept appears valid).



Although I like the idea of reusing this concept, I'm not sure that  
it really solves the problem.  Fundamentally, we're trying to make  
MMD behave intuitively with no programmer effort.



Well, if one views MMD as "a list of methods to try, each with it's own 
requirements on it's arguments", then it can completely solve the 
problem, along with a method sort function.


1) take all methods the user specified "higher than/lower than/equal to" 
out of the mix.

2) sort remaining methods via a standardized function.
3) put all the ones taken out in step 1 back in, where they are requested.
4) scan the methods, in order, for the first that accepts the given 
arguments.

5) dispatch to the chosen one in #4
-or-
6) begin AUTOMETHing, etc.

Then all we need is a DWIMish sort function.

Some ideas:
-- longer parameter lists go before shorter ones.
-- if param(n) of one ISA param(n) of another, it goes first.
-- slurpies after non-slurpies
-- a hashkey of the parameter types (for deterministic coin flips)

I'm not committed to what goes into the method sort function, or in what 
order, just the concept of it. To me it seems easier to visualize than 
distances, etc. If nothing else, it should be easy to explain to users 
and programmers.


With the name tagging idea from before, one could then say things like:

   multi sub foo#lastresort ([EMAIL PROTECTED]) is after(foo#default) {...}

for when the default sort does things incorrectly.

A reasonable extensions of this would be to have a coderef attribute 
that determines if a supplied set of arguments is acceptable, rather 
than the default check. This is a possible MTOWTDI for the 'where' clauses.



Then again, there are likely several glaring problems with this idea 
that I'm just not seeing at the moment.


-- Rod Adams


Re: Perl 6's for() signature

2003-07-31 Thread Rod Adams
At 10:05 AM 7/31/2003 -0600, Luke Palmer wrote:
Well, I don't think it's possible, actually.  There's a flattening
list context at the beginning (implying a sugary drink from 7 eleven),
followed by a code block.  But, as we know, slurpy arrays can only
come at the end of positional parameters.
Anyone but me feel the need for non-greedy slurpy arrays? similar to 
non-greedy RE matches?
Then we could do:

sub for ([EMAIL PROTECTED], &block) {...}

Proposed behavior of *?@ : All Arguement to Parameter mapping left of it 
are processed Left to Right. Once seen, the mapping starts over right to 
left. Everything remaining is slurpable.

Yes, it's more expensive to use, just like the RE version, but shouldn't 
impact performance _too_ bad when it's not, since the behavior will be 
detectable at compile time.

Thoughts?



RE: Perl 6's for() signature

2003-07-31 Thread Rod Adams
At 01:29 PM 7/31/2003 -0400, Hanson, Rob wrote:
> Anyone but me feel the need for non-greedy
> slurpy arrays? similar to non-greedy RE matches?
I definately like the idea of having something like that.  It probably
wouldn't be used much, but it is nice to have the option.
One thing though, can't you accomplish the same thing by slurping
everything, then poping the block off of the array?
One could do most of the stuff in P6 parameters with P5's @_. But as Damian 
showed at the end of E6, it can quickly grow to a nightmare, and making it 
nicer is what P6 is all about.

-- Rod


Rob

-Original Message-
From: Rod Adams [mailto:[EMAIL PROTECTED]
Sent: Thursday, July 31, 2003 12:56 PM
To: Perl 6 Language
Subject: Re: Perl 6's for() signature
At 10:05 AM 7/31/2003 -0600, Luke Palmer wrote:
>Well, I don't think it's possible, actually.  There's a flattening
>list context at the beginning (implying a sugary drink from 7 eleven),
>followed by a code block.  But, as we know, slurpy arrays can only
>come at the end of positional parameters.
Anyone but me feel the need for non-greedy slurpy arrays? similar to
non-greedy RE matches?
Then we could do:
sub for ([EMAIL PROTECTED], &block) {...}

Proposed behavior of *?@ : All Arguement to Parameter mapping left of it
are processed Left to Right. Once seen, the mapping starts over right to
left. Everything remaining is slurpable.
Yes, it's more expensive to use, just like the RE version, but shouldn't
impact performance _too_ bad when it's not, since the behavior will be
detectable at compile time.
Thoughts?



What to do....

2003-11-14 Thread Rod Adams
So I've been lingering around p6-language for a few months now, and have 
noticed the following two trends:

1) All of the work forward on p6 design seems to come from either Larry or 
Damian. (If there are others working in the shadows back there, please make 
yourselves heard.) Most, if not all, the discussions of recent has been of 
the form "How does  work in relation to  mentioned in 
?". While meaningful and worthwhile topics all, they do not 
drive the language forward terribly fast.

2) Reality is constantly interrupting Larry and Damian's efforts in rather 
nasty ways.

Taken separately, either of these trends are bothersome.
Taken together, this feels like a problem.
So the next question is, is there anything that can be done to improve matters?

I'm moderately certain that everyone wishes they could do something about 
#2, I'm moderately sure that the p6 community has done as much as they can 
on that account.

So my real question is, is there any way for the community to get together 
and help take some of the load off these two in the design, or is the 
current process the Best We Can Do (tm) and we just need to practice that 
most unvirtuous of things "patience"?

Can apocalypses be something more along the line of scratches on the wall, 
that then go through some level of deciphering or translation into 
something closer to English? Are there topics that need brainstorming that 
this list could take over?

I certainly don't want the language to loose the internal cohesiveness that 
all languages need, and am suitably scared of "design by committee"... but 
I'd like to think that there's something that could be done to help matters.

Comments?
Suggestions?
-- Rod Adams

PS -- I'm willing to commit several hrs a week to the effort.


Re: What to do....

2003-11-15 Thread Rod Adams
At 10:40 PM 11/14/2003 -0800, chromatic wrote:
I'd really like to see people start turning the existing design
documents into story cards and programmer tests for Perl 6.  That'll
make it much easier to implement the thing.
So basically go back through the existing Apoc/Exeg's and break it down 
into a long list of features. Then start building tests for each feature.

I'll give this some thought.


Design decisions have to be broken into individual tasks at some point.
Sure, some of them will change as we go along.  There's enough there
that can be implemented now, though, without waiting for the big thud of
specifications.   There's plenty of useful work to go around.
Running test cases are *much* easier to implement against than anything
else.
(Hey, it's been working fairly well on the Perl XP Training Wiki:
http://xptrain.perl-cw.com/).
-- c



Re: The C Comma

2003-11-24 Thread Rod Adams
At 04:40 PM 11/24/2003 -0800, Michael G Schwern wrote:
I definately agree that this is used rarely enough that it should be a word
and not a single character.
"then" sounds too much like "if/then" which is confusing.  Its exactly
the opposite from what you're trying to convey.
It also doesn't convey anything about "evaluate the left hand side, ignore
the results and evaluate the right".  Unfortunately, I don't have a better
name.
C

Of course I've always thought the semicolon would have been a better choice 
for the "C comma". That way C<($a, $b, $c)>  would always be a list, and 
C<($a; $b; $c)> would be $c, after $a and $b are evaled.  I haven't thought 
out how much havoc this would cause the parser, but from this programmers 
view, it seems pretty intuitive.

-- Rod




Re: [perl] Re: Object Order of Precedence (Was: Vocabulary)

2003-12-20 Thread Rod Adams


Luke Palmer wrote:
Joe Gottman writes:

- Original Message - 
From: "Jonathan Lang" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Saturday, December 20, 2003 3:41 PM
Subject: [perl] Re: Object Order of Precedence (Was: Vocabulary)



Larry Wall wrote:

If DangerousPet doesn't define a feed method at all, then we might
dispatch to Pet and Predator as if their methods had an implicit
"multi".
And the C trait is the tie-breaker when several options are
equally likely candidates (in terms of type information); OK.
  I'm a little leery about calling this trait "default". The problem is
that we are already using "default" as a keyword (see the switch statement),
and having a trait with the same name as a keyword might confuse users
and/or the compiler.


Perl's using a top-down compiler now, so it won't be looking for the
keyword variant of C after "is".  "default" is sufficiently
overloaded in English, and by context in Perl, that I don't think anyone
will get confused.
Not to say that other names for this trait aren't welcome.

C



Re: Perl 6 using Perl 5 modules

2003-12-21 Thread Rod Adams
PerlDiscuss - Perl Newsgroups and mailing lists wrote:
When the official release of Perl 6 is released and I start to write some
Perl 6 programs using Perl 5 modules, will I get any errors? How will this
be handled? Will all of the Perl 5 modules have to be ported over and
converted to Perl 6 code? Can I have a basic perl6.pl file while using the
standard perl 5 IO::Socket module or whatehaveyou? 
My understanding of things is that this is what Ponie is all about. Make 
it where Parrot can handle P5 code. Of course, when P6 is released, 
Parrot will it. Since one of the Parrot ideals is the interoperability 
of code from various sources, the answer to your question is yes (as 
long as Ponie supports it).

Try the Ponie FAQ: http://opensource.fotango.com/software/ponie/faq

--Rod



Re: Semantics of vector operations

2004-01-29 Thread Rod Adams
Luke Palmer wrote:

Austin Hastings writes:
 

I think you guys may be talking at cross purposes. Robin, I think, is
talking primarily about coding, while Damian talks of reading.
Perhaps Damian's solution is a Unicode2Ascii perl script that emits formal
names, combined with the implementation in Perl of the
E alternative spellings.
OTOH, Robin's concern for how to code when you're stuck with 7 bit ascii on
the boot console of a Sun box remains valid, and *I* sure would rather have
a short name available in a standard way.
Perhaps this is where the "accept Unicode and HTML" philosopy comes in, sort
of like the reverse of C< use English; >, to wit:
 use asciiops;
 ...
 @list.Emethod;   # Instead of E
   

I think that using the POD entities + Unicode is fine, but the solution
to giving people who use E often, I belive, is to be able to define these
escapes simply.  Either the module writer or the user would map a more
usable escape to that character.
Luke

 

Question in all this: What does one do when they have to _debug_ some 
code that was written with these lovely Unicode ops, all while stuck in 
an ASCII world?

Also, isn't it a pain to type all these characters when they are not on 
your keyboard? As a predominately Win2k/XP user in the US, I see all 
these glyphs just fine,but having to remember Alt+0171 for a  is going 
to get old fast... I much sooner go ahead and write E and be done 
with it.

Thoughts?

-- Rod



Re: Unicode under Windows (was RE: Semantics of vector operations)

2004-01-30 Thread Rod Adams
Austin Hastings wrote:

From: Rod Adams [mailto:[EMAIL PROTECTED]

Question in all this: What does one do when they have to _debug_ some 
code that was written with these lovely Unicode ops, all while stuck in 
an ASCII world?
 

That's why I suggested a standard script for Unicode2Ascii be shipped with the distro.
 

Good Idea, which would also beg an ASCII2Unicode script to reverse the 
process.

Also, isn't it a pain to type all these characters when they are not on 
your keyboard? As a predominately Win2k/XP user in the US, I see all 
these glyphs just fine, but having to remember Alt+0171 for a  
 

is going 
   

to get old fast... I much sooner go ahead and write E 
 

and be done 
   

with it.

Thoughts?
 

This has been discussed a bunch of times, but for Windows users 
the very best thing in the US is to change your Start > Settings 
   

Control Panel > Keyboard > Input Locales so that you have the 
 

option of switching over to a "United States-International" IME.

Once you've got that available (I used the Left-Alt+Shift hotkey) 
you can make a map of the keys. The only significant drawback is 
the behavior of the quote character, since it is used to encode 
accent marks. It takes getting used to the quote+space behavior, 
or defining a macro key (hint, hint).
   

(Links Snipped)
 

Thanks for the pointers. I've now set up Win2k so I can easily switch 
between US and United States International. Works nicely.

Now I have to go beat up the Thunderbird guys for trapping the keyboard 
directly and not allowing me to type the chars here.

Thanks Again
-- Rod


Re: The Sort Problem (was: well, The Sort Problem)

2004-02-13 Thread Rod Adams
Here's my stab at a sort syntax, pulling syntax over from REs:

@out
 <== sort key:ri($_->[2]), key:s($_->[4])
 <== @in;
Basicly, you have a list of RE syntax like C values, whilch take 
various modifiers to say how to play with that key, and then an expr on 
how to generate the key given element $_.

Possible modifiers: (verbose versions welcome)
:rreverse/descending
:n   force numeric comparisons
:s  force string comparisons (default)
:u  unicode (implies :s)
:i   case insensitive (implies :s)
:l   localized collation order
:x  call custom compare sub (a la P5)
This allows:

@out = sort keys %hash; # everything gets defaulted
@out = sort key:x{myfunc($a) cmp myfunc($b)}(), @in; # handy for P5 
migration, but not much else
@out = sort key(myfunc($_)), @in; # same as above, but much better.
@out = sort key(%lookup{$_->{remotekey}}), key:ir($_->{priority}), @in; 
# complex in P5, easy here.

Advantages:
- Uses syntax idioms used elsewhere in P6.
- Common cases are easy
- Decent huffman coding.
Disadvantages:
- Do we really want things that look like REs that are not REs?
- If we do this, are we setting ourselves up to create other RE-like 
creatures for grep, for, etc,  to the point
 where people will start wanting to roll their own in modules?

Thoughts?
-- Rod


Re: The Sort Problem

2004-02-14 Thread Rod Adams
Austin Hastings wrote:

Off the top of my head, I can't think of a case where the compare sub
would be needed unless the key was not well-ordered. Does anyone have
an example of a case where the key-extraction sub approach doesn't
reduce the problem to a Scalar comparison? 
 

I can't find the P5 code I used for it right off, but I remember a case 
when I was playing around with various football (US) stats. I was 
ranking teams, and had something akin to:

@teams = sort {$b->{WinPct} <=> $a->{WinPct}  ||
  ($a->{Conference} eq $b->{Conference}
   ?($b->{ConfWinPct} <=> $a->{ConfWinPct} ||
 $b->{ConfWon}<=> $a->{ConfWon}   ||
 $a->{ConfLost}   <=> $b->{ConfLost})
   :($a->{Division} eq $b->{Division}
 ?($b->{DivWinPct} <=> $a->{DivWinPct} ||
   $b->{DivWon}<=> $a->{DivWon}   ||
   $a->{DivLost}   <=> $b->{DivLost})
 :0
 )
   ) ||
  $b->{Won} <=> $a->{Won}  ||
  $a->{Lost}<=> $b->{Lost} ||
  $b->{GamesPlayed} <=> $a->{GamesPlayed}
 } @teams;
   

Creating a keycode for this situation is not a trivial task at all. So 
sorts do occur in the real world for which there is no straightforward 
way to generate a sortkey. Albeit considerably rare.

Also, I think there is utility in have a compare sub supported so that:
1) porting P5 code is easier. (a minor design rationale, but it exists)
2) people used to thinking in terms of compare subs (from C, P5, and 
points of the programming universe) can still think that way.
3) most importantly to me, so that There's More Than One Way to Do It.

-- Rod Adams



Re: The Sort Problem

2004-02-16 Thread Rod Adams
Damian Conway wrote:

Uri persisted:
> but int is needed otherwise? int is more commonly a sort key than 
float.
> it just feels asymetrical with one having a symbol and the other a 
named
> operator.

Sorry, but that's the way the language works. The more general and usual
conversion (to number, not to integer) has the shorter name.


For the record, I do a lot of statistical work. On the sorts where I 
care about speed, I'm using floats far more often than ints. Uri's usage 
obviously varies from mine. Let's not hack up the language to make sort 
more efficient for some arguable benefit.

I would entertain, however, C and C comparators (and 
functions in core) that pretty much (if not precisely) alias C<+> and 
C<~>, forcing said type.


>   DC> If you don't explicitly cast either way, C just DWIMs by
>   DC> looking at the actual type of the keys returned by the extractor.
>   DC> If any of them isn't a number, it defaults to C.
>
> that doesn't work for me. the GRT can't scan all keys before it decides
> on what comparison operator is needed. the GRT needs to merge keys as
> they are extracted and it needs to do the correct conversion to a byte
> string then and not later. you can't DWIM this away if you want the
> optimization.
EXACTLY!!! So, if you want the GRT to kick in, you have to make sure the
return type of your block is appropriate. If you don't give the 
compiler that
hint, you don't get the optimized sorting.


When fed a number that it doesn't trust to be an int or a float, 
couldn't the GRT store the number with C? (ok, 
there's some prepping for sign and endian, but you get the point) Seems 
like a not-terrible way to handle the issue.



Here's another example (all praise be to Rod!):

@teams = sort [
  # 1 parameter so it's a key extractor...
  {+ $^team->{WinPct} },
  # 2 parameters so it's a comparator...
  { ($^a->{Conference} eq $^b->{Conference}
? ($^b->{ConfWinPct} <=> $^a->{ConfWinPct} ||
   $^b->{ConfWon}<=> $^a->{ConfWon}||
   $^a->{ConfLost}   <=> $^b->{ConfLost})
: ($^a->{Division} eq $^b->{Division}
? ($^b->{DivWinPct} <=> $^a->{DivWinPct} ||
   $^b->{DivWon}<=> $^a->{DivWon}||
   $^a->{DivLost}   <=> $^b->{DivLost})
: 0
)
  },
  # 1 parameter each so all three are key extractors...
  {+ $^team->{Won}  } is descending,
  {+ $^team->{Lost} },
  {+ $^team->{GamesPlayed} } is descending,
  ] @teams;
Now that's just spiffy. Except in moving from my P5 version to your P6 
version, you have to s/?/??/ and s/:/::/, IIRC.

>   DC> But you *can't* apply C to a Code reference.
> then how did you apply 'is insensitive'?
I applied it to the *block* (i.e. a closure definition).
That's not the same thing as a Code reference.
> what i am saying is i think that you need to go back to the drawing
> board to find a clean syntax to mark those flags.
No, I think we have it...just put the appropriate trait on the extractor
*block* when you define it.


I really don't see the problem with

@out = sort {lc $_}, @in;

It's short, simple, unambiguous, IMO very clean. But if people want to 
take a tool that we're creating anyways elsewhere in the language 
(traits) to provide another way to do it, that's fine too.

> i just don't like the reverse args concept at all. it is not
> semantically useful to sorting. sorts care about ascending and
> descending, not a vs b in args.
The problem is that sometimes comparator logic is suffiently complex that
a single comparator needs to have a "bit each way", as in Rod's
football team comparator above.


What my football example was meant to show is that no matter how much we 
abuse poor C in the name of progress, we need to have a way to 
drop it all and go back to how we did it in P5, for those truly 
pathological cases where nothing else works. If people don't trust this, 
I'll come up with something worse.

As a side note, the reason I couldn't find the original sort in question 
is that I later scraped it in favor of a more robust 100 line sub to 
figure out who ranked where.

But in more common case, how much it break things to have

  type Comparator   ::= Code(Any, Any) returns Int;

become

  type Comparator   ::= Code(Any, Any) returns Int
| '!' Code(Any, Any) returns Int;
where the '!'

Re: Exegesis 7: Fill Justification

2004-03-01 Thread Rod Adams
Damian Conway wrote:

Richard Nuttall suggested:

An alternative is to have "fill rightmost gaps" and "fill leftmost 
gaps" on
alternate lines. This  produces more balanced looking columns, so 
they don't all look heavier on the left.


That's a *very* interesting idea. What do people think?
The Version 1 samples had various "whitespace worms" appear over on the 
right, which get broken up to some extent with v2. However, v2 has some 
minor even/odd patterns that get some mild notice.

But overall, I like #2 better.

Since I don't think whitespace management is something that needs to be 
deterministic, why not choose the gaps randomly? If we do need 
deterministic results, then a pseudo-random pattern where you expand the 
C<(($LineNumber * $GapToExpandCounter * $SomePrimeNumber) % 
$GapsOnLine)>th gap?

There's also a gremlin in the back of my head telling me the typesetting 
industry probably solved this riddle years ago. But I have no time to 
research it this week.

-- Rod



Re: Compile-time undefined sub detection

2004-03-05 Thread Rod Adams
Larry Wall wrote:

On Fri, Mar 05, 2004 at 06:45:58PM -, Rafael Garcia-Suarez wrote:
: Of course :) the main problem is not that CHECK blocks are executed
: late (just at the end of the compilation phase); it's that they're
: executed too early, notably in some persistent environment, notably
: mod_perl (or mod_parrot in the future.) When you have a virtual machine,
: you'll end up including modules at run time, because the main
: compilation phase becomes less important. Thus CHECK blocks become
: worthless, code-reusability-wise.
Possibly a CHECK block that is compiled after end of main compilation
should translate itself to a UNITCHECK.  But maybe it should be an error.
But it's also possible that CHECK should mean "unit check", and
there should be an explicit MAINCHECK for delegating checks to the
main compilation.  In that case, only in the main compilation would
CHECK and MAINCHECK mean the same thing.  (And since MAINCHECK is
explicitly requesting a check at the end of main, a late MAINCHECK
should probably be considered an error.  (But by that argument, a late
CHECK should probably fail under the current naming scheme.))
Anybody got opinions on the naming of these beasts?  Certainly *not*
renaming CHECK is more compatible with Perl 5.  And I kinda got fond
of UNITCHECK in the last hour or so.  :-)
Larry
 

Given the fact that use of these blocks are overall quite rare, and 
potentially very confusing to the casual perl hacker who encounters one 
of them, I propose a rather different tact:

BEGIN => EXECUTE_ON_PARSE
CHECK => EXECUTE_AFTER_COMPILE and EXECUTE_AFTER_UNIT_COMPILE
INIT => EXECUTE_INITIALIZATION
END => EXECUTE_ON_EXIT
This also has the advantage of being able to reserve all subs with name 
EXECUTE_.* for compiler/interpreter special sub like these, so we could 
add more of them come perl 6.8 w/o much issue.

-- Rod




A12: Single Dispatch over Mult Dispatch

2004-04-23 Thread Rod Adams
(Note: throughout this message, "method" refers to "sub"s and 
"submethods" as well.)

I'm having trouble coming up with a solid argument for why Single Method 
Dispatch (SMD) is our default, when we have MMD.
At this point, I'm tempted to slap a C in front of all my 
methods, for the sake of future extensibility.

So my basic idea is to solicit reasons why we shouldn't make C 
the default, and then allow for c for the obscure 
cases where one wants such behavior.

Arguments in favor:

= If you've bothered to define a signature for the method, you expect 
things that call it to match that signature. I would expect an error 
when I tried to call a method with parameters that didn't match the 
signature. This change would move that error from "Call doesn't match 
signature" to a "Method for name(signature) not found".

= If you haven't defined a signature, MMD will match against the implied 
signature, which it always should, so no problem.

= Making everything multi makes extending existing code much easier, for 
obvious reasons.

Arguement against:

= Likely makes things harder on the optimizer. Or more likely, makes MMD 
optimization a lot more important. But that's a p6i problem, not a p6l one.

Another way to interpret this post is "When is SMD preferred over MMD? 
And is that enough to make it the default?"

If I'm missing something basic feel free to correct me.

-- Rod Adams



Re: Compatibility with perl 5

2004-04-26 Thread Rod Adams
Larry Wall wrote:

In general it's probably a lousy idea to rely on #!/usr/bin/perl6 to
select language since you want the version number to select the
version of Parrot you're running, not the version of Perl.
One thing that occurred to me over the weekend is that we could fix all
the one-liners using a similar strategy to the package/module/class
switch.  It would be a (roughly) zero growth option to simply
switch to :x syntax for command-line switches instead of -x syntax.
Any program that uses colon switches instead of minus switches would
then automatically be assumed to be in Perl 6.
So maybe a minimal Perl 6 marker would be something like

   #!/usr/bin/perl :
   #!/usr/bin/perl ::
   #!/usr/bin/perl :6
Larry

 

Uhm... What exactly is wrong with

#!/usr/bin/perl -M6

?
-- Rod


Re: RFC eq and ==

2004-05-17 Thread Rod Adams
Luke Palmer wrote:
Admittedly, if you use == for everything, you can force string or
numeric comparison this way:
   if +$a == +$b {...}   # numeric
   if ~$a == ~$b {...}   # string
 

Hmm.
In my head, I would expect == to have implicit numification on the 
operands (unless user-overloaded to something else, but that's 
different). In turn, I'd expect eq to have implicit stringifies.

Therefore I'd expect the +'s to redundant in the first example.
I'd then expect the second example to first convert $a and $b to strings 
because of the ~'s, then, because it sees the ==, it would numify those 
strings and do a numeric compare.

Are my expectations misaligned here?
-- Rod



Re: RFC eq and ==

2004-05-17 Thread Rod Adams
Luke Palmer wrote:
Oh, sorry, wasn't clear.  That's *if* eq was eliminated and == became a
polymorphic operator.
You're correct in terms of the current (and hopefully continuing) state
of things.
 

Went back and re-read your first post, and that is indeed what you were 
saying, I just read it too fast.

I'd be seriously annoyed if eq went away. It's one of those things that 
makes Perl Perl. It's up there with the postfix if.

   ~$a == ~$b
feels too much like:
   Cast(String, $a).Compare(Cast(String, $b))
-- Rod


Re: FW: Periodic Table of the Operators

2004-05-30 Thread Rod Adams
Smylers wrote:
Gabriel Ebner writes:
 

Joe Gottman wrote:
   

  The zip operator is now the Yen sign (¥).
 

How are those without a US keyboard supposed to type this?
   

On Windows you can probably press Alt Gr then type in some number.
 

Close. AltGr-Minus. If you're using the US-International layout that 
ships w/ Windows.

-- Rod


Re: FW: Periodic Table of the Operators

2004-06-13 Thread Rod Adams
Jared Rhine wrote:
I haven't yet seen an example presented where using a Unicode
operator would save keystrokes, for instance.
That depends entirely on how you plan to generate them. If you are 
relying on a special command in your editor of choice, yes, the ASCII 
equiv is fewer keystrokes. If, however, you remap your keyboard (easily 
doable in X and Win32, I'd assume Macs can as well), then the common 
Unicode characters are an AltGr away. Thus, « one shifted keystroke 
(AltGr-[), << is two shifted keystrokes (Shift-, Shift-,).

-- Rod Adams


Slices

2004-06-24 Thread Rod Adams
Come the glorious age of Perl6, will hash slices be enhanced to allow 
things like the following?

[EMAIL PROTECTED]'expected'} = [EMAIL PROTECTED];
Specifically, having the slice be something other than the last element.
This likely dictates having {} be able access a list of of hashrefs, not 
just a single hashref or hash.

Comments?




Re: undo()?

2004-07-01 Thread Rod Adams
Brent 'Dax' Royal-Gordon wrote:
David Storrs wrote:
Well, at least that's a nice simple explanation.  Why couldn't anyone
have explained it to me that way before?  Unfortunately, it means that
continuations are a lot less useful than I thought they were.  :<

Actually, I think you're underestimating the little guys.  After all, 
if they rolled back *all* of your changes, all they could do was 
repeatedly execute the same code!

Hmm... Could someone please give a few prototypical cases where 
continuations really shine over other methods of structure?

A guess from my current understanding:
You're wanting to play with a database. You take a continuation. You see 
if have a database handle open and good to go, if so you do your thing. 
(can you then dismiss the continuation? do uninvoked continuations pile 
up somewhere?). If the handle is not ready, you do everything needed to 
prepare the handle, and then invoke the continuation.
But I don't see how a continuation gained you much over C.

So what makes them so cool?
-- Rod


Re: undo()?

2004-07-01 Thread Rod Adams
Austin Hastings wrote:
--- Rod Adams <[EMAIL PROTECTED]> wrote:
 

A guess from my current understanding:
You're wanting to play with a database. You take a continuation. You
see 
if have a database handle open and good to go, if so you do your
thing. 
(can you then dismiss the continuation? do uninvoked continuations
pile 
up somewhere?). If the handle is not ready, you do everything needed
to 
prepare the handle, and then invoke the continuation.
But I don't see how a continuation gained you much over

C.
So what makes them so cool?
   

You know how you can log in to your webmail/slashdot/sourceforge/amazon
account, and get a cookie that says you're logged in?
And you know how you can then go into your browser's history list and
pick up some entry that was invalid, or came from yesterday, and when
you click through, the cookie (local data) that says you're
legitimately logged in stays with you, so the site doesn't give you a
hard time?
That's continuation-like behavior. 

Continuations will let you take "function pointers" at an arbitrary
location: instead of entering the top of the function, you can come in
to the middle. They are similar to setjmp/longjmp in this context: you
have to pass through once to "take" the continuation, before you can
invoke it. But you can invoke it arbitrarily many times, unlike
set-/long-jmp, since the continuation closes over the entire call
stack.
=Austin
 

Well, that's another explanation that jives with my understanding of 
them. But I still don't have an idea of when I would actually want 
to use them in something I'm writing.

-- Rod


Re: Why do users need FileHandles?

2004-07-18 Thread Rod Adams
Dave Whipp wrote:
I was thinking about the discussions about the "open" function, and of the
capabilities of "string"s.
Given that we'll have things like $str.bytes, etc. It doesn't seem a stretch
to suggest that we could also have $str.lines. Once we have that, and also a
level of pervasive laziness (lazy evaluation), it seems to me that we don't
really need user-visible file handles for most of the common operations on
files.
Imagine:
 my $text is TextFile("/tmp/foo.txt");
 for $text.lines {
   ...
 }

I guess what I'm saying is that if we can make tying the standard idiom,
then we can relax you huffmanization worries for things like the "open"
function.
 

Uhm, my impression was that most of the "huffmanization" discussion was 
centered around declaring a file handle to be read only, write only, 
read-write, exclusive, etc. Masking the file handle with what basically 
amounts to a file handle subclass like you describe will still need to 
allow the user to specify all those attributes.

So you would still need to allow:
my $text is TextFile("/tmp/foo.txt" :rw );
my $text is TextFile("/tmp/foo.txt" :excl );
Not that having wrapper classes for file handles is a bad idea, it just 
doesn't relate to what I saw being discussed.
Oh, and "TextFile" should be spelled "IO::File::Text", IMHO.

-- Rod Adams


Re: Why do users need FileHandles?

2004-07-18 Thread Rod Adams
Dave Whipp wrote:
"Rod Adams" <[EMAIL PROTECTED]> wrote in message
news:[EMAIL PROTECTED]
 

Uhm, my impression was that most of the "huffmanization" discussion was
centered around declaring a file handle to be read only, write only,
read-write, exclusive, etc. Masking the file handle with what basically
amounts to a file handle subclass like you describe will still need to
allow the user to specify all those attributes.
So you would still need to allow:
my $text is TextFile("/tmp/foo.txt" :rw );
my $text is TextFile("/tmp/foo.txt" :excl );
   

my $text is TextFile("/tmp/foo") is rw;
my $text is TextFile("/tmp/foo") is const;
truncate Vs append would be infered from usage (assign => truncate). One
might be able to infer read Vs write in a similar way -- open the file based
on the first access; re-open it (behind the scenes) if we write it after
reading it.
 

Case 1:
So I wanted to do a read/write scan, so I create my TextFile, start 
reading in data, so the file is opened for reading. Then, I come to the 
part where I want to update something, so I do a write command. Suddenly 
the file has to be closed, and then re-opened for read and write. And 
all my buffers, file pointers and the like are reset, (though curable 
with very careful planning), leaving me in a bad spot. Better if I could 
just declare the file open for read and write at open time.

Case 2:
I meant to use some critical data file in read-only mode, and accidently 
use a write command somewhere I didn't mean to, and silently just 
clobbered /etc/passwd. Better if I could have just opened the file read 
only, and trigger an error on the write command.

What design philosophy would you envision TextFile taking to handle both 
these cases in a coherent fashion?

:excl would probably need to be an option, but is not sufficiently common to
be agressively huffmanised:
my $text is TextFile("foo.txt", :no_overwrite);
my $text is TextFile("foo.txt") does no_overwrite;
ot that having wrapper classes for file handles is a bad idea, it just
doesn't relate to what I saw being discussed.
Oh, and "TextFile" should be spelled "IO::File::Text", IMHO.
   

Possibly, but would need a hufmanized alias for common use. Possible just
"file":
 

s/file/open/ and we're back where we started.
my Str $text is file("foo.txt") does no_follow_symlink does no_create;
my $text = open("foo.txt" :no_follow_symlink :no_create);
I don't think anyone (read: Larry) has declared exactly what the 
capabilities of the default file handle object are yet. It seems me that 
you could very well get what you want.

-- Rod Adams


Re: Why do users need FileHandles?

2004-07-19 Thread Rod Adams
Dave Whipp wrote:
Under the hood, I don't really care, as long as it works (and is
sufficiently efficient). There are obvious implementations that might be a
bit inefficient on the first iteration (e.g. close and reopen). Quite
frankly, the number of times I open unstructured files in rd/wr mode in a
typical program can be measured on the fingers of one foot! If I want to do
a R-M-W operation then I do like -i, and use a tmp file. Maybe the
hypothetical TextFile object would do the same (by default). If I want to
micromanage the actual access to the file object, then I'd be happy to
c a module that lets me manipulate file handles directly. I just don't
see that as the common case.
Your case 2 is easy: "my Str $passwds is File("/etc/passwd") is const". With
that, we might even catch your error at compile time.
/file/open/ and we're back where we started.
   

Except that we've lost a layer of abstraction: the programmer manipulates a
file's contents, not its accessor. Text files would be just an
implementation of strings. No need to learn/use a different set of
operators. Want to read bytes: use $str.bytes. Graphemes: $str.graphs. Also,
we use the existing access control mechanisms ("is rw", "is const", instead
of inventing new ones to pass to the C function as named-args).
 

I think part of the "mental jam" (at least with me), is that the 
read/write, exclusive, etc, are very critical to the act of opening the 
file, not only an after the fact restriction on what I can do later. If 
I cannot open a file for writing (permissions, out of space, write 
locked, etc), I want to know the instant I attempt to open it as such, 
_not_ when I later attempt to write to it.  Having all these features 
available to open as arguements seems a much better idea to me. It's 
"Open a file with these specifications", not "Open a file, and then 
apply these specifications to it".

I do admit there is merit to your abstraction system, but IMO, it 
belongs in a library.

-- Rod Adams


Re: Why do users need FileHandles?

2004-07-19 Thread Rod Adams
Austin Hastings wrote:
--- Rod Adams <[EMAIL PROTECTED]> wrote:
 

I think part of the "mental jam" (at least with me), is that the 
read/write, exclusive, etc, are very critical to the act of opening
the file, not only an after the fact restriction on what I can do 
later.
   

But why? I'd argue that this ties in to the verbose/exception
discussion of a few weeks back: if the operation fails, let it pass an
exception up the chain that can be caught and resolved (once) at a high
level.
 

Guess I'm still in the
open "foo" or die;
mentality.
Given that file processing is so common in Perl, it deserves a high
huffman scoring. The best way to do that is to abstract the operations
away and replace them with a single declaration of intent. That
declaration, of course, becomes a front-end for C or heavily optimized
parrot.
In a heavily OO paradigm, there would be a swarm of subclasses of type
stream -- istream, ostream, iostream, exclusive_iostream, whatever.
 

Is
my $file = append_text_stream "foo.txt";
really so much better than
my $file = open ">>foo.txt";
I'd strongly prefer having a few, extremely flexible, orthoganal, and 
complete tools, that DWIM the common case for me, than to have to sort 
through a long list of classes to get what I'm looking for.

Now, there's nothing stopping open from returning an object of class 
FileHandle::OStream::Text::Exclusive or whatever. And that object can 
have lots of useful methods to play with. But let me describe to open 
what type of file I want, and let it sort it out.

Another part of me that resists this is that I don't necessarily agree 
with a heavy OO paradigm. I've written several large projects in both a 
OO environment, and non-OO. I have almost always found the OO paradigms 
force me to convert what I wanted to do into something much more painful 
than the non-OO methods. It typically breaks down into the moment you 
want to do something to an object that the class designer did not take 
into account, you basically have to either rebuild parts of the object 
heirarchy from scratch, or get into really ugly things like declaring 
everything a friend of each other, or having to many accessor method 
calls you can't help but slow the whole program down.

Also, my experience is that when following a heavy OO paradigm, you 
often fall into the trap of "There is only one way to do it. Why would 
you ever want another?"

Is all OO bad? of course not. I use for several things, on a frequent 
basis. Is something that's OO necessarily better than something that's 
not? Despite the rumors from the Java crowd, no.
So while I embrace Perl6 having extremely strong OO capabilities, I will 
argue strongly against it taking over the language.

If I cannot open a file for writing (permissions, out of space, 
write locked, etc), I want to know the instant I attempt to open it
as such, _not_ when I later attempt to write to it.  Having all 
these features available to open as arguements seems a much better 
idea to me. It's "Open a file with these specifications", not "Open
a file, and then apply these specifications to it".
   

But why? Do you really open files and then perform an hour of work
before attempting to use them? I'll argue that's not the normal case;
rather, the normal case is something like
 open  or die ...
 other_stuff()
 while (...) {
   print ...
 }
 close
and the intervening delay (other_stuff) is negligible in wall-clock
terms: when a failure occurs, the user hears about it immediately.
 

It's often that I'll open a file to make sure I can save my results, 
then begin some process that is better measured in hours than seconds, 
and then begin outputting. It's not infrequent for me to have a list of 
five or six open statements at the start of a long process, and then 
close them all at the end.

I do admit there is merit to your abstraction system, but IMO, it 
belongs in a library.
   

I think rather that the abstraction should be the default, and the
individual "I don't trust Perl" functions should be available as
separate entry points if the user explicitly requires them.
 

TMTOWTDI can apply here, I believe. You give me my way, I'll give you 
yours. Leave me open with all my parameters, and you can have your list 
of file abstraction classes. I could see having those classes part of 
core, if there's enough support for them, and then something simple like 
"use Files;" to turn them on.

Just my 2¢.
-- Rod


Re: Progressively Overhauling Documentation

2004-08-23 Thread Rod Adams
Juerd wrote:
David Green skribis 2004-08-23 11:30 (-0600):
 

One of the selling features (or one of the features that is always sold) 
of POD is that you can mix it with your code.  Except nobody does, at 
least I can't recall that last time I saw a module that did that, and I 
don't think I've ever really done that myself.  The POD usually sits in 
a lump at the end of the file. 
   

I'll consider inline documentation when POD can be inlined. But as long
as =command paragraphs need to start in the first column, I'm not
interested in this feature.
 

What if we add C attribute that the execution compiler would 
discard, but POD compilers (and debuggers) could make use of? I believe 
that would even allow a particularly stringent corporate policy to 
create a flavor of 'strict' which required documentation of various 
classes of elements (though whether anyone would work there is another 
question...).
But imagine debugging code, and being able to quickly see a comment on a 
variable you can't figure out.

Juerd's sample would become:
sub foo :doc("take an Foo::Bar, and foo it over.") (
 Foo::Bar$bar:doc("what to foo up."),
 Quux::Xyzzy $xyzzy  :doc("Xyzzy to foo bar with"), 
 +$verbose,
 +$foo
} returns Array | undef {
   # real code here
}

-- Rod Adams


Pipeline Performance

2004-08-30 Thread Rod Adams
Over in the Perl Question of the Week list, ( 
http://perl.plover.com/qotw/ ), we entered a discussion of the 
performance, or lack thereof, of pipelining in Perl 5. Randy Sims's 
example code demonstrates this well, and is attached at the bottom of 
this post. The overall point is that pipelining arrays is significantly 
slower than unraveling the pipeline and creating a for or while loop, 
largely due to the temporary lists that must be created.

My question is, is there anything that can be done within Perl 6 to help 
alleviate this issue. It would seem that there are basically two types 
of functions which get placed into a pipeline: sequential and 
non-sequential. Sequential functions, like map and grep, do not need the 
entire input list to begin generating output. Non-sequential functions, 
like sort and reverse, need the entire input list before any output can 
be generated. In this regard, non-sequential functions cannot helped.

But sequential ones, on the other hand, should not need to collect their 
entire input before passing on output. I've seen discussions of lazy 
lists around here before, but I forget the context. Could one write a 
lazy version of C, which only reads an input when an output is 
being requested? And therefore something like:

@x = @y ==> map lc ==> grep length == 4;
Would behave quite differently from:
@temp = map lc, @y;
@x = grep length ==4, @temp;
in that no version of @temp (even internal) is needed.
Of course, I'd want to be able to construct my own map like functions, 
and have creating them with pipeline performance in mind to be easy.

Just a thought, since with the creation of ==> and <==, pipelining is 
bound to become an even more common construct.

-- Rod Adams

Randy Sims's test case:
#!/usr/bin/perl
use strict;
use warnings;
use Benchmark qw(cmpthese);
my $dict = 'projects/qotw/words';
# prime disk cache
open( my $fh, $dict ) or die;
my @result = <$fh>;
close( $fh );
cmpthese( 10, {
 'simple'  => sub{ simple( $dict, 5 ) },
 'compound' => sub{ compound( $dict, 5 ) },
});
sub simple {
   my( $dict, $word_length ) = @_;
   open( my $fh, $dict ) or die;
   my @result;
   while (defined( my $line = <$fh> )) {
   chomp( $line );
   $line = lc( $line );
   push( @result, $line ) if length( $line ) == $word_length;
   }
   close( $fh );
}
sub compound {
   my( $dict, $word_length ) = @_;
   open( my $fh, $dict ) or die;
   my @result = grep length( $_ ) == $word_length,
map { chomp; lc }
<$fh>;
   close( $fh );
}
__END__


Re: Pipeline Performance

2004-08-31 Thread Rod Adams
Aaron Sherman wrote:
On Mon, 2004-08-30 at 16:34, Rod Adams wrote:
 

@x = @y ==> map lc ==> grep length == 4;
   

I would think you actually want to be able to define grep, map, et al.
in terms of the mechanism for unraveling, and just let the optimizer
collapse the entire pipeline down to a single map.
To propose one way of doing it (and really just a simple example off the
top of my head which may not be the best idea...):
macro grep(&cond, [EMAIL PROTECTED]) is mapper {
if cond($_) { ($_) } else { () }
}
macro map(&cond, [EMAIL PROTECTED]) is mapper {
cond($_)
}
Which would do two things:
1. Define a subroutine of the same name that does the full map:
sub grep (&cond, [EMAIL PROTECTED]) is mapper {
my @result;
for @list -> $_ { push @result, $_ if cond($_) }
return @result;
}
2. Populates an optimizer table with just the macro form
When you see C now, you can just
consult that table and determine how much of the pipeline can be
transformed into a single map.
There, you're done. No more pipeline overhead from list passing.
Now, of course you still have things like sort where you cannot operate
on single elements, but those cases are more difficult to correctly
optimize, and lazy lists won't help those either.
 

So if I was to write my own function, and wanted it to be in the middle 
of a pipeline, but I wanted it to have a lazy evaluation feature, how 
would I write that?

For reference, let's use the following problem:
Take as input a list of numbers. For every five numbers, return the 
median element of that grouping. If the total list length is not 
divisible by five, discard the rest. (Not the most useful, but this is 
just example code).

Basic sub to do this:
sub MediansBy5 ([EMAIL PROTECTED]) {
 my @result;
 while @list.length >= 5 {
   push @result, (sort @list.splice(0,5))[2];
 }
 return @result;
}
I would suspect that this would not be evaluated in a lazy manner, 
especially because I'm pooling the results in @result.

One solution I see to this would be to have a "lazy return" of some 
kind, where you can send out what results you have so far, but not 
commit that your execution is over and still allow further results to be 
posted. For lack of better word coming to mind, I'll call a "lazy 
return" C.

Example above becomes:
sub MediansBy5 ([EMAIL PROTECTED]) {
 while @list.length >= 5 {
   emit (sort @list.splice(0,5))[2];
 }
}
And then you could have the relatively simple:
sub grep (&cond, [EMAIL PROTECTED]) {
 for @list -> $_ { emit $_ if cond($_); }
}
sub map (&func, [EMAIL PROTECTED]) {
 for @list -> $_ { emit func($_); }
}
Thoughts?
-- Rod Adams



Re: Synopsis 9 draft 1

2004-09-03 Thread Rod Adams
Larry Wall wrote:
On Fri, Sep 03, 2004 at 05:45:12PM -0600, John Williams wrote:
: What happens when the Pascal programmer declares
: 
: my int @ints is shape(-10..10);
: 
: Does it blow up?

No.
: If not, does  @ints[-1]  mean the element with index -1 or the last element?
The element with index -1.  Arrays with explicit ranges don't use the
minus notation to count from the end.  We probably need to come up
with some other notation for the beginning and end indexes.  But it'd
be nice if that were a little shorter than:
   @ints.shape[0].beg
   @ints.shape[0].end
Suggestions?  Maybe we just need integers with "whence" properties... :-)
Larry
What jumps to my mind is that inside an array subscript could be 
(sub)?context of it's own. Then one could do:

@ints[.beg .. .end ; .beg + 3 .. .end];
Where the .beg and .end would relate to @ints.shape[0] or @ints.shape[1] 
depending on which position it's in.

My only issue with this, and why I refered to it as a possible 
subcontext, is that it's easy to concieve of somewanting to use the 
prior context to generate the subscripts for an array.

The other idea which jumps to mind was to create an operator which tell 
the compiler to treat the the following number as if it referred to a 
0-based (sub)array, and negatives count off the end. What springs to my 
mind is that we are saying this is the "relative to start / end" of the 
range, so I will call it Î (capital delta).

@ints[ Î0 .. Î-1 ; Î3 .. Î-1 ];
It at least looks nice.
-- Rod


Re: parameter contexts (was: Synopsis 9 draft 1)

2004-09-03 Thread Rod Adams
Larry Wall wrote:
I'm still thinking A is the first one and Z is the last one.  Someone
talk me out of it quick.
I had thought about A and Z before my previous post. I dismissed it for 
two reasons:

1) Using Alphas as an index for something that should be numeric can be 
very confusing. Especially when one sees:

@Int[4 .. Z];
2) If A = first and Z = last, DWIM (but maybe not DWYM) would dictate 
that I should be able to say:

@Int[C .. Y];
instead of:
@Int[A+2 .. Z-1];

That's why I liked the concept of an operator to modify the number 
afterwards. Okay, Î might not have been the best choice, but there are 
other options. Looking at your preferred Latin-1 table, we have:

 (§) "Use this Section of the array"
 (®) The R means "Relative to base"
Or if we want to get silly, use  instead of .., and just use the 
numbers as is.

If you insist on using A and Z, at least make them \A and \Z, to give a 
stronger visual cue that something different is happening.

-- Rod



Re: Pipeline Performance

2004-09-18 Thread Rod Adams
Luke Palmer wrote:
Jonadab the Unsightly One writes:
 

Rod Adams <[EMAIL PROTECTED]> writes:
   

One solution I see to this would be to have a "lazy return" of some
kind, where you can send out what results you have so far, but not
commit that your execution is over and still allow further results to
be posted. For lack of better word coming to mind, I'll call a "lazy
return" C.
Example above becomes:
sub MediansBy5 ([EMAIL PROTECTED]) {
 while @list.length >= 5 {
   emit (sort @list.splice(0,5))[2];
 }}
 

That's actually a very good idea.  That's why Perl 6 has it :-)
   sub MediansBy5 ([EMAIL PROTECTED]) {
   gather {
   while @list >= 5 {   # there's no .length; it's .elems
   take (sort @list.splice(0,5))[2];
   }
   }
C returns a list of everything that was Cn inside of it.
It does this by building a coroutine out of its argument, so it works
lazily.
Luke
Better documentation on gather/take is merited.
Before starting this thread, I did a search on gather/take, thinking it 
might be what I needed, but all I could find was in A12 :

"We snuck in an example the new |gather|/|take| construct. It is still 
somewhat conjectural."

This was not very informative.
Not to mention, it should be in S4/S9, not A12.
I would question the need for C, however. Could not a lone 
C/C force the return value of the enclosing routine/closure 
to be a lazy list, and here's a few values to get things started?

To address Jonadab's questions:
1. What if anything do you propose is the evaluation value of emit?
The lazy list being constructed. Maybe a reference to it instead.
2. Should a subsequent implicit return behave differently than usual 
if some values have already been emitted?
This is a bit harder, but I would think it should emit it's parameters, 
then exit the routine.
The downside would be it forces list context where it might not have 
existed before, but it's the most consistent thought I have.

One other question: Would emit behave differently if the sub is called 
in a non-list context, such as void context or a scalar context? 
My thought is that it returns a lazy list, and P6 rules for converting 
such a thing into a void or scalar would apply.

-- Rod Adams.


Re: S5 updated

2004-09-21 Thread Rod Adams
Luke Palmer wrote:
Edward Peschko writes:
 

Ok, fair enough.. although I'm not sure that I'm all that sure I'm completely
happy-with/understand the syntax described in that article. It works for the trivial 
cases, but what about complex grammars? 
   

It works for anything.  It gets pretty inefficient in the case of code
assertions, but there's no way around that.  Testing your assertions
isn't going to be the useful thing about this, anyway.
 

Eyeballing and fixing the regular expression then becomes trivial (or relatively 
trivial).
   

I definitely see the use.
You just pass it to generate.  It recursively calls itself until it's
down to constant strings, which are always a well-defined match (or
character classes, which are tricky and computationally intractible in
the presence of unicode).
I love programming in theoretical Perl 6.
Luke
Now this is truly useful. Especially when one realizes that all of Perl 
6 is already expressed in these handy regular expressions.

It's therefore possible to generate all possible Perl 6 programs, then 
simply see which one(s) satisfy your test cases, and there's no need to 
do any silly programming ever again!

And just think... All the p6c group has to do is a little prep work, and 
P6 will then write itself! Just think of the marketing ploy: "Other 
languages were written _in_ themselves. Perl was written _by_ itself."

This solution definitely has Laziness and Hubris going for it, though I 
suspect it may be lacking in the Impatience department.

(I need more sleep)
-- Rod Adams


Re: S5 updated

2004-09-24 Thread Rod Adams
Edward Peschko wrote:
Well, there re two responses to the "that's not a common thing to want to do":
   1) its not a common thing to want to do because its not a useful thing to do.
   2) its not a common thing to want to do because its too damn difficult to do.
I'd say that #2 is what holds. *Everybody* has difficulties with regular 
expressions - about a quarter of my job is simply looking at other 
people's regex used in data transformations and deciding what small 
bug is causing them to fail given a certain input. 

Running a regular expression in reverse has IMO the best potential for making
regexes transparent - you graphically see how they work and what they match. 
So would this get used? Yes - far more IMO than *other* parts of the 
language that already are sanctified: continuations, for example.

I have to disagree here. I've also been the head of a major data 
transformation project that used P5 RE engine as a workhorse. And yes, 
they are a pain to debug. But I really don't think that a RE --> string 
generator is the solution.

What's wrong with it? Quite simply, they can generate way too many 
different results, and finding the ones that will give you insight can 
be challenging at best. I imagine  it seeing the first * or + and then 
generating an infinite number of strings for just that. What logic would 
you impose to truncate this list in a "standard" way?
Given a long list of possibilities, I'd be tempted to write a different 
RE to scan the matches of the generation of the first RE, and how should 
I then debug the second ones? Also, showing a list of _what_ that RE 
does match gives no clues as to _why_ it matched it, or moreover, why it 
_didn't_ match what you wanted. I just don't see it as being useful.

Oh, and I'd disagree with "*Everybody* has difficulties with regular 
expressions". If after a month of working on my project, if you still 
had troubles building/modifying RE's, your job future there would be in 
serious question. But I never had a problem with that. Once people got 
up to speed, it was mainly just the tedium of dealing with the volume of 
rules and data that got to people. And for reference, outright nasty 
RE's were fairly commonplace.

There's simply no way to graphically show regexes now. Even use re 'debug' is 
terribly cryptic. The best way to deal with them right now is to burn a regex
parser into your brain.

Ahh... Now this is the real problem. People need someway to better see 
how a given RE attacks a given string. I see potential for a standalone 
program that acts as a "RE analyzer". Inputs would be a RE and a string. 
Output would be a step by step graph of the internal logic used to match 
/ not match the string. I'd break the RE up into the same pieces the 
Engine does, then show how that subrule matched char a, then char b, but 
failed to match c, so it backtracked to a, etc.  I envisions three 
columns: partial string matched so far, partial RE used to match it, and 
whatever flags or comments the engine wishes to make at this juncture.

The beauty of this solution is, if Perl6 and/or Parrot (not sure which 
is the better choice) provides a few hooks into the P6RE Engine, it 
would be absolutely authoritative, and could even handle cases where the 
rules changed due to module loading. And since I'd expect those hooks to 
be in there anyways for other reasons (mainly, letting people muck 
around with how they work), I'd suspect all the "Core support" needed 
would already be there (I may be wrong.).

But it doesn't need to be core. A friendly side project, possibly 
mentioned in the core documentation as a learning tool, would do the job 
nicely. And it doesn't need to be discussed on p6i, p6l, or p6c, at 
least not for a very long time.

Or we could just burn a RE parser into everyone's brain, as you 
mentioned. That'd also work.

-- Rod Adams




S10/11 Questions

2004-11-09 Thread Rod Adams
Some questions:
-
Can we get an AUTOCLASS/AUTOCLASSDEF hook pair?
-
How does one create a class with a hyphen in the middle of it? If I say:
use Foo-Bar;
will it complain about not finding a Bar version of Foo? Would I instead 
need to say:

use 'Foo-Bar';
use Foo\-Bar;
use ('Foo-Bar');
$x = 'Foo-Bar'; use $x;
btw, that last one would be really handy sometimes, but for other reasons.
-
If we do:
use Dog-1.2.3;
use Dog-2.0.1;
my Dog $spot;
What do we get? Okay, I know, an error message, but is it on line 2 or 
line 3? Can we instead do something like:

use Dog-1.2.3;
use Dog-2.0.1 is rename(newDog);
my newDog $spot;
-
There needs to be some definition of what happens when more than one 
module matches a given wildcard in 'use'.

Something like:
  1. Throw a warning
  2. Pick the highest version, then the earliest source in the alphabet
of course, there should be a way to flag it to work in other ways, so 
some project could have a standard:

use ($^name ~~ /^Project::/)-(Any)-TPFBundle;
meant to include all the modules made thus far. And yes, I can come up 
with times when this would be useful.

-
I see some utility in having an optional sub-source or version code thingy.
Something like:
use Dog-(Any)-(Any)-Stable;
use Canine-(Any)-(Any)-Development;
-
Can we get a hook that gets called when 'use' fails to find module 
locally? I see potential for:

use AutoCPAN;
use Some::Module::Not::Currently::Loaded;
hmm. that doesn't work, since you typically won't be including the cpan 
author code if you don't have to.

CPAN, or some other public source would be a definate security risk, and 
thus to be discouraged, but it should be possible to write the thing. 
I've heard of sites who had massively distributed mod_perl servers, 
where all the code past a simple stub was stored in a central RDBMS. 
Made releases and version control much nicer.

-
By saying
#!/usr/bin/perl6
forces Perl 6, I assume you mean : "The compiler sees /:i ^#! .* perl6/ 
on the first line".

-
-- Rod Adams



Re: S10/11 Questions

2004-11-10 Thread Rod Adams
Larry Wall wrote:
On Tue, Nov 09, 2004 at 09:18:47PM -0600, Rod Adams wrote:
: Can we get an AUTOCLASS/AUTOCLASSDEF hook pair?
Considering a class is just a variable in another symbol table, seems
like an AUTOVAR in the container might cover it.
 

I guess I don't understand enough of how P6 is being built, but wouldn't 
a similar argument hold for AUTOMETH and AUTOSUB?

: $x = 'Foo-Bar'; use $x;
: 
: btw, that last one would be really handy sometimes, but for other reasons.

All symbolic indirection is done with ::($expr) in Perl 6, so it'd be
   use ::('Foo-Bar')
 

Very nice.
: If we do:
: 
: use Dog-1.2.3;
: use Dog-2.0.1;
: my Dog $spot;
: 
: What do we get? Okay, I know, an error message, but is it on line 2 or 
: line 3?

Presuming we add some way to do aliasing, line 2 would give an error.
: Can we instead do something like:
: 
: use Dog-1.2.3;
: use Dog-2.0.1 is rename(newDog);
: my newDog $spot;

More likely something on the order of
   module newDog ::= (use Dog-2.0.1);
where it's only a "use" in a void context that implicitly uses the same
short name as the alias.  But like I said, it's not even clear that the
pseudo listop syntax of "use" is the right way to handle this.  Maybe it's
just an "isa"-like thing:
   my module newDog is Dog-2.0.1;
or maybe it's more like a role:
   my module newDog does Dog-2.0.1;
But maybe it's something else again that we just haven't thought of yet.
 

I'm largely indifferent to the exact syntax involved, as long as I have 
some way to loading two different versions of the same module, and can 
then differentiate between them in my code. Possible reasons for loading 
two versions of the same thing:

1) Retrograde testing. You just built a new version, and you want to 
have the two versions running side by side through the test cases, 
without having to kick off a new instance.

2) The nifty new version has a whiz-bang function you really need, but 
in the process of upgrading, it broke some other whiz-bang function.

3) The two really are not the same thing, they were just given the same 
name.

There are some separate benefits of module aliasing, aside from loading 
like-named modules, to consider:

1) The module is named something like 
"AudioFile::Info::Ogg::Vorbis::Header::PurePerl", and you'd rather not 
type it more than once.

2) You just changed your entire module naming scheme, and want a stop 
gap measure for all you code that's still referring to the old names.

: There needs to be some definition of what happens when more than one 
: module matches a given wildcard in 'use'.
: 
: Something like:
:   1. Throw a warning
:   2. Pick the highest version, then the earliest source in the alphabet

I think you're assuming version numbers contain alphabetics.  I'd like to
stay away from that if possible.
Nope, I wasn't. I was using the word "source" where you were saying 
"author".

 But I think #2 is far and away the
most common intent with a wildcard on version numbers.  I don't know what
the pecking order should be among authors, but as someone who has suffered
from being a W, it's not going to be alphabetical.  :-)
My wife didn't believe me till she married me and moved from B to W.
Maybe #1 is a suitable response for multiple matching authors.  Or maybe
it should just pick one randomly to keep people honest.
 

As one with a last name starting with "ADA", I can't say I've noticed 
any problems with alphabetical. =).

As for picking "randomly", I think a more deterministic method would be 
in order. But something that can't be easily abused by naming it 
"". How about the following rules for multiple wildcard matches:

1) If the version numbers differ, pick the highest.
2) else, throw a warning (error if strictures), AND
2a) if one is in a directory earlier in @INC than the other(s), use it. 
(Allow users to have a local copy override a global one).
2b) else, pick the one with the lowest CRC32 value of the Author

: of course, there should be a way to flag it to work in other ways, so 
: some project could have a standard:
: 
: use ($^name ~~ /^Project::/)-(Any)-TPFBundle;
: 
: meant to include all the modules made thus far. And yes, I can come up 
: with times when this would be useful.

That sort of thing should be hidden in a metamodule.  In any event, it
doesn't give a good name to alias to.
metamodule. hmm. That brings us back to Aaron Sherman's topic of 
re-exportation.
How does one make a metamodule which uses other modules, and has those 
modules' exports available to metamodule's caller, as if the caller had 
instead called all of those modules in addition to the metamodule?

(And placeholders only work inside closures.)
 

Grr. My web browser used a font that does not adequately distingui

Re: can gather/take have multiple bins

2004-11-25 Thread Rod Adams
Dave Whipp wrote:
gather @bin1, @bin2 -> $bin1, $bin2{
 for @words {
   $bin1.take if /^^a/;
   $bin2.take if /e$$/;
 }
}
   

Juerd point out (private email) that my example doesn't really make any
sense in that it doesn't do anything over and above s/take/push.
However, I think the concept of multiple bins could still be useful. My
understand of gather/take is that the function that does the "gather" is
coroutined (if that's a verb) against the block that does the gathering. So
to be able to usefully use multiple streams, the "gather" would need to fork
into multiple threads that are then interleaved with the "gather" block.
Calling a function in junctive context does the forking bit, so a gather
that gathered in a junctive context might make sense as a serialization
mechanism. I can't quite work out what the syntax would be for that though.
Okay, thinking a bit about this, I agree that there are times when you 
want multiple lazy lists going on at the same time. But, frankly if the 
lists are lazy, why shouldn't the programmer be lazy as well?

@bin1 = gather {
 for @words {
take if /^^a/;
 }
}
@bin2 = gather {
 for @words {
take if /e$$/;
 }
}
Two lazy lists? Two gathers!
Since they are lazy, you can eval them in order you please.
I see a problem with attempting to put the two into one statement. In 
your example above, if you wanted something from @bin2, you could have 
to process a whole lot of things into @bin1, just to get the next 
element out of @bin2. In fact, you could easily end up processing all of 
@words, and filling @bin1, only to discover that @bin2 is empty. To me 
this kind of forced-fill of @bin1 is a complete defeat of the entire 
concept of _lazy_ lists.

There's also the issue of from what I understood of gather/take before 
(still awaiting a proper definition), gather returns a lazy list. So 
it's not C, it's C<@bin1 = gather {...}>. What 
would your C return? A list of lazy lists? How do you easily 
tell the difference between a list of lazy lists and a lazy list? I 
think it's better to leave a 1::1 gather::list ratio, as that will cover 
some {insert randomly high %age} of all cases. For the other cases, 
you're likely better off building a class with two emitter methods, and 
possibly even use C to make it look like two lazy lists.

-- Rod Adams

The thing about lists is that they are linear. They are, by definition, 
a sequence of single items. Now, that 'single item' may very well be a 
reference to something non-trivial, but to the list it's a single value.




Hyper Here-Docs? (was: Re: angle quotes for here-docs ?)

2004-11-25 Thread Rod Adams
Juerd wrote:
Thomas Seiler skribis 2004-11-25 14:52 (+0100):
 

Is $heredoc = «END; the same as $heredoc = <
   

I certainly hope not.
Quoting the delimiter is needed, by the way.
How is <<'END' disambiguated from <<'qw' list>>, anyway?
 

Seeing the « in the context of a here-doc made me think "can you do a 
»<< here-doc?"

So, something like :
@text = »<
text2
END
text3
END
text4
END
for @text { ...}

The hard question about this is: how do you know when you've hit the 
last END? especially if the text you're loading looks like Perl code, or 
if you have different <

btw, should it be »<<, <<«, or »<<«?
-- Rod Adams


Re: Angle quotes and pointy brackets and heredocs

2004-11-28 Thread Rod Adams
On Fri, Nov 26, 2004 at 07:32:58AM +0300, Alexey Trofimenko wrote:
I notice that in Perl6 thoose funny « and » could be much more common 
than  other paired brackets. And some people likes how they look, but 
nobody  likes fact that there's no (and won't!) be a consistent way to type 
them  in different applications, wether it's hard or easy.

But to swap «» with [] or {} could be real shock for major part of 
people..
We also have another ascii pair, < and > . maybe they could be better than  
« and » ?:) i'm not that farseeing, but isn't problem of distinguishing < 
as a bracket and < as an comparison operator no harder than distinguishing  
<< as bracket and as part of heredoc?..
 

Speaking of heredocs.
Are they really common enough to merit a "two char, absolutely no 
whitespace after it" lexical? Especially one that looks a lot like the 
left bitshift operator, as well as an ASCII version of a Unicode quoting 
and splitting character?

What if instead, we add a different adverb to q// and qq//? something 
like :h. That way people can mix and match all the quoting option they 
want, and we remove some annoying requirements about when you can and 
cannot have /<<\s+/ in your code.

P5:
print <<"END", " done.\n";
line 1
line 2
END
P6:
say qq:h/END/, "done.";
line 1
line 2
END

As for the topic being discussed,
Since < and > are now full class quote-like thingies in P6REs, much to 
the chagrin of those of us who parse html on a regular basis, using them 
as such in the rest of P6 makes sense as well. Parsing should not be 
hindered since one would occur in operator context, and the other in 
expression context.

-- Rod Adams


Re: Angle quotes and pointy brackets

2004-11-30 Thread Rod Adams
Brent 'Dax' Royal-Gordon wrote:
I like this in general.  However...
Larry Wall <[EMAIL PROTECTED]> wrote:
 

   * Since we already stole angles from iterators, «$fh» is not
   how you make iterators iterate.  Instead we use $fh.fetch (or
   whatever) in scalar context, and $fh.fetch or @$fh or $fh[]
   or *$fh in list context.
   

I believe you tried this one a couple years ago, and people freaked
out.  As an alternative, could we get a different operator for this? 
I propose one of:

   $fh ->
   $fh» (and $fh>>)
   $fh>
All three have connotations of "the next thing".  The first one might
interfere with pointy subs, though, and the last two would be
whitespace-sensitive.  (But it looks like that isn't a bad thing
anymore...)
Any other suggestions, people?
 

++$fh



Re: Arglist I/O [Was: Angle quotes and pointy brackets]

2004-12-04 Thread Rod Adams
Larry Wall wrote:
So you can say
   for =$*IN {...}
   for =$*ARGS {...}
   for = {...}
   for = {...}
   for =«$foo.c $foo.h» {...}
   for =['foo.c', 'foo.h'] {...}
   for =['.myrc', @*ARGS] {...}
   for [EMAIL PROTECTED] {...}
   for =<> {...}
 

The simplicity is nice, but the visual message is, well, icky.
It might be salvageable by having the ='s balance, yielding:
   for =$*IN= {...}
   for =$*ARGS= {...}
   for == {...}
   for == {...}
   for =«$foo.c $foo.h»= {...}
   for =['foo.c', 'foo.h']= {...}
   for =['.myrc', @*ARGS]= {...}
   for [EMAIL PROTECTED] {...}
   for =<>= {...}
That looks better. Might even make the trailing = mean something useful 
like "auto-chomp".


And I don't think it'll be visually confusing to people who put spaces
on both sides of their assignment operators.
 

But those of us who often use the horizontal ws to break up the terms on 
a line will moderately often not put spaces around our assignments and 
less thans.

Okay, this rant is more about the \s<\s than \s=\s. To me, it is easier 
to understand the grouping of line 1 than line 2 below:

if( $a<$b && $c<$d ) {...}
if( $a < $b && $c < $d ) {...}
In line2, my mind has to stop and ask: is that "($a < $b) && ($c < $d)", 
or "$a < ($b && $c) < $d". It quickly comes to the right answer, but the 
question never comes up in the first line. If I wanted to use more 
parens for clarity, I'd use LISP.

-- Rod Adams


Re: pull & put (Was: Angle quotes and pointy brackets)

2004-12-04 Thread Rod Adams
Brent 'Dax' Royal-Gordon wrote:
Smylers <[EMAIL PROTECTED]> wrote:
 

Yes.  C is a terrible name; when teaching Perl I feel
embarrassed on introducing it.
   

C's only virtue, IMHO, is that it's clearly the inverse of
C.  But I think the spelling and aural relationship between
C, C, C, and C is clear enough to negate that.
But then, I'm a little biased.
Except that push and pull are logical opposites linguistically, but not 
in standard CS parlance. could be very confusing.

There's a possibility of using C and C for enqueue/dequeue, 
except that C == C in standard implementations.

So C and C? yeck.
-- Rod Adams



Required whitespace issues.

2004-12-04 Thread Rod Adams
Alexey Trofimenko wrote:
On Sat, 04 Dec 2004 11:03:03 -0600, Rod Adams <[EMAIL PROTECTED]> wrote:
Okay, this rant is more about the \s<\s than \s=\s. To me, it is 
easier  to understand the grouping of line 1 than line 2 below:

if( $a<$b && $c<$d ) {...}
if( $a < $b && $c < $d ) {...}
In line2, my mind has to stop and ask: is that "($a < $b) && ($c < 
$d)",  or "$a < ($b && $c) < $d". It quickly comes to the right 
answer, but the  question never comes up in the first line. If I 
wanted to use more  parens for clarity, I'd use LISP.

I've got used to write it as
   if( $a < $b and $c < $d) {...}
already. if it could help.. :)
Yes, I know all about being able to use 'and' instead of '&&', and that 
does make things a bit more readable. But I prefer to reserve 'and/or' 
for those cases where you really need the ultra loose binding. Like when 
you have assignments mixed in.  Not to mention that when you remove the 
()'s on control structures, it's easy to confuse the reader (but likely 
not the parser) as to whether your inside the conditional, or outside of 
it, since and/or are often used as a poor man's if.

$y++ while $a < $b[$bar]{$baz =  =<'foobar'>}
 and $c = $d;
Not that I'd actually ever write something that obscene.

I'm deciding I don't like the unary = proposal, for similar reasons to 
<.  It feels like we are rapidly approaching the point where all binary 
operators require surrounding whitespace, to distinguish them from 
similar looking unary/quoting operators. There are at least enough of 
them, including fairly popular ones like = and <, (but not necessarily 
>), that allowing some of them to be \S\S is bound to cause a 
great deal of confusion. In fact, unary = imposes whitespace 
requirements on all ops that end in =.

So I would suggest that P6 adopt one of the following:
1) \S\S is allowable for for all .
2) \s\s is required for all , save method postfix ones.
Pros \S\S  :
- very P5ish
- allows users great flexibility on how they logically group terms in 
more complex expressions
- one liners get easier, especially on platforms that have troubles 
passing args with whitespace in them.

Cons \S\S:
- requires a great deal of reworking to remove ambiguity with similar 
looking unary ops.
- can make code indistinguishable from line noise at times.

Pros \s\s :
- opens up the realm of available binary and unary/balanced ops 
considerably.
- makes life easier for the lexical analyzers.
- forwards compatible with new operators, including user defined ones.

Con \s\s:
- very imposing for an otherwise programmer friendly language.
- makes obsfication contests a lot harder.
Personally, I would very much prefer \S\S. But I strongly suspect 
that removing all the conditions where \s\s is needed is a lost 
cause at this stage on the game. So barring that possibility, I'd vote 
for the consistency of \s\s. But I still wouldn't like it.

For reference, here is a list of the operators that have some form of 
whitespace issue so far:

=
:=
::=
+=
-=
*=
**=
.=
/=
//=
||=
&&=
%=
<
<==
+<
>=
<=
==
!=
=:=
all the alpha ops
+<<
~<<
many hyper variants of operators
..   # 0 .. .length() vs 0 ... length()
likely others as well.
-- Rod Adams


Re: Required whitespace issues.

2004-12-04 Thread Rod Adams
Larry Wall wrote:
On Sat, Dec 04, 2004 at 08:14:17PM -0600, Rod Adams wrote:
: In fact, unary = imposes whitespace requirements on all ops that end in =.
Not true.
I guess not all cases.  But several do in certain situations.
$x ==<$foo>;   # $x == <$foo>;   $x = =<$foo>;
@x <==<$foo>;  # @x <= =<$foo>;  @x <== <$foo>;
$x//=<$foo>;   # $x // =<$foo>;  $x //= <$foo>;
[EMAIL PROTECTED];   # $x ** [EMAIL PROTECTED];  $x **= @y;
Enough to make my overall issue of "an increasing number of operators 
are acquiring whitespace requirements" valid. If I'm not mistaken, \S<\S 
is invalid, but \S>\S is valid.

The rest of my post can be summarized as "A consistent set of rules 
about when whitespace is and is not allowed are in order."

-- Rod Adams





Re: Required whitespace issues.

2004-12-05 Thread Rod Adams
Larry Wall wrote:
<>On Sat, Dec 04, 2004 at 08:55:00PM -0600, Rod Adams wrote:
 
: $x ==<$foo>; # $x == <$foo>; $x = =<$foo>;
: @x <==<$foo>; # @x <= =<$foo>; @x <== <$foo>;
: $x//=<$foo>; # $x // =<$foo>; $x //= <$foo>;
: [EMAIL PROTECTED]; # $x ** [EMAIL PROTECTED]; $x **= @y;

In each of those cases the longest-token rule comes into effect.
That's not only consistent, but standard CompSci for the last 30 years
or so. The only person who will get burned on those is someone who
insists on *not* putting whitespace in front of unary = when it would
be ambiguous. I have negative sympathy for such people. 
<>Well said!
Although I by no means dispute that longest token rule is a long term 
standard in language design, I will claim that many programmers, 
including myself before this, are unaware of it.

So I will now change my concerns to:
"The longest-token rule needs to be mentioned in S03, and explained in a 
future perlop.pod."

-- Rod Adams



Re: pull & put (Was: Angle quotes and pointy brackets)

2004-12-06 Thread Rod Adams
Dan Brian wrote:
If I went with "get", the opposite would be "unget" for both historical
and huffmaniacal reasons.

But "get" has too strong a class accessor connotation in most OO.
"unpull?" ;-)

pushf/popf.  f is for "front".
But I still don't see anything wrong with shift/unshift.
I'd prefer to avoid having a group of words that all mean about the same 
thing, but keeping them straight requires some memory trick. I program 
in too many languages to keep my mnemonics straight. There's going to be 
enough fun with is/has/does/but. For reference, I always have to do a 
'perldoc perlvar' when I need a P5 $.

-- Rod Adams




Auto My?

2004-12-18 Thread Rod Adams
Considering that "proper" and common usage, not to mention strictures, 
dictates a heavy insistence on 'my'. I will thus assume that creation of 
lexical variables with 'my' far out numbers the creation of package 
space globals. Should we not then have it where it's the default 
behavior, and creation of package ones take explicit declaration (via 
'our')?

Well, at least when strictures are on. When they are off, the coder is 
obviously playing fast and loose, and should get the easy 'everything 
global' behavior.

What issues am I overlooking here?
-- Rod


Re: Auto My?

2004-12-19 Thread Rod Adams
James Mastros wrote:
Juerd wrote:
Just typing "my " before the first use of a variable isn't hard, and it
makes things much clearer for both the programmer and the machine. 
Does this imply that it's now possible to type C, 
and declare @foo?  In the current perl, this doesn't work -- it's a 
syntax error.  It'd certainly make many constructs easier.
I see why that's an error. It can be very confusing In literal 
fashion you are attempting to make the 24th element of @foo lexical, and 
having some elements of @foo have different scope from the rest is a bad 
idea.

However, I have also been bitten by that rather frequently, though with 
a different construct. Typically it's with hash slices:

my @[EMAIL PROTECTED] = @[EMAIL PROTECTED]; # ERROR!
my %newhash;
@[EMAIL PROTECTED] = @[EMAIL PROTECTED]; # Okay, but not as convienent.
This was part of the reason I spawned this thread. But it was also due 
to being in the middle of trying to write some decent quality code under 
a heavy time pressure, and noticed that >50% of my lines had a 'my' on 
them. It's typically not that high of a percentage, but when you are 
creating lots of small utility routines, declaring all your lexicals can 
be a significant part of the task. I added to this the observation that 
lexical variables are significantly more common than non-lexicals, and 
thought out loud as to why I was doing more work for the common case 
than the uncommon case, in a language that generally doesn't have that 
problem.

One of the other reasons in favor of the idea was aesthetic.
# stuff which declares $x, $z, and $q
$x = 4;
my $y = 7;
$z = 12;
my $r = 4543;
$q = 121;
compared to:
# stuff which declares $x, $z, and $q
$x = 4;
$y = 7;
$z = 12;
$r = 4543;
$q = 121;
With a fixed width font, like all code editors use, all the =' like up, 
and I can quickly scan the var names to get to the one I want to change 
at that moment. Yes, I could have added a 'my ($y, $r);' to the front of 
the list, but that's adding another statement to the mix, same as the 
hash slice above, adding considerably more weight to 'my' than just 
three keystrokes (m - y - space).

However, given the strong opposition (with merits) to this in other 
responses, I am willing to live with it the P5 way. Just seemed like 
autolexicals was rather DWIMish.

Another facet of this discussion comes into account when also specifying 
type.

from S9:
 my bit @bits;
 my int @ints;
 my num @nums;
 my int4 @nybbles;
 my str @buffers;
 my ref[Array] @ragged2d;
 my complex128 @longdoublecomplex;
Wouldn't this be much better as:
 bit @bits;
 int @ints;
 num @nums;
 int4 @nybbles;
 str @buffers;
 ref[Array] @ragged2d;
 complex128 @longdoublecomplex;
Given that most of the stated reservations had to deal with explicit 
declaration better defining scope, what is wrong with drooping the my in 
this case?

-- Rod Adams


Re: = vs <== [was: Perl 6 Summary for 2005-01-31 through 2004-02-8]

2005-02-09 Thread Rod Adams
Larry Wall wrote:
On Wed, Feb 09, 2005 at 10:04:48AM +0100, Michele Dondi wrote:
: On Tue, 8 Feb 2005, Matt Fowles wrote:
: 
: >  pipe dreams
: >   Juerd wondered if he could mix = and ==> in a sane way. The answer
: >   appears to be no. Once you bring in ==> you should stick with it.
: 
: Huh?!? It doesn't seem to me that the answer is 'no'. In fact C<< ==> >> 
: is supposed to be yet another operator, albeit somewhat a special one. If 
: I got it right the answer is actually 'yes': what Larry suggested is that 
: it would be _stylistically_ better to stick with it once it is used in the 
: first place.

Yes, you can certainly intermix them as long as you keep your
precedence straight with parentheses.  Though I suppose we could go
as far as to say that = is only scalar assignment, and you have to
use <== or ==> for list assignment.  That would be...interesting...to
say the least.  For instance, it would eliminate the guessing games
about whether the syntactic form of the left side indicates a list.
Doubtless there would be some downsides too...
Larry
I have to say that my initial reaction to this was one of disgust, but 
the more I think about it, the more I am warming to the idea of having a 
more robust method of declaring list context vs scalar context.

Issues that arise (my mind has yet to settle enough to label them 
"downsides"):

- List assignment is way too common to inflict a three char operator on, 
especially one that really likes having \S around it. (But don't ask me 
what else to use, not much is left available.) At least, it's way too 
common for me.

- orthogonality says that we would then need a left scalar assignment 
operator to mimic ==>. Linguistically, this is "Calculate all this, then 
stuff the result into $x". This would be very nifty when building long 
self-referring assignments, because the assignment appears after the 
expression which used the previous value, which just "flows" better. 
.

- Would C<< @x = @y; >> then mean C<< @x := @y; >>?
- Somehow, C<< %x <== %y; >> feels very, very wrong.

Pluses:
- I've often considered list assignment to be one of the most useful and 
subtle things that makes Perl Perl, especially when combined with 
hash/array slices. However, attempting to bring less monkish fellows up 
to enlightenment often encounters mental blocks. This might help, having 
a different syntax makes it significantly less 'magical'. (even though 
Magic is Good, imho)

I should probably stop rambling now and get some sleep.
-- Rod Adams




Pop a Hash?

2005-02-09 Thread Rod Adams
Does
($k, $v) <== pop %hash;
or
($k, $v) <== %hash.pop;
make sense to anyone except me?
Since we now have an explicit concept of pairs, one could consider a 
hash to be nothing but an unordered (but well indexed) list of pairs. 
So, C<< pop %hash >> would be a lot like C<< each >>, except, of course, 
that it deletes the pair at the same time.

If we do that, I'd also want to be able to
push %x, %y;
which would mean something like:
%x{%y.keys} <== %y{%y.keys};
but be much easier to read.
-- Rod Adams.
(And now I'm really off to bed.)


Re: Fwd: Junctive puzzles.

2005-02-10 Thread Rod Adams
Patrick R. Michaud wrote:
Even if you fixed the =/and precedence with parens, to read
  my $x = (any(2,3,4,5) and any(4,5,6,7));
then I think the result is still that $x contains any(4,5,6,7).
 

Funny. I thought $x would contain 'true' here, since C was a 
boolean operator. But I could be very wrong.


The overall impression I'm getting here is that we need some syntax for 
saying:

$x = any(1..1000) such_that is_prime($x);
where "such_that" acts as a form of "junctive grep". so the above might 
mean the same as:

$x = any(1..1000 ==> grep(is_prime($_)));
We then can say that any junction stored in a var stays constant, until 
explicitly reassigned. Just like every other kind of thing we store.

Philosophy Question:
What's the difference between a junction and an array containing all the 
possible values of the junction? Other than how they are used, of 
course. So, on that train of thought, would this make sense:

if $x == @x.any {...}
if $x == @x.none {...}
If this is the case, then this entire discussion collapses into how to 
best convert arrays into junctions and junctions into arrays. Perl's 
existing abilities to edit arrays should be more than sufficient for 
editing junctions.

-- Rod Adams


Sets vs Junctions (was Junctive puzzles.)

2005-02-10 Thread Rod Adams
Damian Conway wrote:
Rod Adams wrote:
The overall impression I'm getting here is that we need some syntax 
for saying:

$x = any(1..1000) such_that is_prime($x);

In standard Perl 6 that'd be:
  $x = any(grep {is_prime $^x} 1..1000);
or, if you prefer your constraints postfixed:
  $x = any( (1..1000).grep({is_prime $^x}) );
Both of those seem way too brutal to me.

We then can say that any junction stored in a var stays constant, 
until explicitly reassigned. Just like every other kind of thing we 
store.

Yep. That's exactly what we'll be saying!
Good.

Philosophy Question:
What's the difference between a junction and an array containing all 
the possible values of the junction?

Junctions have an associated boolean predicate that's preserved across 
operations on the junction. Junctions also implicitly distribute 
across operations, and rejunctify the results.

My brain is having trouble fully grasping that. Let me attempt a paraphrase:
Junctions exist to be tested for something.
When a test is performed, the junction is evaluated in terms of that 
test. A "result junction" is created, which contains only the elements 
of the original junction which will pass that given test. If the result 
junction is empty, the test fails.

Looking at the S09 C<< substr("camel", 0|1, 2&3) >> example explains a lot.

So, on that train of thought, would this make sense:
if $x == @x.any {...}
if $x == @x.none {...}

Probably. It's entirely possible that, in addition to being built-in 
list operators, C, C, C, and C are also 
multimethods on Scalar, Array, and List.
okay.
--
Now that I've gotten some feedback from my original message (on list and 
off), and have had some time to think about it some more, I've come to a 
some conclusions:

  Junctions are Sets.  (if not, they would make more sense if they were.)
  Sets are not Scalars, and should not be treated as such.
  If we want Sets in Perl, we should have proper Sets.
Let's first define what a Set is:
- A Set is an unordered collection of elements in which duplicates are 
ignored.
- There are really only two questions to ask of a Set: "Is X a member of 
you?", and "What are all your member?"
- Typically, all members of a set are of the same data type. (I'm in no 
way committed to this being part of the proposal, but it makes sense if 
it is)

Sets and Lists are two different things. Lists care about order and 
allow duplicates. Iterating a Set produces a List, and one can convert a 
List into a Set fairly easily.

Sets and Hashes are quite similar, but in other ways different. The keys 
of a Hash are a Set of type String. In addition to the String 
constraint, each element of the set has an additional scalar value 
associated with it. Hashes can be multidimensioned. I have no idea what 
a multidimensional Set is. It may be possible to represent Sets as 
lightweight Hashes if the "Strings for keys" constraint is lifted or 
altered, but I see several advantages to Sets being distinct, for 
reasons I'll outline below.

So I propose making Sets a first class data type right up there with 
Arrays, Hashes, and Scalars. For the purposes of this posting, I will 
assume that they get a sigil of #. (to get a comment, you need 
whitespace after the #). I harbor no expectations that it will stay as 
this, but I needed something, and didn't feel like remapping my keyboard 
at the moment. Interestingly, on US keyboards, @#$% is shift-2345.

With that, we can now make existing operators do nifty things:
#a = #b + #c;# Union (Junctive $b or $c)
#a = #b - #c;# Difference( $b and not $c)
#a = #b * #c;# Intersection  ( $b and $c)
#a == #b;# Do sets contain the same values?
#a <  #b;# Is #a a subset of #b? likewise >, <=, >=
$a ~~ #b;# Membership
#a += $b;# Add value to set
#a = @b; # Create a set from an array/list
#a = (1,2,3);
$ref = #{1..10}; # an anonymous Set reference
@a = #b; # One way to iterate the members.
It's probably best to define binary | and & as "Set Creation with 
Union/Intersection", so we have:

#a = 1|3|7;
#a + @b == #a | @b;
We also add some methods here and there:
@a = #b.values;
#b = @a.as_set;
$a = #b.elems;
my str #a = %b.keys;
I also envision "virtual sets", which cannot be iterated, but can be 
tested for membership against. These would be defined by a closure or 
coderef.

#natural_numbers = { $^a == int($^a) && $^a > 0 };
#primes = &is_prime;
Set operations with virtual sets should be able to define new closures 
based on the former ones:

#a = #b + #c;  ==>  #a = {$^a ~~ #b || $^a ~~ #c};
#a = #b * #c;  ==>  #a = {$^a ~~ #b && $^a ~~ #c};
#a = #b - #c;  ==>  #a = {$^a ~~ #b && $^a !~ #c};
#a = #b + 3;   ==>  #a = {$^a == 3  || $^a ~~ #b};
So now, some 

Re: Fun with junctions (was Sets vs Junctions)

2005-02-12 Thread Rod Adams
Patrick R. Michaud wrote:
On Sat, Feb 12, 2005 at 03:49:02AM -0600, Jonathan Scott Duff wrote:
 

On Sat, Feb 12, 2005 at 01:03:26AM -0600, Rod Adams wrote:
   

I also find the following incredibly disturbing:
 

perl6 -e "$x = 'cat'|'dog'; say $x;"
   

dog
cat
 

Would that happen though?  What's the signature of C? I think
it's something like 
	multi sub *say ($stream = $*OUT: *$data) { ... }
so autothreading wouldn't happen anyway as S9 says the slurpy array/hash
aren't autothreaded.  
   

I reread S09, and I believe "autothreading" is the wrong term for the 
iteration that a junction incurs (Even though it appears in the section 
immediately after Junctions. Autothreading is  something far weirder, 
dealing with partial dimensional slices, I believe. And in that case, it 
makes sense to turn off autothreading for slurpys, since in flattening, 
you get rid of the messy dimensions. Therefore I suspect that the above 
is wrong, and the behavior of C is still to duplicate.

-- Rod Adams


Re: Fun with junctions (was Sets vs Junctions)

2005-02-12 Thread Rod Adams
Patrick R. Michaud wrote:
On Sat, Feb 12, 2005 at 12:41:19AM -0600, Rod Adams wrote:
 

Of course we'll always have C. But this is Perl, and I want YAWTDI.
After all, another way to test membership was just added, whereas before 
you pretty much just had C.
   

...another way to test membership was added...?
 

$x == any(@y);
My issue is less that lists and sets are radically different. It is much 
more a matter of Junctions and Scalars are radically different. Getting 
me to accept that a Scalar holds several different values at once is a 
hard sell. Especially when you consider duplicated side effects.
   

Since Scalars can be objects that are fairly complex aggregations
that simultaneously hold (or appear to hold) multiple different 
values at once, this doesn't seem like a strong argument.
 

But, to extract those alternative values from an object, you do 
something special to it, like call a method. Whenever you evaluate the 
object as a scalar, you get a single value back. Quite probably a 
reference to something much more elaborate, but a single value none the 
less. When you do a C, C is only called once.


And what happens if you attempt to evaluate a junction in a non-boolean 
context?
   

I dunno, which context are you concerned about?
  $a = any(2,3,4);
  $b = ? $a; # boolean context, $b == true
  $n = $a + 3;   # numeric context, $n == any(5,6,7)
  $s = $a ~ 'x'; # string context, $s == any('2s', '3s', '4s')
  @l = ($a); # list context, @l == (any(2,3,4))
 

It was basically a reiteration of my "iterated  side effect" argument, 
which gets worse if you do:

@l = (any(1,2,3),any(4,5,6),any(7,8,9),any(10,11,12),any(13,14,15));
say @l.join(' ');
I believe this generates 243 lines of text. IMO, this is not desirable. 
However, if the majority of people out there are fine with this 
behavior, I'll let it rest.

I also have not seen any good way to avoid the situation. It's now been 
established that one can do a C<.isa("Junction")> to determine that what 
we have is, indeed, a junction. However, once that happens, your options 
are basically to either live with it, or throw an exception. If you're 
given 'cat'|'dog', there's no way to extract 'cat' and or 'dog', unless 
you happened to be expecting 'cat' and 'dog', and test for them explicitly.

For clarification, is the type of 3|'four' == Junction|int|str?
And I've yet to receive a good answer for what C<3/any(0,1)> does to $!.
-- Rod Adams


Re: Fun with junctions (was Sets vs Junctions)

2005-02-12 Thread Rod Adams
Patrick R. Michaud wrote:
On Sat, Feb 12, 2005 at 01:18:53PM -0600, Rod Adams wrote:
 

My issue is less that lists and sets are radically different. It is much
more a matter of Junctions and Scalars are radically different. Getting
me to accept that a Scalar holds several different values at once is a
hard sell. Especially when you consider duplicated side effects.
   

Since Scalars can be objects that are fairly complex aggregations
that simultaneously hold (or appear to hold) multiple different 
values at once, this doesn't seem like a strong argument.
 

But, to extract those alternative values from an object, you do 
something special to it, like call a method. Whenever you evaluate the 
object as a scalar, you get a single value back. Quite probably a 
reference to something much more elaborate, but a single value none the 
less. When you do a C, C is only called once.
   

s/object/Junction/g above doesn't give me much grief.  Extracting
values from a Junction is also done by calling methods or functions.
 

None of which has been mentioned or defined, so I was forced to assume 
they didn't exist.

Of course, if we go this route, we are now saying that the return type 
signature of a sub is defined by an instance of class Junction.

And what happens if you attempt to evaluate a junction in a non-boolean 
context?
   

I dunno, which context are you concerned about?
[...]
 

It was basically a reiteration of my "iterated  side effect" argument, 
which gets worse if you do:

@l = (any(1,2,3),any(4,5,6),any(7,8,9),any(10,11,12),any(13,14,15));
say @l.join(' ');
   

I'm not so sure it gets "worse" here -- @l.join(' ') gets evaluated
first, and C is called only once because none of its parameters
are a junction.  In this case C is going to return a junction
of strings.  Similarly, as Scott Duff pointed out, C will be 
called only once, since the arguments to C are passed as part of a
slurpy array and as such do not autothread.  (No, I'm not entirely
sure what would be output as a result.  However, whatever it is,
it should all be on one line, not 243 lines.)
 

As I stated in a different message, my latest, fairly careful, 
interpretation of S09 rendered that autothreading and junctions were not 
directly related topics, even if I wrongly implied they were several 
posts ago. Thus the reference that slurpy lists cancel autothreading is 
not relevant to this issue. But if it makes the rest of the discussion 
go smoother, assume I've overwritten C with a non-slurpy version 
that otherwise does the same thing.

I would still think that the above would print 243 times. Consider it 
this way: P5's C<"print"> returns true upon success. Thus, C would 
could also be considered a boolean function for "Is this printable with 
a linefeed after it?". So I could then write:

@l = (any(1,2,3),any(4,5,6),any(7,8,9),any(10,11,12),any(13,14,15));
$x = say @l.join(' '));
Given the rest of Junction logic defined thus far, I would expect $x be 
a junction of 243 true/false values.


I also have not seen any good way to avoid the situation. It's now been 
established that one can do a C<.isa("Junction")> to determine that what 
we have is, indeed, a junction. However, once that happens, your options 
are basically to either live with it, or throw an exception. If you're 
given 'cat'|'dog', there's no way to extract 'cat' and or 'dog', unless 
you happened to be expecting 'cat' and 'dog', and test for them explicitly.
   

Umm, what's wrong with...?
  $l = 'cat'|'dog'|'mouse';
  @extract = $l.values(); # ('cat', 'dog', 'mouse')
 

The fact that it didn't exist until now.
Does this mean we can do:
@l = (any(qw/a b c d/) eq any(qw/c d e f/)).values();
and get @l == ('c','d')?

For clarification, is the type of 3|'four' == Junction|int|str?
   

I would guess the type of 3|'four' to be int|str, which is also a
Junction, but don't hold me to that.
 

But if you go with the Junction is a Class argument from above, I would 
expect the type would have to be Junction, and then one could query the 
Junction object as to what types it can mimic.
Of course, we could have Junction do some magic, and have each instance 
create an anonymous subclass that is also ISA whatever types of values 
happen to be in it at the time.

Which seems fairly heavyweight for something so integrated into the 
language.


Will I be able to create variables that can hold ints, but _not_ 
junctions of ints? In other words, is:

my int $x = 3|4;
legal? How do I make it illegal, so as to protect myself from duplicated 
side effects which may be disastrous in application X? If the above is 
illegal, how do a declare a variable

Re: Fun with junctions (was Sets vs Junctions)

2005-02-11 Thread Rod Adams
reiterate my autothreading concerns above.
And in these, you still have to do something completely different to 
determine what the factors are.

Sometimes a short loop is a good thing.
btw, in my set notation, you get:
@bar * {is_factor($^a, $foo)}
-- Rod Adams


Re: Fun with junctions (was Sets vs Junctions)

2005-02-11 Thread Rod Adams
Patrick R. Michaud wrote:
Rod Adams wrote:
 

I would argue that this sort of relational comparison is of limited 
usefulness. 
   

Well, except junctions hold more information than the simple comparisons
I've given here.  For example, a junction can have a value like:
   $x = ($a & $b) ^ ($c & $d)
which is true only if $a and $b are true or $c and $d are true but not
both.
 

That's why I allowed for virtual sets, defined by a closure.
Invariably, the next question that will nearly always be 
asked is "_Which_ values worked / didn't work?". 
   

If you're wanting to know *which* values worked, we still have C --
we don't need a special set notation for it, or to worry about junctions.
 

Of course we'll always have C. But this is Perl, and I want YAWTDI.
After all, another way to test membership was just added, whereas before 
you pretty much just had C.

and((2,3,4) ?<= 3)
btw, I like and()/or() over all()/any() because it makes it very clear 
we are establishing a boolean context.
   

To me the fact that we're using <= establishes that we're interested
in a boolean result; I don't need "and/or" to indicate that.  Using
"and" to mean "all" doesn't quite work for me, as I somehow think of
"and" as a two-argument operation.
 

That's a minor quibble, and I could go either way.
[intersection]
#foo * #bar   # and we even know which ones!
[containment]
#foo <= #bar
[non-intersection]
!(#foo * #bar)
   

Somehow overloading C<*> to mean "intersection" just doesn't work for
me here.  I'd have to think about it.
 

I saw a reference to a flavor of Pascal that used it that way. C 
might be more in line with the math notation for it, but somehow I doubt 
that would make you feel better.

Ultimately I don't think I agree with the notion that sets and lists
are so different, or that sets deserve/require their own sigil.
My issue is less that lists and sets are radically different. It is much 
more a matter of Junctions and Scalars are radically different. Getting 
me to accept that a Scalar holds several different values at once is a 
hard sell. Especially when you consider duplicated side effects.

And what happens if you attempt to evaluate a junction in a non-boolean 
context?

-- Rod Adams


Re: Fun with junctions (was Sets vs Junctions)

2005-02-11 Thread Rod Adams
Damian Conway wrote:
Patrick R. Michaud wrote:
Ultimately I don't think I agree with the notion that sets and lists
are so different, or that sets deserve/require their own sigil.  

Sets shouldn't have a sigil anyway, whether they're qualitatively 
different from lists or not. A set is a *value* (like an integer, or a 
string, or a list). A set is not a *container* (like an scalar or an 
array). And only containers get sigils in Perl.
Yet you're wanting to store something which holds different values (a 
junction) in a scalar field. I could see holding an enumerated set in an 
array, without any trouble at all. But junctions can be more than an 
enumeration of elements. To steal Patrick's example from before:

  $x = ($a & $b) ^ ($c & $d)
Which cannot be held in an array.
So my argument here is that none of the existing containers are suitable 
for holding a set/junction.

Scalars are meant to hold a single value. Junctions can hold several.
Arrays can hold many different values, but cannot store the 
interrelationship between then, as in the example above.
Hashes suffer the same problems as Arrays.

So my proposal was to create a new container, Sets, to store them in. I 
included the ability to store enumerated values, as well as create more 
complex logic via closures.

I was also attempting to add a bit of sanity to the semantics, by 
rephrasing things into something the average programmer would be able to 
parse. Given the numerous corrections to how one junction or another was 
parsed, I concluded that the exact semantics were becoming too subtle.

I also find the following incredibly disturbing:
>perl6 -e "$x = 'cat'|'dog'; say $x;"
dog
cat
Getting iterated executions of a statement without explicitly iterating 
it bothers me greatly. I work heavily in databases, where updating or 
inserting twice with one call can be fatal to data consistency.

So, if we are not having Sets, how exactly does one tell if what they 
are holding is a single value scalar, or a multi-value junction?

Can a junction hold values of completely different types, or just 
different values of the same type?

If evaluation of one value of a junction causes an error, is $! now a 
junction as well?

-- Rod Adams


Re: Fun with junctions (was Sets vs Junctions)

2005-02-12 Thread Rod Adams
Damian Conway wrote:
Rod Adams wrote:
I also find the following incredibly disturbing:
 >perl6 -e "$x = 'cat'|'dog'; say $x;"
dog
cat

That would be disturbing if that's what happened.
C is just a shorthand for C.
So saying a junction is the same as printing it, which is a run-time 
error.
So we have a restriction that Junctions cannot be outputted. What 
qualifies as output? Clearly C and its derivatives are output. 
What about a DBI call?  Hmm. I guess it does ultimately resolve into a 
socket write, so it would be trapped there.

However, what if what you're calling a non-Perl Parrot based function? 
Do we disable junctions from playing with non-PurePerl functions? Or do 
we autothread over them? How do we tell if a non-Perl function outputs 
to determine if we should be able to autothread into them or not?

Out of curiosity, was the "Junctions can't be outputted" error 
documented somewhere prior to now?

-- Rod Adams


Containers vs Objects.

2005-02-15 Thread Rod Adams
In my recent unsuccessful attempt to convert junctions into sets with their 
own container, perhaps the strongest argument against could be paraphrased 
as follows:

Everything about junctions or sets can be represented fully as an object, 
and objects are nicely stored in scalars, because it's simply one instance 
of a given class, in this case C.

My question comes down to: so what makes Arrays and Hashes so special? As 
many pure-OO languages demonstrate, both can be fully represented as an 
object, and objects belong in Scalars. The obvious statement I expect to 
here is "Perl's always had Arrays and Hashes". While I'm not sure if they 
were there for Perl 1.0 (I started w/ Perl 4.xx), I do know that they 
certainly predate P5's objects and references. Therefore, there was no 
other way to create an array or hash. That is no longer the case.

In P6, we've even gone so far as to say that you can access an element in 
an array ref with C<$ref[1]>. I'm fairly sure you can call all the methods 
of the Array class on the $ref, letting you do C<$ref.pop> and all the 
other fun things we do with arrays. Similar things hold for hashes.

So I'm interested in hearing what pushes Arrays and Hashes over the edge 
for needing their own container and sigil, whereas Junctions/Sets do not.

-- Rod Adams


Re: Fun with junctions (was Sets vs Junctions)

2005-02-15 Thread Rod Adams
Damian Conway wrote:
>Rod Adams wrote:
>
>> However, what if what you're calling a non-Perl Parrot based function?
>> Do we disable junctions from playing with non-PurePerl functions? Or do
>> we autothread over them? How do we tell if a non-Perl function outputs
>> to determine if we should be able to autothread into them or not?
>
>The non-outputting happens at the output operation, which is *always* in
>Parrot (at some level) and presumably is dealt with there.
Certainly all Perl code is Parrot code, at some level. However, I think 
this is more Patrick's problem than Dan's, and that Patrick is going to 
need some guideince from

I see it this way:
When perl sees a function call, and one of the arguments is a junction, 
there are three basic options:
1) If the junction is wrapped up in some larger container, like a slurpy 
list, pass it on as is.
2) If the function in question is an "outputing" one, throw an exception.
3) autothread over the function.

Consider the following:
$x = 3|4;
$y = fun($x);
sub fun ($x) {
 warn "enter: fun($x)\n" if $DEBUG;
 $x + 1;
}
Which option from above is in effect? I do not think I left any room for 
the junction to be enclosed in a larger container, so option #1 is out. 
That leaves #2 and #3.

If we autothread, the C only gets a regular scalar, and is happy, so 
we could get the dreaded repeated outputs.
If we throw and exception, then we have the case that when debugging is 
turned off (normal case), there is no output at all, and we now have a very 
confused library user, wondering why this simple math function is 
complaining about outputting a junction.

So is there a runtime internal flag, saying "I'm in the middle of 
autothreading a junction, if I happen across anything wanting to generate 
output, throw an exception."? That would certainly solve the pure Perl 
problem. But it starts to break down at the Parrot level.

Now consider the case that above fun() was written in Python, and imported 
into the perl-space. Constrast that to the CPAN author who refactors a 
perceived slow part of their module into PIR or even into C, and binding it 
into Parrot via neo-XS. (I don't follow p6i enough to remember what they 
call it. Certainly it's better than "neo-XS").

How does the "runtime flag" work in these cases? Does Parrot now have to 
mark all the subs that _might_ perform some type of output as such, 
regardless of where that sub came from?
If so, has Dan signed off on this?
If not, how does Patrick resolve whether to autothread or raise exception?

-- Rod Adams





Re: Containers vs Objects.

2005-02-15 Thread Rod Adams
At 01:04 PM 2/15/2005 -0800, chromatic wrote:
On Tue, 2005-02-15 at 14:26 -0600, Rod Adams wrote:
> So I'm interested in hearing what pushes Arrays and Hashes over the edge
> for needing their own container and sigil, whereas Junctions/Sets do not.
Perl isn't a "pure" object-oriented language.
No argument there.
Which is why I was interested effectively the argument that "Junctions/Sets 
are Objects, and don't need their own container/sigil" was considered so 
compelling.

-- Rod Adams



Re: Fun with junctions (was Sets vs Junctions)

2005-02-15 Thread Rod Adams
Larry Wall wrote:
Or perhaps
the problem isn't returning junctions per se, but storing them into
a variable that the user is thinking of as a simple scalar value.
 

That was the largest, perhaps only, reason I made my "Sets vs Junctions" 
post.

Although my solution to the issue was different from yours in almost 
every respect. You put limits on unsuspectedly storing a junction in a 
scalar. I made a new place to put them.

-- Rod Adams


Re: Containers vs Objects.

2005-02-15 Thread Rod Adams
chromatic wrote:
So I'm interested in hearing what pushes Arrays and Hashes over the edge 
for needing their own container and sigil, whereas Junctions/Sets do not.
   

Perl isn't a "pure" object-oriented language.
 

Rephrasing my question:
What characteristics would _any_ new structure or class have to have to 
merit becoming a first class container with it's own sigil, rather than 
being just another class?

Or is Perl close enough to "pure" object-oriented these days, where only 
grandfathered classes make the cut?

As a separate question, is there a relatively easy way to create a 
user-defined class with it's own sigil? (w/o having to modify half the 
parse rules).

-- Rod Adams


Re: Fun with junctions (was Sets vs Junctions)

2005-02-15 Thread Rod Adams
Patrick R. Michaud wrote:
On Tue, Feb 15, 2005 at 03:07:53PM -0600, Rod Adams wrote:
 

I see it this way:
When perl sees a function call, and one of the arguments is a junction, 
there are three basic options:
1) If the junction is wrapped up in some larger container, like a slurpy 
list, pass it on as is.
2) If the function in question is an "outputing" one, throw an exception.
3) autothread over the function.

Consider the following:
$x = 3|4;
$y = fun($x);
sub fun ($x) {
warn "enter: fun($x)\n" if $DEBUG;
$x + 1;
}
Which option from above is in effect? I do not think I left any room for 
the junction to be enclosed in a larger container, so option #1 is out. 
That leaves #2 and #3.
If we autothread, the C only gets a regular scalar, and is happy, so 
we could get the dreaded repeated outputs.
   

As you've written things above, C is autothreaded (your option #3), 
and we'll see two C output lines if $DEBUG is set.  Whether or 
not the repeated outputs are "dreaded" is a matter of perspective.  
Since the caller has chosen to pass a junction to C, the caller 
shouldn't be overtly surprised when C is autothreaded, or that it 
generates multiple output lines.  In fact, I'd be concerned if it didn't.
 

The case of Damian's response in a prior message:
Rod Adams wrote:
I also find the following incredibly disturbing:
 >perl6 -e "$x = 'cat'|'dog'; say $x;"
dog
cat

That would be disturbing if that's what happened.
C is just a shorthand for C.
So saying a junction is the same as printing it, which is a run-time 
error.
Could easily be achieved with a single layer of encapsulation?
perl6 -e "$x = 'cat'|'dog'; say1 $x; sub say1 ($x) {say $x}"
Or is the consensus that that's somehow not disturbing, and direct calls 
are disturbing.

If what you're saying is true, then feeding a junction into DBI for a 
"insert" statement, since the output proper is encapsulated, would 
create multiple new records in the database? I'm back to being very 
disturbed.


If so, has Dan signed off on this?
If not, how does Patrick resolve whether to autothread or raise exception?
   

Well, the ultimate answer is that both Dan and Patrick (and others)
will negotiate the exact interface when we get to that point, and 
that we don't seem to be too concerned about it at the moment.
(It could just be that we're both burying our heads in the sand 
hoping it'll be magically "solved" by the other.  :-)
 

Actually, using the semantics you've outlined above, there is no 
implementation problem.
However, I disagree that those semantics are desirable.

OTOH, what happens with...?
   sub nofun($x is rw) {
   $x += 2;
   }
   $y = 3 | 4;
   nofun($y);
Do we need to change the semantics of what happens with autothreading to:
method autothread (&func, $junction) {
 my $result;
 my $value;
 for $junction.values -> $value {
   my $temp = $value;
   func($temp);
   $result |= $temp;
 }
$result;
}
-- Rod Adams



Junction Values

2005-02-15 Thread Rod Adams
Okay, so we've established that:
$x = any(3,4,5);
@l = $x.values.sort;
Leaves us with @l == (3,4,5), and that makes a fair amount of sense.
What do the following evaluate to:
@l1 = all(3,4,5).values.sort;
@l2 = one(3,4,5).values.sort;
@l3 = none(3,4,5).values.sort;
@l4 = any(all(1,2),all(3,4)).values.sort;
If C<.values> doesn't it cut it for these cases, what other forms of 
introspection are we going to allow on junctions, to determine what they 
are?


On a slightly different topic, do the following equivalences work:
any($a, $a) == $a
any($a,$a,$b) == any($a,$b)
any(any($a,$b),any($c,$d)) == any($a,$b,$c,$d)
all($a, $a) == $a
all($a,$a,$b) == all($a,$b)
all(all($a,$b),any($c,$d)) == all($a,$b,$c,$d)
none($a, $a) == undef
none($a,$a,$b) == none($a,$b)
none(none($a,$b),none($c,$d)) == none($a,$b,$c,$d)
one($a, $a) == false
one($a,$a,$b) == ($a == $b ?? undef ::  $b)

-- Rod Adams


Re: Junction Values

2005-02-15 Thread Rod Adams
Damian Conway wrote:
.values tells you what raw values are inside the junction. The other 
kind of introspection that's desirable is: "what raw values can 
*match* this junction". There would probably be a .states method for 
that.

To see the difference between the two, consider:
my $ideal_partner = all( any(Âtall dark richÂ),
any(Ârich old frailÂ),
any(ÂAustralian richÂ),
);
$ideal_partner.values would return the three distinct values in the 
junction:

( any(Âtall dark richÂ),
any(Ârich old frailÂ),
any(ÂAustralian richÂ),
);
But $ideal_partner.states would return only those non-junctive values 
that (smart-)match the junction. Namely, "rich".
One would need a method of determining whether the C<.values> are in an 
any/all/none/one relationship. Trivial, but necessary. That and 
C<.values> are likely enough introspection. Leave the C<.state> for CPAN 
to solve.


On a slightly different topic, do the following equivalences work:

(I will assume in all my answers that $a, $b, $c, $d have different 
values, except where it doesn't matter either way).

all($a,$a,$b) == all($a,$b)

False. The autothreading makes that:
all( $a==$a, $a==$b, $b==$b, $b==$a)
and they're not (in general) all true.
I knew I was typing this all wrong. Whipping out math symbols, replace 
the == with â, or identical to.
In other words, I was not asking how C< if all($a,$a,$b) == all($a,$b) 
{...} > evaluated, but instead if

if all($a,$a,$b) {...}
if all($a,$b) {...}
would both evaluate the same.
And I was making no assumptions about the values of $a .. $d.

all(all($a,$b),any($c,$d)) == all($a,$b,$c,$d)
False. Because all($a,$b) != all($a,$b,$c,$d)
Should have been
all(all($a,$b), all($c,$d)) â all($a,$b,$c,$d)
Sorry for any confusion. It's just a real pain to type chars that are 
not bound on your keyboard.

As for the undef's, I didn't know what else to call the empty junctive.
-- Rod Adams



Re: Junction Values

2005-02-15 Thread Rod Adams
Patrick R. Michaud wrote:
none(none($a,$b),none($c,$d)) == none($a,$b,$c,$d)
 

True.
   

H...
  -> none(none($a,$b) == none($a,$b,$c,$d),
  none($c,$d) == none($a,$b,$c,$d))
  -> none(none($a == none($a,$b,$c,$d),
   $b == none($a,$b,$c,$d)),
  none($c == none($a,$b,$c,$d),
   $d == none($a,$b,$c,$d)))
  -> none(none(none($a==$a, $a==$b, $a==$c, $a==$d),
   none($b==$a, $b==$b, $b==$c, $b==$d)),
  none(none($c==$a, $c==$b, $c==$c, $c==$d),
   none($d==$a, $d==$b, $d==$c, $d==$d)))
  -> none(none(none(1, 0, 0, 0),
   none(0, 1, 0, 0)),
  none(none(0, 0, 1, 0),
   none(0, 0, 0, 1)))
  -> none(none(0, 0), none(0, 0))
  -> none(1,1)
  -> false
Ummm, what am I missing?  To state it another way... we can
show that none($a,$b) == none($a, $b, $c, $d) is true, so
 none( none($a,$b), none($c,$d) ) == none($a, $b, $c, $d)
is equivalent to
 none( none($a,$b) == none($a, $b, $c, $d),
   none($c,$d) == none($a, $b, $c, $d))
which is none(1, 1), or false.  Did I autothread wrongly here?
 

No, upon closer looking, you're right that it should both evaluate 
false, and that they are not equivalent in what I meant to be asking.

none(none($a,$b),none($c,$d)) ? all(any($a,$b),any($c,$d))
Should work, though. Not that it helps simplify matters at all.
In essence, what I'm doing is attempting to create a set of rules 
whereby one can simplify a junction, by removing the nestedness of it, 
or removing terms outright. In the process, I'm making sure that I 
understand what they mean.

-- Rod Adams


Re: Containers vs Objects.

2005-02-15 Thread Rod Adams
Larry Wall wrote:
 But as far as English is concerned, sets are just
objects that have a singular outside and a (potentially) plural inside,
much like almost any other object.  At least, that's how concrete
sets work. 
 

Hmm. I would argue that most of the time, when English Speakers use sets 
quite commonly in their speak, and often refer to them as lists (e.g.  
Shopping Lists). In fact, when expressing any list, we go out of our way 
to explicitly give them an order or ranking. Not to mention people do 
think in terms of sets. Back to the shopping list, you have the set of 
things on your list (#list), and the set of things in your cart (#cart), 
as well as the things in the store (#store).
What can you cross off your list? #list x #cart
What's left to buy? #list - #cart
What's not available? #list - #store
What did you buy that wasn't asked for? #cart - #list

Add to this the not infrequent use of the phrase "You listed ___ twice." 
in response to hearing a list, thus implying something more set-ish 
about it than an array gets. Or the frequency with which one gives six 
or more responses to the question "What are your top 5 ?"

I have little ability to translate hashes into English, beyond "How many 
cans of ___ are in the cupboard?"

So in terms of frequency of use in the English Language, I'd rank things 
in the following order:
1) Scalars
2) Sets
3) Arrays
4) Hashes

As for Perl Speakers, I would argue that a high percentage of the time 
someone says C< for @list {...} >, they really don't care for which 
order the elements are executed in, just that they are. Creating a hash 
where all the values are 1, just to get the set like features of the 
keys, is a fairly common Perl idiom.

As Computer Science Speakers, Sets are a very fundamental data 
structure. Okay, not as fundamental as Arrays. But easily more so than 
Hashes.

Programmers tend not to speak in terms of Sets very often, because their 
languages don't support them.

Junctions, on the other hand, almost never come up in English, except as 
a Set. Where do you see sentences which have a word which means two 
other words _at_once_, and the listener is supposed to understand all of 
the meanings? Double entendres come close, but there are two main 
drawbacks: 1) only a limited set of words can be used in this case, and 
each of them has a very limited number of values it can possess. Not any 
noun taking on the value of any two or more other nouns at once. 2) it 
is almost never in question that only one meaning was meant, and the 
other meaning was merely a cover, to prevent a faux-pas.

-- Rod Adams


Re: Junction Values

2005-02-16 Thread Rod Adams
Patrick R. Michaud wrote:
On Wed, Feb 16, 2005 at 06:04:37PM +, Nigel Sandever wrote:
If the hyper operator returned one boolean result for each 
comparison it made, and if a list of boolean values in a 
boolean context collapsed to a count of the trues/1s it contained, 
I think those would work. 
   

Part of the problem is that we don't have a "list of boolean values"
that is somehow distinguishable from "list of values".  (And a list
evaluated in boolean context is true if the list is non-empty.)
If we create a "list of boolean values" type, it effectively becomes
a junction.  :-)
What if we instead redefine any/all/one/none to be functions (and/or 
list methods) that take a list, evaluates each element in boolean 
context, and returns boolean?

Therefore, Nigels's examples become:
   if any( $x »==« @list) { ... }
   if none($x »==« @list) { ... }
   if all( $x »==« @list) { ... }
   if one( $x »==« @list) { ... }
Then case that I see happening most often will then be:
   if any($x »==« (1,2,10,100,200,1000,2000)) { ... }
I'll also throw in the argue that anything much more complex than this 
definitely falls into the category of "edge case", and is of dubious 
utility, and IMHO, a lot of danger.

It occurred to me that junctions felt a lot like typeglobs. Very 
powerful thing, that little *. But also something that experienced 
programmers tell inexperienced ones something like "Don't mess with them 
unless you really understand them." Then throw in that most programmers 
use a heavy dose of lexicals, which aren't typeglobable. In the end, you 
are left with only one useful idiom left:
   *NewFunc = sub {...};
Which will usually appears inside an AUTOLOAD.
(yes, I'm sure that Damian and some others on this list can create 
exceptionally cool use of typeglobs, in ways that would warp our minds, 
but I'm talking overall utility).

How does this relate to junctions? All I think anyone ever *asked* for 
out of a junction was an easier way to write:

   if ($x==$a or $x==$b or $x==$c or $x==$d) { ... }
The rest of the invention feels like "Magic", and is something the 
experienced will tell the inexperienced not to mess with until they 
really understand the consequences of using them. And even then, few of 
the experienced will make more use of it than the simple case.

-- Rod Adams



Re: Junction Values

2005-02-16 Thread Rod Adams
Larry Wall wrote:
That, and we'd like a novice to be able to write
   given $x {
when 1 | 2 | 3 {...}
when 4 | 5 | 6 {...}
   }
Or just change C to accept a list of things to compare against, 
followed by a coderef.

-- Rod Adams


Re: Junction Values

2005-02-17 Thread Rod Adams
Brent 'Dax' Royal-Gordon wrote:
Rod Adams <[EMAIL PROTECTED]> wrote:
 

Larry Wall wrote:
   

That, and we'd like a novice to be able to write
  given $x {
 when 1 | 2 | 3 {...}
 when 4 | 5 | 6 {...}
  }
Or just change C to accept a list of things to compare against,
followed by a coderef.
   

And change if, unless, while and until to do the same thing.  
 

Actually, upon further investigation, I believe we get this all of this 
without junctions.

According to S03, "The scalar comma |,| now constructs a list reference 
of its operands."
Then S04 mentions that C< $scalar ~~ @array > is true if $scalar is in 
@array.
Since C< given ... when > uses smart matching for it's evaluation, one 
should be able to write the above as:

given $x {
 when 1, 2, 3 {...} # at worst, this is:  when (1,2,3) {...}
 when 4, 5, 6 {...}
}
The simple if is:
if $x ~~ (1,2,3,4) {...} # parens needed here since , is lower than ~~ 
in precedence.

Same for unless/while/until. And all of this from the entirely useful C< 
~~ >. The S04 code describing @Array ~~ $Scalar (for Num/Str) uses 
junctions, but I'd argue a better implementation would be a short 
circuiting C< for > loop, even if junctions exist. It's just plain 
faster that way.

So what I see now for utility of junctions is thus:
- Common cases which C< ~~ > appears to handle for us suitably well.
- Edge cases which, IMHO, do not merit the huffman level of several 
single character operators. All of which can be accomplished without the 
use of junctions, though not as gracefully.

I see no need for junctions in core.
And lose the ability to say:
   when none(1, 2, 3) { ... }
   when 1 ^ 2 ^ 3  { ... }# More useful with classes, regexen, etc.
   when 1 & 2 & 3 { ... }# Likewise
All so that a newbie doesn't confuzzle himself.
 

You can always write your switch statements the Perl 5 way.
Or you could write:
   when ({$^a ~~ /1/  && $^a ~~ /2/  && $^a ~~/3/}) {...}
And the like. Look up what C< $scalar ~~ $coderef > does if you're not 
convinced.
(side question: what is the proper syntax for using a closure as the 
evaluation expression in a C< when > statement?)

hmm, since the $_ is set, you could likely get away with:
   when ({/1/  && /2/  && /3/}) {...}
in the case of RE's.
Personally, I'd rather have a chain saw than a nail trimmer, even if
I'm less likely to hurt myself with the nail trimmer.  And it looks
like we'll have a warning or stricture to keep newbies from chopping
their legs off anyway.
 

I can understand your sentiments here, but I'd be a lot more sympathetic 
to your cause if the alternative ways of accomplishing these things were 
actually difficult. I think it's been demonstrated that any of the 
junction evaluations could be done with a call to C< grep >, with 
numerous other ways to perform them as well.

-- Rod Adams


Re: Junction Values

2005-02-17 Thread Rod Adams
Larry Wall wrote:
On Thu, Feb 17, 2005 at 02:18:55AM -0600, Rod Adams wrote:
: The simple if is:
: 
: if $x ~~ (1,2,3,4) {...} # parens needed here since , is lower than ~~ 
: in precedence.

That is asking if $x is a list containing 1,2,3,4.
 

Quoting S04:
   $_  $xType of Match ImpliedMatching Code
   ==  = ==
   Array   Array arrays are identical match if $_ »~~« $x
   Array   any(list) list intersectionmatch if any(@$_) ~~ any(list)
   Array   Rule  array grep   match if any(@$_) ~~ /$x/
   Array   Num   array contains numbermatch if any($_) == $x
   Array   Str   array contains stringmatch if any($_) eq $x
And since there are no tell tell *'s on these saying that they are _not_ 
reversible, I must assume they _are_.

In C< if $x ~~ (1,2,3,4) {...} >, if $x is type Num or Str, then I see 
no way of reconciling your statement above.

: Same for unless/while/until. And all of this from the entirely useful C< 
: ~~ >. The S04 code describing @Array ~~ $Scalar (for Num/Str) uses 
: junctions, but I'd argue a better implementation would be a short 
: circuiting C< for > loop, even if junctions exist. It's just plain 
: faster that way.

Junctions can short circuit when they feel like it, and might in some
cases do a better job of picking the evaluation order than a human.
 

I was afraid someone was going to say that. And I now must convert my 
reservations about junction autothreading from "very disturbing" to 
"you've got to be kidding".

According to Patrick, and since no one has corrected him, I will assume 
he is right,

perl6 -e "say1 'cat'|'dog'; sub say1 ($x) {say $x}"
Should output "cat\ndog\n" or "dog\ncat\n". Now, if we allow Junctions to short circuit, and since there is no fixed order of values in a junction, we could get any of "cat\ndog\n", "dog\ncat\n", "cat\n", or "dog\n". 
What's that get us? non-deterministic output! I could handle non-deterministic *order* of output, because by the simple fact that you were using a junction, you didn't care about order.

Non-deterministic output! how fun!
Not to mention it contradicts S09:
"... that routine is "autothreaded", meaning the routine will be called 
automatically as many times as necessary to process the individual scalar elements of the junction 
in parallel."
Now there is some wiggle room in there for short circuiting, but not very much.

: So what I see now for utility of junctions is thus:
: 
: - Common cases which C< ~~ > appears to handle for us suitably well.

Only if we make lists second-class citizens.  The need for junctions
first became evident when we found ourselves filling the ~~ tables
with various sorts of weird non-symmetries.
 

So what other semantic makes sense for:
Str ~~ Array
Num ~~ Array
which would better appeal to your sense of symmetry?
Besides, people were telling me that my Sets were not needed, because 
they could be rendered with Arrays and Hashes. I fail to see how 
junctions are that different.

: - Edge cases which, IMHO, do not merit the huffman level of several 
: single character operators. All of which can be accomplished without the 
: use of junctions, though not as gracefully.

Grace is important.  Even more important is mapping naturally to human
linguistic structures, to the extent that it can be done unambiguously.
 

In my experience, English tends not to superimpose several values on a 
given noun at once.

: I see no need for junctions in core.
I do, and I'm not likely to change my mind on this one.  Sorry.
 

I realized that fairly early on. The situation I'm in is that while I 
don't agree with all the design initiatives that come out here, it's 
been the case that the more I think about them, the more I like them. I 
always achieve at least a state of ambivalence or better about it.

With Junctions, it's been the case that at first I thought they were 
useful and cool, but the more I think about them, the more I dislike them.

I'll argue my case for a few more days, and if I haven't gotten anywhere 
by then, I'll likely give up.

-- Rod Adams


Re: Junction Values

2005-02-18 Thread Rod Adams
Brent 'Dax' Royal-Gordon wrote:
Rod Adams <[EMAIL PROTECTED]> wrote:
 

Larry Wall wrote:
   

Junctions can short circuit when they feel like it, and might in some
cases do a better job of picking the evaluation order than a human.
 

I was afraid someone was going to say that. And I now must convert my
reservations about junction autothreading from "very disturbing" to
"you've got to be kidding".
   

...
 

Not to mention it contradicts S09:
"... that routine is "autothreaded", meaning the routine will be called 
automatically as many times as necessary to process the individual scalar elements of the junction 
in parallel."
Now there is some wiggle room in there for short circuiting, but not very much.
   

The "wiggle room" is that the junction knows when it's being asked to
collapse into a Boolean, and can know if there's no possible way the
function it's running will have side effects.  (That's why we're
declaring ties now.  There may be cases where we can't know for sure
if there will be side effects or not--Halting Problem stuff--but we
can make sure the junction optimizer is conservative.  The Halting
Problem becomes a lot easier if you ask whether a program *might* halt
instead of whether it *will*.)
In general, it seems to simply be an amazingly bad idea to autothread
a function with side effects.  In fact, I'd recommend that we warn if
a side effect occurs during autothreading.
 

Besides, people were telling me that my Sets were not needed, because
they could be rendered with Arrays and Hashes. I fail to see how
junctions are that different.
   

Junctions are intended to be used mainly within conditionals and other
statements;
If the set of these "other statements" is limited, consider creating a 
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.

This way, you get all the happy functionality, at the cost of typing 
"use Junction;", and I get loads of protection against the evil side of 
autothreading. Doing Junctions this way also makes the them extensible. 
If someone figures out what a "not" junction is, they can add it in 
later. And people like me can't complain about what the module is doing 
to the language, because "all's fair if you predeclare" would be in effect.

I think junctions are important at the statement level because they
help make similar things look similar.  Consider these two statements:
  if($foo == $bar) { .. }
  if(grep { $foo ==  $_ } $bar, $baz) { ... }
What makes these two statements so fundamentally different from each
other that they should be expressed in ways that *look* so different?
 

You mean besides the shift in plurality? A shift in plurality in English 
forces you to modify a hefty portion of your sentence to accommodate it. 
At a minimum, you change your verb, in this case the C< == >.
Shifting plurality in programming languages also incurs changes to the 
code around it.

: - Edge cases which, IMHO, do not merit the huffman level of several
: single character operators. All of which can be accomplished without the
: use of junctions, though not as gracefully.
Grace is important.  Even more important is mapping naturally to human
linguistic structures, to the extent that it can be done unambiguously.
In my experience, English tends not to superimpose several values on a
given noun at once.
   

No, but nor does it have a concept quite like a variable. 

Which significantly weakens the "mapping naturally to human linguistic 
structures" argument, IMO.

Junctions are equivalent to the English sentence "Get eggs, bacon, and
toast from the store".  (In Perl, that'd be something like C<<
$store->get("eggs" & "bacon" & "toast") >>.) 
 

Or just have C< get() >  take a list, and it's:
$store->get(<>); # is that the latest use of <<>>?
It's just a bit of
orthogonality that allows you to give "eggs, bacon, and toast" a name
and use it later.
@shopping list = <>;
gives them a name you can use later, as well.
-- Rod Adams


Re: Junction Values

2005-02-18 Thread Rod Adams
Larry Wall wrote:
The need for junctions
first became evident when we found ourselves filling the ~~ tables
with various sorts of weird non-symmetries.
 

~~ can easily be called the "DWIM compare" operator. It even looks like 
you're waving your hands, asking for some strange voodoo to happen. It 
can also be thought of as "Here! take these two things, do something 
with them, and tell me how it went". So it's magic central. And magic is 
invariably a messy thing to implement.

And once the concept is out there, is makes sense to have practically 
every combination of types do _something_ useful if fed to ~~. Which 
makes it where ~~ is likely destined to be one of the most overloaded 
operators in the history of computing. So be it. It's amazingly useful. 
It also takes a monstrous amount of the Perl 6 DWIMery and puts it all 
in one place.

Not to mention, you've already defined P6 to be good at this 
multi-sub/method game, so take advantage of it. It's not like this table 
will be represented all in one function (at least I hope not)

-- Rod Adams


Re: Junction Values

2005-02-18 Thread Rod Adams
Luke Palmer wrote:
Rod Adams writes:
 

Junctions are intended to be used mainly within conditionals and other
statements;
 

If the set of these "other statements" is limited, consider creating a
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.
I'm trying to salvage what I can, since people seem to be rejecting 
everything I offer.

 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.
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?  
 

What on earth does C< for (2..sqrt(3|5)) {...}  > mean in the current 
state of junctions?

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.

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. 
 

You get into this probl

Re: Junction Values

2005-02-18 Thread Rod Adams
Jonathan Scott Duff wrote:
On Fri, Feb 18, 2005 at 12:42:31PM -0600, Rod Adams wrote:
 

No, but nor does it have a concept quite like a variable. 

 

Which significantly weakens the "mapping naturally to human linguistic 
structures" argument, IMO.
   

Why exactly?  It's just the variable-nature of variables that isn't
exactly expressed linguistically, otherwise variables are just nouns
really.
 

And nouns either refer to single item, or a group of items as a whole. 
Not one item that behaves like a chameleon.

When you say "The French", you are referring to the entire group of 
people that associate themselves with the country of France. Not all the 
people of France juxtaposed into one entity. If you want that, you say 
"A Frenchmen" or "One of the French", but even then you are referring to 
a single person, who happens to part of the group "The French". This 
last is a pure Set membership question. The same "The French" can be 
used as : "The French are invading!!". With a junction, you can build 
something that says "any group of people from France", "one person from 
France", "everyone from France", and even "not from France", but none of 
them embody the concept that we think of as "The French".

If you were to have an embodiment of "The French" (as I proposed way 
back in "Sets vs Junctions"), it is fairly easy to then create all of 
the above junctions. Via the introspection that Junctions are being 
defined with, it's possible to get that back out, but not smoothly.

So, linguistically, a noun is either a specific entity, or a group of 
things, taken as a whole.
As Damian so emphatically stated earlier in this long and twisting 
thread, a Junction is not a group of things, lopped together. It is one 
single thing, that has several different values at once. In addition, it 
also has a boolean function (any/all/one/none), declaring how all these 
values relate when evaluated. The closest linguistic parallel to this 
I've see is the double entendre, which doesn't even come close.

Sets and Junctions are two different things. They are related, but quite 
different, and should not be confused.

Junctions are equivalent to the English sentence "Get eggs, bacon, and
toast from the store".  (In Perl, that'd be something like C<<
$store->get("eggs" & "bacon" & "toast") >>.) 

Or just have C< get() >  take a list, and it's:
$store->get(<>); # is that the latest use of <<>>?
   

It's just a bit of
orthogonality that allows you to give "eggs, bacon, and toast" a name
and use it later.
shopping list = <>;
gives them a name you can use later, as well.
   

Except that you've introduced a definite ordering where one isn't
needed.
 

Yes, well, people don't get to use that argument on me after repeatedly 
saying that sets could be easily stored in arrays and/or hashes. I don't 
remember if you, personally said it, but it felt like a consensus vote 
from over here. One I don't really disagree with.

Not to mention the definite ordering only matters if you process it in a 
way that it does.

In attempts to better explain:
   $store->get("eggs" & "bacon" & "toast");
   $store->get(<>);
say two radically different things. The first statement says: "Go to the 
store and get Eggs. Go to the store and get Bacon. Go to the store and 
get Toast. Save the results of each trip separately, and then when 
someone asks how your trip (not trips) to the store went, you then see 
if all the results are the same."

The second statement says: "Go to the store once. You have the following 
shopping list: Eggs, Bacon, Toast. Was your trip successful?"

-- Rod Adams



Re: Junction Values

2005-02-18 Thread Rod Adams
Ashley Winters wrote:
On Fri, 18 Feb 2005 12:47:51 -0700, Luke Palmer <[EMAIL PROTECTED]> wrote:
 

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?
   

sqrt() won't die; it gets threaded and returns a Junction, I would
expect. It's the lack of an &*infix:<..>(Int, Junction) function which
causes death
In the context this question was posed, the proposal I was making, 
sqrt() would throw an exception. But that's likely not what this 
discussion is about.

In the terms of junctions as defined, I expect that it would stop at the 
lowest value of $x greater than or equal to 4. Unless we start allowing 
junctive lists as well as junctive scalars...

-- Rod Adams.




Re: Junction Values

2005-02-18 Thread Rod Adams
Craig DeForest wrote:
Hmmm... It seems that this way does lie madness -- there's a fundamental 
ambiguity between autothreading happening inside or outside the declared 
loop, and there's no "least surprising" way to implement it.  Certainly 
inside the loop is the easiest and most natural to implement, but that acts 
strange from an API standpoint.  Outside the loop works well from an API 
standpoint but introduces all sorts of weird cases that the implementation 
has to consider.  
 

I would think that my latest idea of turning off "autothreading" per se, and replacing it with an explicit "threading" call/operator, would solve this dilemma. The idea was specifically to have it where threading happened on function calls when a junction was surrounded by hyper operators. Otherwise, the junction is passed "as is". 

So we still get:
if $x == 3|4|5|6 {...}
would thread over infix:<==> without any funkiness, since we'll assume 
operators are well written, and can take junctions as parameters, same as:
if is_prime(3|4|5|6) {...}
Would pass the junction to is_prime, to do with as it pleases, including throwing an exception. However, 

if is_prime(»3|4|5|6«) {...}
would thread over is_prime, and collate the results outside of call.
These semantics also give us the ability to easily mix and match what we 
send to a function, so we can say:
if funky_test(all(@A), »any(@B)«) {...}
Basically I'm putting all the power of threading into the hands of the 
caller.
I will further argue that C< »junction« > should not short circuit. It should do the 
simple brute force "try all values" approach, since the side effects are likely 
desired. Operators, which should be able to accept junctions as parameters, are encouraged to 
short circuit, since there are no side effects possible for the evaluation of that operator. By 
the time the operator gets called, it should have all the parameters it needs, and there are no 
more side effects to be had.
As for C< .. >, I'd say that it should handle junctions being fed into it 
by throwing an exception.
-- Rod Adams



Re: Junction Values

2005-02-18 Thread Rod Adams
Brent 'Dax' Royal-Gordon wrote:
Rod Adams <[EMAIL PROTECTED]> wrote:
 

Luke Palmer wrote:
   

  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?
 

What on earth does C< for (2..sqrt(3|5)) {...}  > mean in the current
state of junctions?
   

In the current state of junctions, the autothreading is done at the
level of the call to do_prime, so $x is never a junction. 

Actually, if one writes is_prime to have slurpy array passing a la 
Perl5, as I wrote in a different post, $x most certainly is a junction 
at this point.

Although this does beg the question: If by default one can't assign a 
junction to a variable, does this apply only in cases with an assignment 
operator, or does it also happen on parameter passing?

I've just reread Larry's post about normally disallowing storage of 
junctions in a lvalue. He covers the point about declaring parameters 
that are junctional, and the parameters are otherwise non-junctional. 
What is not clear here is whether or not the S09 talk about if a 
junction is inside another container (like a slurpy array), if it gets 
caught or not. The array itself is not a junction, but one or more of 
it's elements might be. So do we have to walk the entire reference tree 
if we are given a complex data type, looking for junctions? This is not 
an option, think no further than lazy lists to see why. So the other 
option is to have a runtime check, and as soon as a memory store 
containing a junction is encountered, then throw an exception. Even if 
this happens well after the parameter passing step. Hmm. Messy, but 
possible.


Only under
your notion of junctions as just another object with no autothreading
until the operator level will $x ever be a junction.
 

For the record, I've withdrawn that proposal.
All I want now is for autothreading to be explicit.
But if it somehow *did* become a junction, I would imagine something
like this would happen:
  for (2 .. sqrt( 3 | 5 )) { ... }
  for (2 .. ( sqrt 3 | sqrt 5 )) { ... }
  for ( ( 2 .. sqrt 3 ) | ( 2 .. sqrt 5 ) ) { ... }
  for ( 2 .. sqrt 3 ) { ... } | for ( 2 .. sqrt 5 ) { ... }#notionally
However, it's clear that the last step doesn't make a whole lot of
sense, since C has no return value.  Maybe C would be
declared with a signature that didn't allow junctions at all.
 

Or is it the case that C< .. >  acts a bit like the old flip flop it 
used to be, and stop at the first true value it sees?
AFAIK, the concept of Junctional Lists has not been created yet, so what 
else would it return? A list of junctions? all of which are ($x|$x) or 
($x|undef)?

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:
   

I will readily admit that the behavior of junctions in a slurpy
subroutine call is suboptimal, and it might be a good idea to
reexamine it.  However, I will also point out that most newbie
programmers probably won't use the @_ behavior, and likely won't be
using slurpy parameters either, while more experienced programmers
will know better.
 

Except for the absolutely massive amount of Perl5 code out there that 
will be hastily translated by people who don't trust the Perl6 <-> Ponie 
interplay, and the flocks of Perl5 programmers coming over without 
learning all the new features of their upgraded language, you're 
probably right.

-- Rod Adams


Re: Junction Values

2005-02-18 Thread Rod Adams
Brent 'Dax' Royal-Gordon wrote:
Rod Adams <[EMAIL PROTECTED]> wrote:
 

   if $x == 3|4|5|6 {...}
would thread over infix:<==> without any funkiness, since we'll assume 
operators are well written, and can take junctions as parameters, same as:
   if is_prime(3|4|5|6) {...}
Would pass the junction to is_prime, to do with as it pleases, including 
throwing an exception. However,
   if is_prime(»3|4|5|6«) {...}
would thread over is_prime, and collate the results outside of call.
   

So basically you're proposing that, rather than do one implicit loop
that'll probably do what you want, the default should be to do an
unknown number of implicit loops in somebody else's code, and you have
to ask explicitly for the more sensible behavior.  Somehow this
doesn't strike me as an improvement.
 

What I'm asking for is to be in control of how often I get the possible 
side effects of calling a function. If I make a call to a DBI method to 
go insert a record, I want exactly 0 (on error) or 1 (on success) 
records inserted into my database, _unless_ I told it do otherwise. 
Since a junction is a single item, it should produce a single effect 
_unless_ I tell it to expand the values and act like several items at once.

Simply put, I want control over my side effects.
As for whether passing the junction as a junction or passing the 
junction via autothreading should be the default:

Junctions exists. I want to say "stay a junction" or "explode into 
pieces, go your separate ways, and then come back". In one case I'm 
doing nothing to the junction, in the other case I'm doing quite a bit. 
So it makes sense that the latter is something additional to the former.

Taking into account how common that particular action might be, I chose 
to propose a rather short modification to it, that still clearly said 
something special was going on here. One could say I'm just extending 
the hyper operator from "do this operator several times" to "do this 
expression several times".

"More sensible behavior" is entirely subject to the exact instance at 
hand. In the case of let's say C< == >, I want to feed it the raw, 
unexploded junction.
I well written C< == > should be able to apply all kinds of 
optimizations to the task at hand, and provide much more sensible results.
I expect calls with operators to be considerably more common than 
function calls w/ junctions.

So if I grant you your default of autothreading, we then get:
   if $x == »3|4|5« {...}
   given $x {
  when »3|4|5« {...}
   }
Which seemed far more suboptimal than the other way around, IMO.
These semantics also give us the ability to easily mix and match what we send 
to a function, so we can say:
   if funky_test(all(@A), »any(@B)«) {...}
   

sub funky_test ( Junction|Any @a, @b ) { ... }
 

Unless you have a junction, and you wanted it to autothread on the first 
parameter, rather than be passed in, in order to get some perceived 
desirable side effect out of funky_test that passing it a Junction would 
only give a subset of.

Suppose funky_test is a derivative of C< printf >. Only this printf 
let's you feed it a junction for the format, and it will sort through 
them and see which one matches best depending on actual number of 
parameters, parameter types, etc. Ordinarily, this would be fairly cool 
stuff.
But let's say you instead wanted it to print the same data with all the 
different formats. With my calling, you could make the distinction 
rather easily. With yours, you have to set up the looping yourself.

Basically I'm putting all the power of threading into the hands of the caller.
   

The caller is not in a position to know if the callee is internally
structured in such a way that passing in a raw junction makes sense. 
 

Sure they are. It's called reading the documentation. If it doesn't say 
it can handle junctions, it probably can't.

The right place to say "I can handle a junction, don't autothread" is
in the callee; that's the behavior @Larry is proposing.
 

I'm sending the same message. Only my message goes to the programmer, 
not the runtime.
I'm also making it where the decision to insert autothreading code or 
not is made at compile time, not runtime.

As for C< .. >, I'd say that it should handle junctions being fed into it by throwing an exception.
   

Why is this more sensible than returning a list of junctions in list
context and a junction of arrayrefs in scalar context?  (I believe
infix:<..> will return an arrayref in scalar context, though I could
be wrong.)
(The array of junctions is negotiable, by the way; whatever it is,
though, it should probably be the same as the default meaning for list
returns from an autothreaded function.)
 

About the only thing is could return would be a lazy list of jun

Re: Junction Values

2005-02-19 Thread Rod Adams
Brent 'Dax' Royal-Gordon wrote:
Rod Adams <[EMAIL PROTECTED]> wrote:
 

The caller is not in a position to know if the callee is internally
structured in such a way that passing in a raw junction makes sense.
 

Sure
they are. It's called reading the documentation. If it doesn't say it can
handle junctions, it probably can't.
   

I don't want to have to stop in the middle of a hundred-line function
to think, "Does Store::Market.get act sanely when I give it a
junction?  Do I need to explode it manually, or will it handle the
junction nicely on its own?" 

You call functions where you don't know what data types they are 
expecting? That's... surprising.
Even in a loosely typed world like Perl, knowing what a sub or method is 
expecting to be fed seems like a good idea to me. I see checking for 
accepting junctions as input as being on the same level as "Does it want 
a list or an arrayref here?".

When I'm writing my own insanely large functions, I'm constantly hitting 
the docs to see the nuances about the method calls I'm not already 
intimately familiar with. And if I'm going to attempt to use a function 
in a new way (like feeding it a Junction), I recheck the docs to make 
sure I'm not setting myself up for trouble down the road.

Your mileage may vary.
-- Rod Adams.
(PS - This should not be construed to be an attack on you or your 
programming style. It is not. Though I've never seen you in action, I 
have every reason to believe you are a fully competent developer. It is 
simply a response to your statement above, explaining why I thought the 
attitude expressed there represented a weak argument.)




Re: Junction Values

2005-02-19 Thread Rod Adams
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 in scope where $x was 
assigned to (or the explicit use of some other module that also 
activates C). 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 pragma in order for junctions to even be stored in 
variables. It's as bizarre as requiring C or C or C or C 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 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

Re: Junction Values

2005-02-19 Thread Rod Adams
Damian Conway wrote:
Hmm. On rereading my last message, I feel that it comes across as 
angry, and critical of this entire discussion or perhaps of particular 
participants.

That was certainly not my intent and I apologize if that's how it 
appeared. I genuinely respect the contributions of every person on 
this list, and even when (as now) I strenuously disagree with the 
ideas expressed, I know that those contributions are sincere and 
offered with the best interests of Perl at heart.

I still stand by every point I made in that last message, but I'm 
sorry that I let my frustrations leak into the discussion.

Damian

Well, I for one, never took any offense to any of the responses sent my 
way. And I appreciate the patience it's likely taken to not just 
completely Warnock me.

However, I also realize that I might have stepped on some toes of the 
course of this long discussion. Which was never my intention, and I'll 
apologize to any who feel I've slighted them in the process.

I do believe everyone on this list shares the same goals of making Perl 
6 the possible language that it can be. However, opinions will vary as 
to what that actually means. Being a group of people that can by and 
large be described as having a fairly large egos, these differences of 
opinion can become rather passionate. And passion leads to some pretty 
extreme responses.

It certainly hasn't helped matters that the exact nature of my proposal 
has changed in some fairly drastic ways on a regular basis, as I came to 
a better understanding of what Junctions were, and how they were being 
implemented. I apologize for any confusion this may have caused, but I 
do think the resulting discussions have shed some new insights on 
Junctions, Sets, what it means to have a sigil, why junctions can't just 
be another class, and several other topics. Poor Mr. Fowles is likely 
having nightmares figuring out how to summarize all of this.

Positions I still stand by:
- Sets belong in the language, and need more support. This can likely be 
done at the module level, but I'd like them better incorporated, 
preferably with their own sigil. However, I believe they can peacefully 
coexist with Junctions, and one concept does not need to crowd out the 
other.

- Implicit autothreading is a Bad Thing, and should not happen. This is 
almost entirely due to the side effects such behavior can generate. To 
keep the power of junctions viable, explicit threading should be 
trivially easy, but it should be explicit, none the less.

-- Rod Adams



Lingering questions about Junctions.

2005-02-19 Thread Rod Adams
Okay,
Now that I've largely accepted junctions (except implicit autothreading, 
which is Bad.), I see some corners that need to be poked at in terms of 
how they fit into the language as a whole.

All of these examples assume an appropriate level of "use junctions;" is 
in effect.


- Can junctions be used as array/hash subscripts?
In an rvalue context, this makes sense, in that you can simply return a 
junction of the deferences. But in an lvalue context, this gets dubious 
for everything except all() junctions. Consider:

   @x = 1..10;
   @x[any(4,3)] = 7;
What does @x look like now?
   @x[all(4,3,2)] = 7;
makes sense, as long as it means:
   @x[4,3,2] »=« 7;
I don't want to even think about what:
   @x[none(1,2)] = 7;
does.

- Can you have non-scalar junctions?
As the discussions surrounding C< .. > demonstrated, it's not that hard 
for someone to create a situation where a junction of lists might come 
into existence. But let's consider something a step beyond.

   %x = (a => 1, b => 2, c => 3) | (d => 4, e => 5, f => 6);
   @y = %x.keys;
Does this explode, or does @y have something useful in it now?
Before dismissing the concept completely, it's perfectly possible to 
create something much like a junctive hash via references:

   %x = (a => 1, b => 2, c => 3);
   %y = (d => 4, e => 5, f => 6);
   $z = one(\%x, \%y);
   @w = $z.keys;

- What does it mean to sort a list of junctions?
   @x = any(1,6), all(2,5), one(3,4);
   @x = @x.sort;
Does sort() carp on junctions, or is it just one of the weird things you 
have to live with if you're playing with junctions?

-- Rod Adams



Re: Junction Values

2005-02-19 Thread Rod Adams
Damian Conway wrote:
Rod Adams wrote:
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?

Yes, it's a side-effect of the new default prohibition on junction 
assignments (though I'm still working hard to convince everyone that 
that prohibition cripples junctions and that having to  
before you can assign a basic Perl 6 scalar datatype to a variable is 
an abomination).
FWIW, I agree with you that having something half enabled by default 
make little sense. But I'll accept it as a stop gap until I get my 
explicit threading.

And I really don't like the implications of how turning on "use 
junctions" can also suddenly change the threading semantics of 
junctions. Talk about subtleties in action...

I imagine some intermediate level programmer decides they are ready to 
start playing with stored junctions. He adds a "use junctions;" at the 
top of his file, thus turning it on for all functions written in that 
package. Suddenly, some of his function calls with stop implicitly 
threading, and instead start carping in some truly spectacular ways. 
Said programmer quickly takes away the "use junctions;", and never 
considers using stored junctions again. It's just not worth the trouble, 
in his mind.

If, however, he was conditioned to put in some »«'s whenever he wanted 
his junctions to thread, he would not encounter this problem.


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.

Sure. That's why we have the ability to specify subroutines where 
junctive args are *not* autothreaded, by typing the corresponding 
parameter as taking a junction:

multi sub infix:«==» (YourType $x, Junction $y) is symmetrical {...}
multi sub infix:«<»  (YourType $x, Junction $y) is symmetrical {...}
These two multisubs can optimize for junctive arguments to their 
hearts' content.
I guess I misunderstood your statement of "literal junctions *will* 
autothread in all circumstances" to mean _all_ circumstances, not just 
ones where the callee didn't explicitly say they could accept them, or 
if the current "use junctions;" status is in alignment with the moon, or 
other such things.

I will allow you to alter that statement if you now find it 
insufficiently qualified.

I don't see that Patrick's response implies that at all. In fact, I 
think his statement that:

   >> Well, the ultimate answer is that both Dan and Patrick (and others)
   >> will negotiate the exact interface when we get to that point, and
   >> that we don't seem to be too concerned about it at the moment.
   >> (It could just be that we're both burying our heads in the sand
   >> hoping it'll be magically "solved" by the other.  :-)
   >>
   >> However, in working out these examples I'm fairly comfortable that
   >> it can be made to work at the Perl 6 compiler level if need be,
   >> although it will probably be a lot more efficient if we can find a
   >> way to do it within Parrot.
seems to confirm that detecting and reporting autothreaded 
side-effects is entirely possible.
Let me attempt to clarify the discrepancy as I see it.
I'll take Damian's recent comment of: " And if C< 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. "

and my 19210 code of:
   $x = 3|4;
   $y = fun($x);
   sub fun ($x) {
   warn "enter: fun($x)\n" if $DEBUG;
   $x + 1;
   }
I hope it's clear that whether or not fun() has side effects is a 
runtime decision, and can't realistically be determined at function call 
time.
Now, let's assume that this falls under Damian's heading of "happens to 
autothread when I wasn't expecting it to."
If $DEBUG is off, no worries.
If $DEBUG is on, I expect my explicit warning, as promised.

What I am questioning is how perl decides when to give my warning. Does 
perl inspect fun() to see if there are any side effect causing calls in 
it? Or does it keep an internal note to itself saying "I'm 
autothread

Re: Junction Values

2005-02-19 Thread Rod Adams
Damian Conway wrote:
Rod Adams wrote:
I never want to see implicit threading. Ever.

If this is the only stumbling block, then it's easily solved.
Instead of ruining junctions by imposing all kinds of complex and 
annoying hoops and hurdles (i.e. C and C), we can just offer a C pragma that 
prevents any non-explicit junction from autothreading any operator or 
subroutine. Put it at the top of your code and you'll never get any 
implicit threading.
Well, allow me to explain what I want in a little more detail, so I can 
be sure I'm getting it.

I want to be able to feed a junction to functions that handle it, but I 
also want to thread over ones that do not. But I do not want the 
decision of which way to go to be made for me.

So, I want to be able to pass a raw junction into C< == >, because it 
understands junctions, and will take care of the threading for me, 
likely in a way that's much more efficient than my generalized »« 
threading ever could. I do not consider this implicit threading. It's 
passing the task of threading off to C< == >, which itself performs some 
form of explicit threading.

But when I'm faced with some function that does not directly support 
junctions, or one which does, but not in a way that I like, I want to be 
able to thread my junction over it.


I do not think that what you said above is enough to accomplish this. I 
believe what I need to separate your threading desires from mine is two 
fold:

1) I need my »« modifier which forces explicit threading, which will not 
normally be needed under "use autothreading;" conditions.
2) I need "no autothreading;" to alter the calling syntax to require »« 
when threading is desired (or you can do a .values() and .junctiontype() 
and roll your own if you really want to). But I can still pass junctions 
around at will, withstanding normal type check requirements.

Then the only argument left is whether "use autothreading" or "no 
autothreading" should be default.  I would, of course, say "no 
autothreading;", and then turn back on the ability to store junctions.

IMO, "no autothreading" would provide enough cover for the unsuspecting, 
removing the Bad Side Effects problems that spawned Larry's no junction 
storage default. At the same time, junctions still have enormous power 
via the »«. If people don't want to have to bother figuring out when to 
thread for themselves, they can then turn on "use autothreading", and 
let perl attempt to figure it out for them.

Also, if "no autothreading" is default, the person new to Perl6 will 
always have something to present to investigate to figure out what is 
going on. In my code, it'll be the funny looking C< »$junction« > 
things. In your code, it'll be the C< use autothreading; > at the top of 
the page.


The only implementation problem I see is a potential for the »« to be 
mis-parsed, since » and « seem to be serving several different roles 
these days, but I don't think any of them conflict with this meaning. If 
you want to rename »« to something else, I'm open to suggestions. Just 
leave it fairly simple.

As for why implementation should be easy (or at least the delta between 
your way and my way is easy):

- The functionality of »$junction« has to be defined anyways if 
autothreading happens. It's just calling an already existent chunk of code.

- The logic of when to thread becomes:
   given $situation {
  when marked_with_»«()
{ thread }
  when use_autothreading() & damians_ouija_board()
{ thread }
  default
{ don't thread }
   }
And you've already defined how the ouija board works, everything else 
should be boilerplate for the compiler/runtime to handle.

This sound reasonable enough?
-- Rod Adams


Re: Junction Values

2005-02-20 Thread Rod Adams
Nigel Sandever wrote:
On Sat, 19 Feb 2005 18:42:36 +1100, [EMAIL PROTECTED] (Damian Conway) wrote:
The Awesome Power of Junctions:
   

As I tried to express elsehwere, this what I'm looking for. 

Instinctively, and for a long time since I first came across Q::S, I thought 
that the "killer app" of Junctions is there somewhere, I'm just not seeing it 
yet.

I'd really like to see some practical demonstrations of the Awesome Power. 

Something that goes beyond producing a boolean result from a set of values that 
could equally be done using hyperoperators?
 

Well, that was one of my stumbling blocks early on. They don't really 
give you the power to do anything you couldn't previously do. They just 
make certain things a lot easier to do.

But I'll take a whack at giving you something non-trivial to do without 
junctions:

   $re1 = /^ <-[x]>* x <-[x]>* $/; # match a string with exactly one 
'x' in it.
   $re2 = /^ <-[y]>* y <-[y]>* $/; #  ditto 'y'
   $re3 = /^ <-[z]>* z <-[z]>* $/; #  ditto 'z'

   $re4 = all($re1, $re2, $re3);  # matches if x,y, & z all appear 
exactly once, in any order.
   $re5 = one($re1, $re2, $re3);  # matches if there is exactly one x, 
y, or z
   $re6 = any($re1, $re2, $re3);  # matches if there is at least one of 
x,y,z that appears exactly once.
   $re7 = none($re1, $re2, $re3); # matches if there are 0 or 2+ of 
each of x,y,z.

And all seven of these can be used as any stored RE can:
   if $x ~~ $re6 {...};
   given $x {
  when $re5 {...}
  when 'santa' {...}
  when ($re1 | $re3) & $re3 {...}
   }
Looking at the junctioned RE's:
#6 would is straight forward to do as a single RE in this case, and in 
the general case.
#5 would be fairly trivial to in this case, but not in the general case.
#4 is possible with a lot of zero-length look aheads and look-behinds, 
but very ugly.
#7 I have no idea how to attack as a single RE in anything close to 
approaching elegance.

So what have we gained here? The ability to join several RE's together, 
into something that still acts like a single RE. Show me the equivalent 
code without junctions, and then we'll compare the power of junctions.

btw, the examples above assume the ability to store a junction. So you 
either have to 'use junctions;', or convince Larry to rescind that 
restriction.

HTH.
-- Rod Adams



Re: Junction Values

2005-02-20 Thread Rod Adams
Damian Conway wrote:
Rod Adams asked:
> This sound reasonable enough?
Frankly, no. ;-)
Sorry, but your latest proposal sounds complex, multiply 
special-cased, and way too much of an imposition on the programmer 
(which is specifically what junctions are supposed to avoid).
Funny. I thought it was simple and elegant. My explanation might have 
been complex, as well as the motivations, but I truly considered it a 
straight forward and simple solution.

As for "too much of an imposition on the programmer", that's essentially 
what I was asking for all along. To be imposed upon to decide when 
threading occurs. I won't apologize for that, or change my position on 
it. But I was making the imposition optional.

And, actually, now that I better understand your latest proposal, I 
realize how amazing close we are.

Then, if you don't want implicit autothreading, you can turn it off 
completely: C.

And if you want explicit (non-auto)threading, you can use an explicit 
junction, even under C:

is_prime( any($x) )
Change that C< any($x) > to C< »$x« >, and the important differences 
between our positions shrink dramatically.

Reason I don't like any() here is that $x already has a junctive 
condition on it. While any() with a single value does not change in the 
least how this will be evaluated in the long run, it could be confusing 
to wrap an all() junction inside an any() call. Doubling up the type 
works for all the types except none(). Use »« for an explicit call 
designator, and you revert to the type already in the junction.

Give me my »« as a secondary way of always explicitly threading, and 
I'll go away happy. You can keep the rest of your proposal the same.  
I'll just start using them wherever I think threading should happen, 
even if I never needed to use them in most of the places I will. It'll 
be a good visual to myself of what's going on.

Don't give them to me, and I'll frown for a while, but then likely get 
over it.

I truly appreciate the thought and effort that all of you--especially 
Rod and Patrick--have put into this discussion, but I'm afraid I have 
to bow out of it now.
I understand bowing out of this perfectly. There other tasks whose time 
I've raided for this discussion, and the backlog is starting to look 
pretty nasty.

But it has been a good and healthy discussion. Many things have come of 
it. Thanks to all the participants.


PS: FWIW, I'd have absolutely no objection to us adding a fifth core
junctive type (perhaps C, perhaps just C ;-) that
has *no* associated predicate, but which implements full set 
semantics:

 my $x = set(1..3);
 my $y = set(1,3,5,7,9);
 my $n = 2;
 $x | $y  # set(1,2,3,5,7,9)
 $x & $y  # set(1,3)
 $x - $y  # set(2)
 !$x  # set(none(2));-)
 $x < $y  # $x is a proper subset of $y
 $x <= $y # $x is a subset of $y
 $x == $y # $x is the set $y
 $x ~~ $y # $x is the set $y
 $n < $y  # $n is an element of $y
 $n ~~ $y # $n is an element of $y
 set()# empty set
 $x.values# list of elements of set $x
 $x.powerset  # power set of $x
 $x x $y  # cross product of $x and $y
 # etc., etc.
Now THAT is an even better idea than the separate Set class I was going 
to champion whenever I next had time for such a thing!
I support this concept fully!

-- Rod Adams
PS - Looks like Matt gets his wish. This juggernaut of a thread is 
coming to a close. I'd be happy to proof his summary of it if he gives 
me an advanced copy.



Re: Junction Values

2005-02-20 Thread Rod Adams
Eirik Berg Hanssen wrote:
Rod Adams <[EMAIL PROTECTED]> writes:
 

   $re1 = /^ <-[x]>* x <-[x]>* $/; # match a string with exactly one
'x' in it.
   $re2 = /^ <-[y]>* y <-[y]>* $/; #  ditto 'y'
   $re3 = /^ <-[z]>* z <-[z]>* $/; #  ditto 'z'
   

   $re7 = none($re1, $re2, $re3); # matches if there are 0 or 2+ of
each of x,y,z.
   

#7 I have no idea how to attack as a single RE in anything close to
approaching elegance.
   

 Depending on your idea of elegance ... anchored zero-width negative
lookahead:
$re7 = qr/^ (?!= $re1 | $re2 | $re3 ) /x;
 Oh right.  Perl6.  Well, if I understand "<$re1>" correctly, I think
this is what it will look like:
$re7 = /^  | <$re2> | <$re3> > /;
 

That doesn't quite do it, but something along those lines is possible. 
You'd have to make sure the look ahead/behinds match to the end of the 
string, not just some substring. And then you'd have to put in something 
to actually match the string. So possible, but not straightforward in 
the least.

 I still want junctions, but I also still am not quite sure how they
will behave.  For instance, I wonder how this would autothread or not:
my sub f (Int $x) {
 if $x {
   return 0, 1, $x;
 }
 else {
   return 0, 1;
 }
}
my $j = 0 | 7;
my @a = (1, f($j), 0);
 - How many elements are there in @a?  3? 5? 4|5?
 - What is @a[-1]?  0?  any(0)?  0|undef?
 - What is @a[4]?  undef?  0|undef?  0?
 Naïvely, I would expect that setting of @a be equivalent to this:
my @a = (1, ([0,1]|[0,1,7]), 0);
 And so from the callers perspective, &f, which usually returns two
or three values, suddenly returns a single (junctive) value.  New
semantics for &f, courtesy of autothreading.  I expect this is too
naïve.  But what am I missing?
 

I believe you are correct in your analysis.
It's also something that I will cover as soon as I have time to write 
down the revelation I had about junctions laying in bed last night. 
(Don't cringe everyone. I actually figured out why Damian insists on 
implicit threading. And I agree with him. Now I want to clamp a 
completely different kind of restriction on Junctions.)

I might be able to find time for it late tonight. Might take a few days.
-- Rod Adams


Junctions, Sets, and Threading.

2005-02-22 Thread Rod Adams
ing operation that they lost with the Prime
Junction Rule.
Since all the »'s and «'s floating around make this explicit threading,
there are no nasty surprises laying around. You never have a scalar
suddenly explode into a list, causing no end of havoc in unsuspecting
code.
These are also infinitely more useful, since you can be guaranteed that
they won't short circuit, and they are in exactly the order you
specified.

So that's how I feel about things. The Prime Junction Rule was the big
revelation I had the other night. The rest of this was the logical
consequence spawned off that single thought to make it a complete idea.
I think that overall in this process I've done the following:
- Kept the real power of Junctions intact.
- Provided fairly strong protection for newbies, without sacrificing
 power.
- Kept Nasty surprises to a minimum.
- Got rid of the need for "half on" features.
- Provided back any power that the Prime Rule removed through sets and
 expanded hyper ops.
-- Rod Adams


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 "\n"s 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

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 C. 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 //, prompt 'search for: ';
 my @out = split //, 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 

Re: scoping functions as list operators?

2005-02-24 Thread Rod Adams
Luke Palmer wrote:
We have discussed making equals low precedence enough to eliminate the
parentheses in the standard swap:
   $x, $y = $y, $x;
 

$x, $y <== $y, $x;
-- Rod Adams


Re: scoping functions as list operators?

2005-02-24 Thread Rod Adams
Luke Palmer wrote:
Now we just need to determine if 'my' can leave its post as a unary declarator.
 

Don't see why not... If you ever need it unary, you can just put the () 
back in.

The question becomes which is more common:
Scoping a single variable in a list context, or scoping several 
variables at once. Likely the later.

This also reminds me of the thought someone had a while back about 
making = not copy in list context, making people use ==>/<== for all 
list assignments. It would certainly take care of the :

   $x, $y = $y, $x;
problem that will have people scratching their heads. (assuming that 
doesn't trigger a warning/error). Overall, I like the protection it 
provides, but dislike the extra three keystrokes it means for something 
I use so often.

-- Rod Adams




Re: scoping functions as list operators?

2005-02-24 Thread Rod Adams
Uri Guttman wrote:
that fixes Stéphane's problem with my yall proposal. and yall solves the
unary my problem. :)
 

Stop misusing "y'all" before this Texan has to hurt you.
And y'all wonder why we hate you damn yankees. Can't even speak properly 
up there.

:-)
We should instead have a list attribute, so we can say:
   $x, $y, $z are mine! mine! mine!;
(Must be spoken like a three year old when read.)
-- Rod Adams




Re: Q: Junctions & send+more=money

2005-02-26 Thread Rod Adams
Markus Laire wrote:
I have two questions about this example code
(taken from http://svn.openfoundry.org/pugs/examples/sendmoremoney.p6)
I have a few issues with this code. Or at least observations of how it 
differs from the classic "SEND + MORE = MONEY" problem. see below.


#!perl6
use v6;
my $s; my $e; my $n; my $d; my $m; my $o; my $r;
my $y;
$s = any(0..10) & none(0);
$e = any(0..10);
$n = any(0..10);
$d = any(0..10);
$m = any(0..10) & none(0);
$o = any(0..10);
$r = any(0..10);
$n = any(0..10);
$y = any(0..10);

I think these should be any(0..9).
Indeed they should. I will assume they are written as such in my 
discussion below.


my $send := construct($s,$e,$n,$d);
my $more := construct($m,$o,$r,$e);
my $money := construct($m,$o,$n,$e,$y);
if ($send + $more == $money) {
say " send = $send";
say "+more = $more";
say "-"
say "money = $money";
}
sub foldl(Code &op, Any $initial, [EMAIL PROTECTED]) returns Any {
if ([EMAIL PROTECTED] == 0) {
 return $initial;
} else {
 return &op(shift @values, &?SUB(&op, $initial, @values));
}
}
sub add(Int $x, Int $y) returns Int {
return $x + $y;
}
sub construct([EMAIL PROTECTED]) returns Junction {
return foldl( sub ($x, $y) { $x * 10 + $y}, 0, @values);
}

How would the if (...) {...} work if there were more than one possible 
match to this equation?
As written, this generates a rather large number of solutions. I do not 
see any test to make sure that the individual letters are different. Nor 
is there any check to see if all the "e"'s assume the same value.

So what you reach the:
   if ($send + $more == $money) {...}
stage is $send being something equivalent to  any(..) & 
none(..0999), only no where near as simplified. Similar values can 
be found in $more and $money. Therefore, you're asking something like: 
"Are there any two numbers between 1000 and  that together total 
between 1..9?" The answer is yes, and then you get an error as 
you attempt to print a raw junction, if you're lucky, or 9000 "send" 
lines, followed by 9000 "more" lines, followed by 9 "money" lines.

Junctions are _not_ the same as unbound variables in Prolog. They do not 
"widdle away" inconsistent values as those inconsistencies are found. 
Most of them (all except all()) do not have to use the same value each 
time they are evaluated.

If I'm wrong about this interpretation of this code, I apologize. But it 
certainly fits my understanding of junctions, which has grown by leaps 
and bounds over the last few weeks.

HTH,
-- Rod Adams



  1   2   3   >