Re: Proposal: split ternary ?? :: into binary ?? and //

2005-09-06 Thread Damian Conway

Luke wrote:


Not that being explicit is always a bad thing:

$val = some_cond()
  ?? ($arg1 // $arg1_default)
  // ($arg2 // $arg2_default)


No. What's a bad thing is creating new linguistic traps for when people 
inevitably forget to be explicit.




And I question your notion of highly useful in this case.


Huh??? Both // and the ternary are unquestionably highly useful constructs. My 
point was that making them not work together is a Very Bad Idea.




I guess the thing that I really think is nice is getting :: out of
that role and into the type-only domain.


Yes, I'd certainly like that too. But not at the cost of turning // into a 
bear-pit for the unsuspecting.


Damian


Re: Proposal: split ternary ?? :: into binary ?? and //

2005-09-06 Thread Patrick R. Michaud
On Tue, Sep 06, 2005 at 07:26:37AM +1000, Damian Conway wrote:
 Thomas Sandlass wrote:
 
 I'm still contemplating how to get rid of the :: in the
 ternary 
 
 Comments?
 I believe that the single most important feature of the ternary operator is 
 that it is ternary. That is, unlike an if-else sequence, it's impossible to 
 leave out the else in a ternary operation. Splitting the ternary destroys 
 that vital characteristic, which would be a very bad outcome.

At OSCON I was also thinking that it'd be really nice to get rid of 
the :: in the ternary and it occurred to me that perhaps we could use
something like '?:' as the 'else' token instead:

   (cond) ??  (if_true) ?: (if_false)

However, I'll freely admit that I hadn't investigated much further
to see if this might cause other syntax ambiguities.

Pm


RE: Proposal: split ternary ?? :: into binary ?? and //

2005-09-06 Thread Thomas Sandlass
HaloO,

Luke wrote: 
?? !! ain't bad either.
  
  It's definitely much better that sabotaging the
  (highly useful) // operator
  within (highly useful) ternaries.

 I guess the thing that I really think is nice is getting :: out of
 that role and into the type-only domain.

Right. To make :: indicate type or meta was my primary concern.
So I see the following situation:

unwanted  
?? ::

ASCII replacements
?? //# two binaries   
?? \\# I would like it as chaining binary nor
?? !!# wasn't binary ! the none() constructor
 # and !! the binary nor---at least in Pugs?

Latin1 replacements
?? ¦¦
?? ¡¡
?? ¿¿

@Larry's choice?
-- 
TSa



Re: Proposal: split ternary ?? :: into binary ?? and //

2005-09-06 Thread Luke Palmer
On 9/6/05, Thomas Sandlass [EMAIL PROTECTED] wrote:
 Right. To make :: indicate type or meta was my primary concern.

Okay, now why don't you tell us about this new binary :: you're proposing.

Luke


Re: multisub.arity?

2005-09-06 Thread Damian Conway

H. The arity of a given multi might be 3 or 4 or 5.

If *only* there were a way to return a single value that was simultaneously 
any of 3 or 4 or 5.


Oh, wait a minute...

Damian



Re: multisub.arity?

2005-09-06 Thread Luke Palmer
On 9/3/05, Damian Conway [EMAIL PROTECTED] wrote:
 H. The arity of a given multi might be 3 or 4 or 5.
 
 If *only* there were a way to return a single value that was simultaneously
 any of 3 or 4 or 5.
 
 Oh, wait a minute...

Well, we'd better document that pretty damn well then, and provide
min_arity and max_arity, too.   This is one of those places where
Yuval is spot on about autothreading being evil.  This is also one of
those places where I am spot on about Junctive logic being evil.

It looks like returning a junction is the dwimmiest thing we can do here:

given code.arity {
when 1 { code(1) }
when 2 { code(1,2) }
}

So if code is a multimethod that has variants that take two
parameters or three parameters, great, we call it with (1,2), which
will succeed.  And if it has variants that take one parameter or three
parameters, great, we call it with (1), which will succeed.  And if it
has variants that take one parameter or two parameters, um..., great,
we call it with (1), which will succeed.

In that last case though, this is not equivalent to the above:

given code.arity {
when 2 { code(1,2) }
when 1 { code(1) }
}

That may be a little... surprising.  Still, it's fixed to succeed
either way, so that's probably okay, right?

But let's do a little thinking here.  You're asking a code reference
for its arity.  It's pretty likely, that unless you are doing
dwimminess calculations (which aren't that uncommon, especially in
Damian's modules), that you have no idea what the arguments are
either.  An example of a function that uses arity is map.

sub map (code, [EMAIL PROTECTED]) {
gather {
my @args = @list.splice(0, code.arity);
take code([EMAIL PROTECTED]);
}
}

In the best case (depending on our decision), this fails with can't
assign a junction to an array.  In the worst case, it autothreads
over splice, returning a junction of lists, makes @args a junction of
lists, and then returns a list of junctions for each arity the
multimethod could have taken on.  I don't think that's correct... at
all.   The correct way to have written that function is:

sub map (code, [EMAIL PROTECTED]) {
gather {
my @args = @list.splice(0, min(grep { ?$_ } code.arity.states));
take code([EMAIL PROTECTED]);
}
}

Not quite so friendly anymore.  In order to use this, we had to access
the states of the junction explicitly, which pretty much killed the
advantage of it being a junction.

Junctions are logical travesty, and it seems to me that they cease to
be useful in all but the situations where the coder knows
*everything*.

But I still like them.

Here's how I'm thinking they should work.  This is a minimalistic
approach: that is, I'm defining them in the safest and most limited
way I can, and adding useful cases, instead of defining them in the
richest and most general way possible and forbidding cases that are
deemed unsafe.

Throw out all your notions about how Junctions work.  We're building
from scratch.

Things that come on the right side of smart match do a role called
Pattern, which looks like this:

role Pattern {
method match(Any -- Bool) {...}
}

Among the things that do pattern are Numbers, Strings, Arrays, ...
(equivalence); Types, Sets, Hashes (membership); Bools, Closures
(truth); and Junctions (pattern grep).  That is, a Junction is just a
collection of Patterns together with a logical operation.  It, in
turn, is a pattern that can be smart-matched against.  Therefore, we
sidestep the issue of the existence of junctions making every ordered
set have exactly one element[1]. because there is nothing illogical
against testing against a pattern.  You can also safely pass it to
functions, and they can use it in their smart matches, and everything
is dandy.

That's it for the base formulation.  A junction is just a pattern, and
it makes no sense to use it outside of the smart-match operator.

But that means that we have to change our idioms:

if $x == 1 | 2 | 3   {...}
# becomes
if $x ~~ 1 | 2 | 3   {...}# not so bad

if $x  $a | $b  {...}
# becomes
if ($x ~~ { $_  $a } | { $_  $b }) {...}  # eeeyuck
if $x  $a || $x  $b {...}  # back to square one

# from E06
if any(@newvals)  any(@oldvals) {
say Already seen at least one smaller value;
}
# becomes
if (grep { my $old = $_; grep { $_  $old } @newvals } @oldvals) {
say I don't remember what I was going to say because the
condition took so long to type
}

So, that sucks.  But I'm beginning to wonder whether we're really
stuck there.  The two yucky examples above can be rewritten, once we
take advantage of some nice properties of orderings:

if $x  max($a, $b) {...}
if min(@newvals)  min(@oldvals) {...}

But that's a solution to the specific comparison problems, not the
general threaded logic problem.

Yeah... so, that's 

Re: multisub.arity?

2005-09-06 Thread Juerd
Luke Palmer skribis 2005-09-06 13:28 (+):
 Well, we'd better document that pretty damn well then, and provide
 min_arity and max_arity, too.

Won't junctions do Array, then? I think foo.arity.max would be very
intuitive, and likewise, for @foo.arity { ... }


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



RE: Proposal: split ternary ?? :: into binary ?? and //

2005-09-06 Thread Thomas Sandlass
HaloO,

Luke wrote:
 Okay, now why don't you tell us about this new binary :: you're proposing.

Well, not a new one. Just plain old foo::bar::blahh and 'my ::blubb $x'
with relaxed whitespace rules. The ternary ?? :: is a splinter in my
mind's eye because it is not a compile time or symbol lookup construct.

The driving idea is to let tokens always mean the same or at least very
similar things in different contexts. And I thought that is your rating
as well. For :: that should be 'symbol table management'. E.g. ::= fits
that notion perfectly while the alternative separation of the ternary
doesn't.

There's yet another approach, to make ternary listfix:

  $val = $cond ?? true ?? false;

and perhaps we change it from ternary to (n  2)-ary:

  $val = $tested_only ?? $val_or_test ?? $other_or_test ?? $final;

But in both ways, recursive ternary needs parens.
Which can be regarded as a good thing. This listfix ??
behaves more like a rhs returning ||. As the RegularityGuy(TM)
I like the chaining triple // || \\ where // returns the first
defined, || returns the first true and \\ returns the first false.
And of course there are low precedence counterparts err, or, nor.
And the binary \ for none() construction. BTW is (\) indicating
the relative complement of the set operators? Even the unary ref
prefix makes sense as \ because it means 'not the value' or
'not right here but keep for later reference'. 
-- 
TSa




Re: multisub.arity?

2005-09-06 Thread Yuval Kogman
On Tue, Sep 06, 2005 at 13:28:24 +, Luke Palmer wrote:

This should still work:

 sub map (code, [EMAIL PROTECTED]) {
 gather {
 my @args = @list.splice(0, code.arity);
 take code([EMAIL PROTECTED]);
 }
 }

multi sub foo ( ... ) { ... } 
multi sub foo ( ... ) { ... }

my @mapped = map foo ...;

I think this is inconsistent.

There is another option though:

sub map (code, [EMAIL PROTECTED]) {
gather {
take code.mutably_bind_some(@list); # removes stuff
# from @list
}
}

The code object can then look for suitable multimethod alternatives
for the arguments in question, avoid that alltogether, dispatch
based on the arity of the first alternative, dispatch based on the
arity of the most general alternative, or whatever.

I would be careful though, and only pass singly bindable, non slurpy
code refs into map in my code, in which case i'd expect
'mutably_bind_some(@list)' to be along these lines:

method mutably_bind_some ([EMAIL PROTECTED] is rw) {
my @bound_params = map { pop @params } 1 .. $?SELF.arity;
$?SELF.bind_params(@bound_params);
}

-- 
 ()  Yuval Kogman [EMAIL PROTECTED] 0xEBD27418  perl hacker 
 /\  kung foo master: /me supports the ASCII Ribbon Campaign: neeyah!!!



pgpZ6GyiTREuw.pgp
Description: PGP signature


Re: Proposal: split ternary ?? :: into binary ?? and //

2005-09-06 Thread Nicholas Clark
On Tue, Sep 06, 2005 at 04:57:30PM +0200, Thomas Sandlass wrote:

 There's yet another approach, to make ternary listfix:
 
   $val = $cond ?? true ?? false;

So
 ^^ that one
doesn't do the same thing as
   ^^ that one?

I'd find that confusing in itself.
And that's without considering the change from the C? : of C and Perl 5.

[contents of this message may settle in transit, particularly if your mail
reader uses a proportional font.]

Nicholas Clark


Re: multisub.arity?

2005-09-06 Thread Austin Hastings

On a related note:

Suppose I have a function with a non-obvious arity: I might, in a 
desperate attempt to find billable hours, describe the arity as a trait:


 sub sandwich($bread, $meat, $cheese, $condiment1, $qty1, ...)
 does arity ({ 3 + 2 * any(1..Inf); });

That's cougheasy enough for trivial cases like this, but is there a 
way to use Cassuming for the more difficult cases?


Specifically, and obviously, printf-and-friends:

 my example := printf.assuming(format = %s %s %n\n);
 say example.arity();

The obvious output is any(1..Inf), since who's going to code the arity 
function?


But:

1. Is it possible to code an arity trait as a run-time block? (I assume yes)

2. Could this, or any, trait take advantage of assumed parameters? If 
so, how?


(Of course, after the arity function is written, it seems obvious to die 
unless the current function's arity is le the number of arguments...)


=Austin





\(...)?

2005-09-06 Thread Ingo Blechschmidt
Hi,

# Perl 5
my @array_of_references = \($foo, $bar, $baz);
print [EMAIL PROTECTED];# prints 3
print ${ $array_of_references[1] };  # prints $bar

# Perl 6
my @array = \($foo, $bar, $baz);
say [EMAIL PROTECTED];
# 3 (like Perl 5)?
# Or 1, making \(...) similar to [...]?

If \(...) still constructs a list of references, are the following
assumptions correct?

\(@array);   # same as
[EMAIL PROTECTED];
# (As () is only used for grouping in this case.)
# Correct?

\(@array,);  # same as
map { \$_ } @array;
# (As postcircumfix:{'\\(', ')'} is called here.)
# Correct?


--Ingo

-- 
Linux, the choice of a GNU | Row, row, row your bits, gently down
generation on a dual AMD   | the stream...
Athlon!| 



Packages, Modules and Classes

2005-09-06 Thread Stevan Little

Hey all,

I recently added Package and Module into the MetaModel (2.0) so that

   Package is an Object
   Module is a Package
   Class is a Module

as mentioned here 
http://article.gmane.org/gmane.comp.lang.perl.perl6.language/4599. 
Currently Packages have names and Modules add version and authority 
information, but I have nothing yet in place to represent package 
symbol tables. Which brings me to my questions.


I assume that each symbol table entry has the following slots; SCALAR, 
ARRAY, HASH, SUB, METH. I base this off the AUTO* hooks described in 
S10. I assume too that the METH slot is only valid for Classes, and not 
appropriate for Packages and Modules.


This would mean that given this code:

  package Foo;
  our $baz;
  sub bar { ... }

%Foo::{'bar'}{SUB} is a ref to the bar sub, and %Foo::{'baz'}{SCALAR} 
is a ref to the scalar $baz. The same, I would assume, would apply for 
Modules, so that:


  module Foo;
  our $baz;
  sub bar { ... }

is pretty much interchangable with the first example. But I think it's 
a little trickier when we get to Classes. Given this code:


  class Foo;
  our $baz;
  sub bar { ... }

I would expect it to behave just as it does for a Package or Module. 
But when we start to introduce methods and attributes, I am unsure of 
how things will work.


  class Foo;
  has $.baz;
  method bar { ... }

Can I get to $.baz? If I can, what will I get?

I expect that %Foo::{'bar'}{METH} will give me a method ref, but what 
happens when I try to store something in it? Does that perform some 
kind of meta-model actions (Foo.meta.change_method(...) or somesuch)? 
What if I delete the symbol table entry, what happens then (more 
meta-trickery)?


Thanks,

Stevan







Re: \(...)?

2005-09-06 Thread Juerd
Ingo Blechschmidt skribis 2005-09-06 19:46 (+0200):
 If \(...) still constructs a list of references, are the following
 assumptions correct?

IIRC, the RHS of \ is in scalar context, and the comma in scalar context
(the parens are just for precedence), creates an arrayref.

Which is interesting (and imho, a bad idea), because:

 \(@array);   # same as

\(@array) and [EMAIL PROTECTED] are the same thing

 \(@array,);  # same as

\(@array,) is [ @array ], NOT map { \$_ } @array


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


Re: \(...)?

2005-09-06 Thread Ingo Blechschmidt
Hi,

Juerd wrote:
 Ingo Blechschmidt skribis 2005-09-06 19:46 (+0200):
 If \(...) still constructs a list of references, are the following
 assumptions correct?
 
 IIRC, the RHS of \ is in scalar context, and the comma in scalar
 context (the parens are just for precedence), creates an arrayref.
 
 Which is interesting (and imho, a bad idea), because:
 
 \(@array);   # same as
 
 \(@array) and [EMAIL PROTECTED] are the same thing

Agreed.

 \(@array,);  # same as
 
 \(@array,) is [ @array ], NOT map { \$_ } @array

I'm not sure of the []s, remember postcirumfix:[ ] creates *new*
containers:

[EMAIL PROTECTED] = $bar;
# @array[0] unchanged

Compare this to:

(@array,)[0] = $bar;
# @array[0] changed to $bar

So, I think, if we ditch Perl 5's special \(...),

\(@array,); # should be the same as
\do { (@array,) };

This has the consequence that

(\(@array,))[0] = $bar;

changes @array[0].


--Ingo

-- 
Linux, the choice of a GNU | Mr. Cole's Axiom: The sum of the
generation on a dual AMD   | intelligence on the planet is a constant;
Athlon!| the population is growing.  



Re: multisub.arity?

2005-09-06 Thread Damian Conway

Luke wrote:

 Well, we'd better document that [junctive arity values] pretty damn
 well then, and provide min_arity and max_arity, too.

Unnecessary. The Cmax and Cmin builtins should be overloaded to Just
Work on junctive values:

if min code.arity  2 {...}


 This is one of those places where Yuval is spot on about autothreading
 being evil. This is also one of those places where I am spot on about
 Junctive logic being evil.

No. Neither autothreading nor junctive logic is evil. They're just
different. I know that many people can't tell the difference between
evil and different, but you two are smart enough to be able to.


 It looks like returning a junction is the dwimmiest thing we can do here:

 given code.arity {
 when 1 { code(1) }
 when 2 { code(1,2) }
 }

 So if code is a multimethod that has variants that take two
 parameters or three parameters, great, we call it with (1,2), which
 will succeed.  And if it has variants that take one parameter or three
 parameters, great, we call it with (1), which will succeed.  And if it
 has variants that take one parameter or two parameters, um..., great,
 we call it with (1), which will succeed.

 In that last case though, this is not equivalent to the above:

 given code.arity {
 when 2 { code(1,2) }
 when 1 { code(1) }
 }

 That may be a little... surprising.  Still, it's fixed to succeed
 either way, so that's probably okay, right?

It's not surprising at all. The order of Cwhen tests (usually) matters,
because a series of Cwhen statements (usually) short-circuits.


 But let's do a little thinking here.  You're asking a code reference
 for its arity.  It's pretty likely, that unless you are doing
 dwimminess calculations (which aren't that uncommon, especially in
 Damian's modules), that you have no idea what the arguments are
 either.  An example of a function that uses arity is map.

 sub map (code, [EMAIL PROTECTED]) {
 gather {
 my @args = @list.splice(0, code.arity);
 take code([EMAIL PROTECTED]);
 }
 }

 In the best case (depending on our decision), this fails with can't
 assign a junction to an array.  In the worst case, it autothreads
 over splice, returning a junction of lists, makes @args a junction of
 lists, and then returns a list of junctions for each arity the
 multimethod could have taken on.  I don't think that's correct... at
 all.   The correct way to have written that function is:

 sub map (code, [EMAIL PROTECTED]) {
 gather {
 my @args
 = @list.splice(0, min(grep { ?$_ } code.arity.states));

BTW, that should be code.arity.values, not code.arity.states.


 take code([EMAIL PROTECTED]);
 }
 }

 Not quite so friendly anymore.

Only because you're doing it the unfriendly way. Instead of, for example:

  sub map (code, [EMAIL PROTECTED]) {
  gather {
  my @args = @list.splice(0, min code.arity);
  take code([EMAIL PROTECTED]);
  }
  }

which is perfectly friendly, and also clearer. Or, perhaps more usefully, a 
multi should be illegal as a map block:


  sub map (code, [EMAIL PROTECTED]) {
  croak Can't use multi as map block if code.arity.values  1;
  gather {
  my @args = @list.splice(0, code.arity);
  take code([EMAIL PROTECTED]);
  }
  }



 Junctions are logical travesty,

Well, that's very emotive, but I don't believe it's either a useful or an 
accurate characterization. I would agree that junctions can be logically 
*sophisticated*, but then I'd argue that *all* programming constructs are that.



 and it seems to me that they cease to be useful in all but the
 situations where the coder knows *everything*.

What does that mean, exactly? How can anyone *ever* write sensible code
without knowing what kind of values they're processing?


 But I still like them.

 Here's how I'm thinking they should work.  This is a minimalistic
 approach: that is, I'm defining them in the safest and most limited
 way I can, and adding useful cases, instead of defining them in the
 richest and most general way possible and forbidding cases that are
 deemed unsafe.

 Throw out all your notions about how Junctions work.  We're building
 from scratch.

 Things that come on the right side of smart match do a role called
 Pattern, which looks like this:

 role Pattern {
 method match(Any -- Bool) {...}
 }

 Among the things that do pattern are Numbers, Strings, Arrays, ...
 (equivalence); Types, Sets, Hashes (membership); Bools, Closures
 (truth); and Junctions (pattern grep).  That is, a Junction is just a
 collection of Patterns together with a logical operation.  It, in
 turn, is a pattern that can be smart-matched against.  Therefore, we
 sidestep the issue of the existence of junctions making every ordered
 set have exactly one element[1]. because there is nothing