Re: Nitpick my Perl6 - parametric roles

2006-10-10 Thread Darren Duncan

At 4:08 PM +0200 10/10/06, TSa wrote:

HaloO,

Darren Duncan wrote:
Within a system that already has an underlying set-like type, the 
Junction in this case, a test for uniqueness is (pardon any 
spelling):


  all(@items).elements.size === @items.size

The all() will strip any duplicates, so if the number of elements 
in all(@items) is the same as @items, then @items has no duplicates.


OK, but you are not using the 'set with additional behavior' of
junctions. How would that be spelled with a pure set?

   set(@items).elements.size === @items.size

perhaps? This would nicely blend with the junction forms.


Yes, that is exactly how it would be spelled with a pure set.  In 
fact, your example is the more normal one, in that simply turning a 
collection into a set removes duplicates.  I used all() in my example 
because that is the Junction equivalent of making a set that contains 
all distinct members of @items. -- Darren Duncan


Re: Nitpick my Perl6 - parametric roles

2006-10-10 Thread TSa

HaloO,

Darren Duncan wrote:
Within a system that already has an underlying set-like type, the 
Junction in this case, a test for uniqueness is (pardon any spelling):


  all(@items).elements.size === @items.size

The all() will strip any duplicates, so if the number of elements in 
all(@items) is the same as @items, then @items has no duplicates.


OK, but you are not using the 'set with additional behavior' of
junctions. How would that be spelled with a pure set?

   set(@items).elements.size === @items.size

perhaps? This would nicely blend with the junction forms. Would
it even be the case that Set is a super role of the junctions?

Regards,
--


Re: Nitpick my Perl6 - parametric roles

2006-09-26 Thread Sam Vilain
Darren Duncan wrote:
>> Perhaps, but then Junctions might not assume elements have equality or
>> identity operations defined.
>> 
> As I recall, every type in Perl 6 has an equality and identity 
> operation defined because the Object superclass provides one.  If 
> nothing else, the type's equality and identity are the same as =:= 
> and .WHERE.
>   

Ok, seems reasonable.

>>  and that would
>> also have the side effect of making creating a junction an O(N^2) operation.
>> 
> Not if the type uses a hash-like index internally; then creating a 
> junction (or set) is more like O(N).
>   

Oh, yes, good point.

>> I think that the S06 definition needs re-wording.  It's more like a Bag
>> than a Set AIUI.
>> 
> I don't know what part you are reading, but the list of types that I 
> see says that a Junction is "Sets with additional behaviours".
>   

We're on the same page. It's just not the way that any of the prototypes
have behaved to date.

Sam.


Re: Nitpick my Perl6 - parametric roles

2006-09-26 Thread Darren Duncan

At 8:13 PM +1200 9/26/06, Sam Vilain wrote:

Darren Duncan wrote:
 > Within a system that already has an underlying

 set-like type, the Junction in this case, a test
 for uniqueness is (pardon any spelling):

all(@items).elements.size === @items.size

 The all() will strip any duplicates, so if the
 number of elements in all(@items) is the same as

 > @items, then @items has no duplicates.

Perhaps, but then Junctions might not assume elements have equality or
identity operations defined.


As I recall, every type in Perl 6 has an equality and identity 
operation defined because the Object superclass provides one.  If 
nothing else, the type's equality and identity are the same as =:= 
and .WHERE.



To do that you need to require this (and
which identity operator would you like to use today?),


Junction and Set and Mapping keys and Hash keys etc would simply use 
.WHICH and/or === when determining equality.  That's one of the big 
advantages in having such generic operators.  Simple.


And don't bring up eqv or whatever, since keying should always be on 
immutable things.



 and that would
also have the side effect of making creating a junction an O(N^2) operation.


Not if the type uses a hash-like index internally; then creating a 
junction (or set) is more like O(N).



I think that the S06 definition needs re-wording.  It's more like a Bag
than a Set AIUI.


I don't know what part you are reading, but the list of types that I 
see says that a Junction is "Sets with additional behaviours".


-- Darren Duncan


Re: Nitpick my Perl6 - parametric roles

