develooper Front page | perl.perl6.language | Postings from May 2005

Re: [S29] uniq

Thread Previous | Thread Next
From:
Damian Conway
Date:
May 19, 2005 14:48
Subject:
Re: [S29] uniq
Message ID:
428D09B1.8020409@conway.org
Ingo Blechschmidt wrote:

> Is it intentional that there's no uniq in the current S29[1] draft?
> See [2] for Damian saying that uniq is probably in.

It still probably is.


> I wondered what uniq's default comparator should be, =:=?

&infix:<~~>


> Should it be possible to give an own comparator block, similar as with
> grep? E.g.
>   uniq <a b a a c d>;   # <a b a c d>
> 
>   uniq:{ abs $^a == abs $^b } 42, 23, -23, 23, 42
>                         # 42, 23, 42

Yes, I'd expect that it would be implemented as a multisub, equivalent to:

     multi sub uniq (&key_for: *@data) {
         my %seen is shape(Any);
         return grep { %seen{key_for $datum}++ } @data;
     }

     multi sub uniq (: *@data) {
         return uniq { $^self } @data;
     }

Note that this implementation is order-preserving, does not require repeated 
elements to appear consecutively, and keeps only the first occurrence.

The usage would be:

     uniq <a b a a c d>;                          # <a b c d>

     uniq { abs $^value } 42, 23, -23, 23, 42;    # 42, 23


BTW, I am *sorely* tempted to suggest the following implementation instead:

     multi sub uniq (&key_for: *@data is copy) {
         my %seen_at_index is shape(Any);
         my @uniq;
         for @data -> $datum {
             my $prev_index_for_datum := %seen_at_index{key_for $datum};
             if defined $prev_index_for_datum {
                 @uniq[$prev_index_for_datum] |= $datum;
             }
             else {
                 $prev_index_for_datum = +@uniq;
                 push @uniq, $datum;
             }
         }
         return *@uniq;
     }

     multi sub uniq (: *@data) {
         return uniq { $^self } @data;
     }

which would produce:

     uniq <a b a a c d>;                          # <a b c d>

     uniq { lc } <a b C A a c d>;                 # 'a'|'A', 'b', 'C'|'c', 'd'

     uniq { abs $^value } 42, 23, -23, 23, 42;    # 42, 23|-23

But I'd want to think through the ramifications a little more carefully before 
actually advocating something that correct. ;-)

Damian

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About