Earlier in the week, fw wrote a journal post about his First Perl6 program. I was quite excited to see this, but then read a comment from educated_foo that pointed out that the Perl 5 version is actually shorter to write.
That didn't sit too well with me, because we really ought to make common things simpler, not harder. What really bugged me (about Perl 6, not about fw's post) was the following for sorting a hash by values:
for %words.pairs.sort: { $^b.value <=> $^a.value } -> $pair { say $pair }
.say for %words.sort: { $^b.value <=> $^a.value };
{ $^b.value <=> $^a.value }
just bugs me.%hash.sort: { .value }
> my %hash = { c=>5, b=>7, a=>-4, e=>9, d=>0 }; > .say for %hash.sort: { .value } a -4 d 0 c 5 b 7 e 9
> .say for %hash.sort: { .key } a -4 b 7 c 5 d 0 e 9
> .say for %hash.sort: { .value.abs } d 0 a -4 c 5 b 7 e 9
@dogs
contains a list of Dog objects we want to sort:
@dogs.sort: { .name } # sort dogs by name @dogs.sort: { .age } # sort dogs by age
> my @a =; > .say for @a.sort: { .lc } Apple apricot BaNaNa berry CHERRY danish Fruit
@a.sort: { .lc }
@a.sort: { $^a.lc leg $^b.lc }
multi method sort(@values: &by) { ... if &by.arity < 2 { my @v = @values.map(&by); my @slice = (0..^@v).sort: { @v[$^a] cmp @v[$^b] }; return @values[ @slice ]; } ... }
min
and max
:my $longest_string = @strings.max( { .chars } );
my %words; $*IN.slurp.comb.map: { %words{$_}++ }; .say for reverse %words.sort: { .values };
.comb
is not yet implemented), but at least it's getting closer to what we'd really like to see here. in the first version we compute
Nice.
Maybe this doesn't make sense but some way to stick with method calls appeals to me.
Instead of:
@dogs.sort: {
Something like:
@dogs.sort_by.name
But even as already implemented, I agree it's an improvement and a nice language feature. Thanks, Patrick!
Re:or this?
pmichaud on 2008-12-12T22:15:44
Part of the difference here is that
.sort_by (or .sort) is a method call on the list as a whole, and any method call after that really ought to be treated as a method call on the resulting sorted list. For example, @list.sort.reverse
@list.sort.map {... } Also, something like
@list.sort_by.name
gets the invocant in the wrong place, because in order for this to work the invocants to.name should be the individual elements of @list. So, I think the information on how to sort (e.g.,
.name
) really deserves to be an argument to the sort method, as opposed to a method itself.I did think of using the method name
.sort_by
as a way of distinguishing the "sort by comparison function" from the "sort by value" behavior, but I think/hope the dwimminess of using the block to determine that is sufficient. It's much nicer to always think "sort" than to have to wonder or remember the answer to "do I need '.sort' here or '.sort_by'?"Of course, Larry and the folks on perl6-language get the strongest vote, and I'll be glad to implement whatever API they finally decide on.
Thanks!
Pm
Turns out that this particular form of sort
already exists in the Perl 6 spec -- it was just in an odd place. In Synopis 3, we have:
The advantage of the method form is that it can be used in places that
require tighter precedence than C<~~> provides:
sort { $^a.M <=> $^b.M }, @files
though that's a silly example since you could just write:
sort {.M }, @files
So, it's just Synopsis 29 that needs to be updated, and as of this morning Moritz++ has made that change. So this is indeed an official part of the language, and we can go on remarking about how cool Perl 6 is.
Pm
Re:A few problems...
theorbtwo on 2008-12-18T18:13:29
Sorry for the rather fragmented first issue. It should say something along the lines of "why do you test if the airity is less then 2, rather then testing for it being exactly 1?"