2006-09-26 Thread Sam Vilain
TSa wrote:
> HaloO,
>
> Sam Vilain wrote:
>   
>> perl -MPerl6::Junction=one,all -le '@foo=qw(1 2 3 4); print "yes" if
>> (all(@foo) eq one(@foo))'
>> yes
>> 
>
> But does it fail for duplicates? I guess not because junctions
> eliminate duplicates and you end up testing unique values as
> above. E.g. all(1,1,2) == one(1,1,2) might actually give the
> same result as all(1,2) == one(1,2).
>   

Neither Pugs nor Perl6::Junction behaves like this.

pugs> for ([1,2,3], [1,1,2,3]) -> $x { my @x = @$x; my $all_unique = (
all(@x) == one(@x) ); print "{ $x.join(",") } became ", $all_unique; say
" (which is { $all_unique ?? "TRUE" !! "FALSE" })" }
1,2,3 became all(VJunc one(VBool True)) (which is TRUE)
1,1,2,3 became all(VJunc one(VBool False,VBool True),VJunc one()) (which
is FALSE)

Sam.


Re: Nitpick my Perl6 - parametric roles

2006-09-26 Thread TSa

HaloO,

Sam Vilain wrote:

Ah, yes, a notable omission.  I understood a Seq as a list with
individual types for each element, which are applied positionally.


I can understand that the type-checker can produce this type
for immutable sequences.



 The
superclass for things like Pair.


Hmm, have to think about that. Tuple subtyping usually has the
reverse logic where a larger tuple is a subtype if the common
parts are subtypes.



Here's a quick mock-up of what I mean:

   role Seq[ \$types ] {
   submethod COMPOSE {  # a la BUILD for classes
   loop( my $i = 0; $i < $types.elems; $i++ ) {
   # assumption: "self" here is the class
   # we're composing to, and "has" is a class
   # method that works a little like Moose
   self.has( $i++ => (isa => $types.[$i]) );


I don't understand this line. First of all, why the increment?
Then what does the double pair achieve when given to the .has
method? I guess you want a numeric attribute slot.


   }
   }
   my subset MySeqIndex of Int
   where { 0 <= $_ < $types.elems };

   method post_circimfix:<[ ]>( $element: MySeqIndex ) {
   $?SELF.$element;


This is also unclear. Firstly there's no $?SELF compile time
variable anymore. Secondly you are using the invocant as method?
Shouldn't that be the sequence index for retrieving the numerical
attribute slot?


   }
   }

Seq is certainly interesting for various reasons.  One is that it is a
parametric role that takes an arbitrary set of parameters.  In fact,
it's possible that the type arguments are something more complicated
than a list (making for some very "interesting" Seq types); the above
represents a capture, but the above code treats it was a simple list.


Can type parameters of roles be handled through normal variables as
your code does?


Regards,
--


Re: Nitpick my Perl6 - parametric roles

2006-09-26 Thread Sam Vilain
Darren Duncan wrote:
> Unless I'm mistaken, you may be going about this the wrong way.
>
> Within a system that already has an underlying 
> set-like type, the Junction in this case, a test 
> for uniqueness is (pardon any spelling):
>
>all(@items).elements.size === @items.size
>
> The all() will strip any duplicates, so if the 
> number of elements in all(@items) is the same as 
> @items, then @items has no duplicates.
>   

Perhaps, but then Junctions might not assume elements have equality or
identity operations defined.  To do that you need to require this (and
which identity operator would you like to use today?), and that would
also have the side effect of making creating a junction an O(N^2) operation.

I think that the S06 definition needs re-wording.  It's more like a Bag
than a Set AIUI.

Sam.


Re: Nitpick my Perl6 - parametric roles

2006-09-26 Thread Sam Vilain
Miroslav Silovic wrote:
> TSa wrote:
>   
>>>   role Set[::T = Item] does Collection[T] where {
>>>   all(.members) =:= one(.members);
>>>   };
>>>   
>> Nice usage of junctions!
>>
>> 
>
> But buggy - one means *exactly* one. So for an array of more than 1 
> element, all(@array) never equals one(@array) - if they're all the same, 
> it's more than 1, otherwise it's 0.
>
>   

perl -MPerl6::Junction=one,all -le '@foo=qw(1 2 3 4); print "yes" if
(all(@foo) eq one(@foo))'
yes

Didn't test on pugs yet.

Sam.

> all(.members) =:= any(.members) would also not work, as it will try to 
> match each member with some other or same member of the array. It will 
> always return true, in other words, as each element of the array is 
> equal to itself.
>
> This leaves all(.members) =:= .members[0], possibly extra with 
> non-emptiness test.
>
> Miro
>
>
>   



Re: Nitpick my Perl6 - parametric roles

2006-09-26 Thread TSa

HaloO,

Sam Vilain wrote:

perl -MPerl6::Junction=one,all -le '@foo=qw(1 2 3 4); print "yes" if
(all(@foo) eq one(@foo))'
yes


But does it fail for duplicates? I guess not because junctions
eliminate duplicates and you end up testing unique values as
above. E.g. all(1,1,2) == one(1,1,2) might actually give the
same result as all(1,2) == one(1,2).

Regards,
--


Re: Nitpick my Perl6 - parametric roles

2006-09-25 Thread Darren Duncan

At 7:28 PM -0700 9/25/06, Ashley Winters wrote:

On 9/25/06, Miroslav Silovic <[EMAIL PROTECTED]> wrote:

TSa wrote:


 >   role Set[::T = Item] does Collection[T] where {
 >   all(.members) =:= one(.members);
 >   };


 > Nice usage of junctions!

But buggy - one means *exactly* one. So for an array of more than 1
element, all(@array) never equals one(@array) - if they're all the same,
it's more than 1, otherwise it's 0.


Yeah, that would've been cool. Are we left with asserting
C? That'd be pretty close to the
original elegance.

Ashley Winters


Unless I'm mistaken, you may be going about this the wrong way.

Within a system that already has an underlying 
set-like type, the Junction in this case, a test 
for uniqueness is (pardon any spelling):


  all(@items).elements.size === @items.size

The all() will strip any duplicates, so if the 
number of elements in all(@items) is the same as 
@items, then @items has no duplicates.


Similarly, if @items is a list of Pair (such as 
when you're implementing a Mapping), and you want 
to assert that their keys are all distinct, then 
this variation (pardon any spelling) would do it:


  all(@items.map:{ .key }).elements.size === @items.size

Incidentally, a unique-key constraint on an RM 
relation or table is like the latter as well, but 
substitute "key" for the name(s) of the attribute 
or column.


On the other hand, if you're using the above Set 
to implement the Junction in the first place, we 
can't use all/any/one/none etc in the definition.


-- Darren Duncan


Re: Nitpick my Perl6 - parametric roles

2006-09-25 Thread Ashley Winters

On 9/25/06, Miroslav Silovic <[EMAIL PROTECTED]> wrote:

TSa wrote:
>
> >   role Set[::T = Item] does Collection[T] where {
> >   all(.members) =:= one(.members);
> >   };
>
> Nice usage of junctions!
>

But buggy - one means *exactly* one. So for an array of more than 1
element, all(@array) never equals one(@array) - if they're all the same,
it's more than 1, otherwise it's 0.


Yeah, that would've been cool. Are we left with asserting
C? That'd be pretty close to the
original elegance.

Ashley Winters


Re: Nitpick my Perl6 - parametric roles

2006-09-25 Thread Sam Vilain
TSa wrote:
>>   role Collection[\$types] {
>>has Seq[$types] @.members;
>>   }
> This is a little wrapper that ensures that collections have got
> a @.members sequence of arbitrary type. This immediately raises
> the question how Seq is defined.
> [...and later...]
> Are you sure that the underlying Seq type handles the one and
> two parameter forms you've used so far?

Ah, yes, a notable omission.  I understood a Seq as a list with
individual types for each element, which are applied positionally.  The
superclass for things like Pair.

Here's a quick mock-up of what I mean:

   role Seq[ \$types ] {
   submethod COMPOSE {  # a la BUILD for classes
   loop( my $i = 0; $i < $types.elems; $i++ ) {
   # assumption: "self" here is the class
   # we're composing to, and "has" is a class
   # method that works a little like Moose
   self.has( $i++ => (isa => $types.[$i]) );
   }
   }
   my subset MySeqIndex of Int
   where { 0 <= $_ < $types.elems };

   method post_circimfix:<[ ]>( $element: MySeqIndex ) {
   $?SELF.$element;
   }
   }

Seq is certainly interesting for various reasons.  One is that it is a
parametric role that takes an arbitrary set of parameters.  In fact,
it's possible that the type arguments are something more complicated
than a list (making for some very "interesting" Seq types); the above
represents a capture, but the above code treats it was a simple list.

>>   role Set[::T = Item] does Collection[T] where {
>>   all(.members) =:= one(.members);
>>   };
> 
> Nice usage of junctions! But how is the assertion of
> uniqueness transported into methods that handle adding
> of new values?

I haven't defined any mutable state yet; it's still "pure".

I'd expect mutability to be a different role, and a set of primitives
that work on this level by returning a new set with the changes made.
In fact the mutable Set could re-use those primitives, by just having a
Set as a member (that 'handles' the Set role methods), and automatically
changing that member each time a change is made, to point to the new Set
with the new contents.

Which all sounds very inefficient and scary until you realise what
happens inside generative GC VMs that support STM.

>>   role Mapping[::K = Item, ::V = Item] does Collection[Pair[K,V]] {
>>   all(.members).does(Pair) and
>>   all(.members).key =:= one(.members).key;
>>   }
> 
> I guess this is a typo and you wanted a where clause. The first
> assertion of the members doing the Pair role should be guaranteed
> by using Pair as the type argument when instantiating the Collection
> role.

Well spotted; yes, that is superfluous.

>>   role Hash[Str ::K, ::V = Item] does Mapping[K, V]
> 
> Will the Str assertion not be too specific for non-string hashes?

Another assumption I make here is that there is a basic type "Hash",
which as its name suggests, is all about hashing strings, and that the
more general form is called "Mapping" where any object can be the
source, not just Str subtypes.

Thanks for your other nitpicks and comments - much appreciated!

Sam.


>>   where { all(.members).key == one(.members).key }
>>   {
>>   method post_circumfix:<{ }> (K $key) of V|Undefined {
> 
> Nice union type as return type. But isn't the type name Undef?
> 
>>   my $seq = first { .key == $key } &.members;
> 
> Wasn't that @.members?
> 
>>   $seq ?? $seq.value :: undef;
> 
> Ternary is spelled ?? !! now.
> 
> 
>>   }
>>   }
>>  
>>   role ArrayItem[::V = Item] does Seq[Int, V] {
>>   method index of Int { .[0] }
>>   method value of Item { .[1] }
>>   };
> 
> Here we see the two parameter version of Seq at work.
> 
> 
>>   role Array of Collection[ArrayItem]
>>   where { all(.members).index == one(.members).index }
>>   {
>>   method post_circumfix:<[ ]> (Int $index) of Item {
>>   my $seq = first { .index == $index } &.members;
> 
> Is this first there a grep-like function? Shouldn't it then
> read 'first { .index == $index }, @.members'?
> 
> 
>>   $seq ?? $seq.value :: undef;
>>   }
>>   }
>>
>> I'll take the feedback I get, and try to make a set of Perl 6 classes in
>> the pugs project that look and feel just like regular Perl 6 hash/arrays
>> but are expressed in more elementary particles.
> 
> This might be very useful in future debates about these types. But
> I think everything hinges on the basic Seq type.
> 
> 
> Regards, TSa.



Re: Nitpick my Perl6 - parametric roles

2006-09-25 Thread TSa

HaloO,

Miroslav Silovic wrote:

TSa wrote:

Nice usage of junctions!



But buggy - one means *exactly* one. So for an array of more than 1 
element, all(@array) never equals one(@array) - if they're all the same, 
it's more than 1, otherwise it's 0.


Doesn't all(1,2,3) == one(1,2,3) expand the all junction first?
So that we end up with 1 == one(1,2,3) && 2 == one(1,2,3)
&& 3 == one(1,2,3) which is true. In the case of duplicated
entries we get a false if the one-junction supports that.
That is, how does e.g. one(1,1,2) work? Is it failing for 1?

Regards,
--


Re: Nitpick my Perl6 - parametric roles

2006-09-25 Thread Miroslav Silovic

TSa wrote:


>   role Set[::T = Item] does Collection[T] where {
>   all(.members) =:= one(.members);
>   };

Nice usage of junctions!



But buggy - one means *exactly* one. So for an array of more than 1 
element, all(@array) never equals one(@array) - if they're all the same, 
it's more than 1, otherwise it's 0.


all(.members) =:= any(.members) would also not work, as it will try to 
match each member with some other or same member of the array. It will 
always return true, in other words, as each element of the array is 
equal to itself.


This leaves all(.members) =:= .members[0], possibly extra with 
non-emptiness test.


   Miro




Re: Nitpick my Perl6 - parametric roles

2006-09-25 Thread TSa

HaloO,

Sam Vilain wrote:

Anyone care to pick holes in this little expression of some Perl 6 core
types as collections?  I mean, other than missing methods ;)


My comments follow.



  role Collection[\$types] {
   has Seq[$types] @.members;
  }


This is a little wrapper that ensures that collections have got
a @.members sequence of arbitrary type. This immediately raises
the question how Seq is defined.



  role Set[::T = Item] does Collection[T] where {
  all(.members) =:= one(.members);
  };


Nice usage of junctions! But how is the assertion of
uniqueness transported into methods that handle adding
of new values? In other words: I doubt that this comes
freely out of the type systems inner workings but is
more a statement of the intentions of a Set. Which leads
to the question when this where clause will be checked
or used to base MMD decisions.



  role Pair[::K = Item, ::V = Item] does Seq[K,V] {
  method key of K { .[0] }
  method value of V { .[1] }
  };
 
  role Mapping[::K = Item, ::V = Item] does Collection[Pair[K,V]] {

  all(.members).does(Pair) and
  all(.members).key =:= one(.members).key;
  }


I guess this is a typo and you wanted a where clause. The first
assertion of the members doing the Pair role should be guaranteed
by using Pair as the type argument when instantiating the Collection
role. Are you sure that the underlying Seq type handles the one and
two parameter forms you've used so far?



  role Hash[Str ::K, ::V = Item] does Mapping[K, V]


Will the Str assertion not be too specific for non-string hashes?


  where { all(.members).key == one(.members).key }
  {
  method post_circumfix:<{ }> (K $key) of V|Undefined {


Nice union type as return type. But isn't the type name Undef?


  my $seq = first { .key == $key } &.members;


Wasn't that @.members?


  $seq ?? $seq.value :: undef;


Ternary is spelled ?? !! now.



  }
  }
 
  role ArrayItem[::V = Item] does Seq[Int, V] {

  method index of Int { .[0] }
  method value of Item { .[1] }
  };


Here we see the two parameter version of Seq at work.



  role Array of Collection[ArrayItem]
  where { all(.members).index == one(.members).index }
  {
  method post_circumfix:<[ ]> (Int $index) of Item {
  my $seq = first { .index == $index } &.members;


Is this first there a grep-like function? Shouldn't it then
read 'first { .index == $index }, @.members'?



  $seq ?? $seq.value :: undef;
  }
  }

I'll take the feedback I get, and try to make a set of Perl 6 classes in
the pugs project that look and feel just like regular Perl 6 hash/arrays
but are expressed in more elementary particles.


This might be very useful in future debates about these types. But
I think everything hinges on the basic Seq type.


Regards, TSa.
--


Nitpick my Perl6 - parametric roles

2006-09-25 Thread Sam Vilain
Anyone care to pick holes in this little expression of some Perl 6 core
types as collections?  I mean, other than missing methods ;)

  role Collection[\$types] {
   has Seq[$types] @.members;
  }
 
  role Set[::T = Item] does Collection[T] where {
  all(.members) =:= one(.members);
  };
 
  role Pair[::K = Item, ::V = Item] does Seq[K,V] {
  method key of K { .[0] }
  method value of V { .[1] }
  };
 
  role Mapping[::K = Item, ::V = Item] does Collection[Pair[K,V]] {
  all(.members).does(Pair) and
  all(.members).key =:= one(.members).key;
  }
 
  role Hash[Str ::K, ::V = Item] does Mapping[K, V]
  where { all(.members).key == one(.members).key }
  {
  method post_circumfix:<{ }> (K $key) of V|Undefined {
  my $seq = first { .key == $key } &.members;
  $seq ?? $seq.value :: undef;
  }
  }
 
  role ArrayItem[::V = Item] does Seq[Int, V] {
  method index of Int { .[0] }
  method value of Item { .[1] }
  };
 
  role Array of Collection[ArrayItem]
  where { all(.members).index == one(.members).index }
  {
  method post_circumfix:<[ ]> (Int $index) of Item {
  my $seq = first { .index == $index } &.members;
  $seq ?? $seq.value :: undef;
  }
  }

I'll take the feedback I get, and try to make a set of Perl 6 classes in
the pugs project that look and feel just like regular Perl 6 hash/arrays
but are expressed in more elementary particles.

Cheers,
Sam.