I think that grep should be renamed to something English and more, well,
semantic. 'Filter' comes to mind as a suggestion. I realise there's a
lot of cultural background (from Unix and Perl 5) that favours 'grep',
but I think it's more important to name the language elements
consistently (the right kind of consistency, I hope).
It's also possible to retain 'grep' as an alias (or add the new name as
an alias), but generally I've found having the same thing with multiple
names doesn't help at all (I'm looking at you, Ruby).
--
Ilmari Vacklin <ilmari....@helsinki.fi>
The name is relatively unimportant in the overall scheme of things.
I'm more worried about the fact that it's difficult to partition a
list into multiple lists in one pass without declaring temp arrays.
: It's also possible to retain 'grep' as an alias (or add the new name as
: an alias), but generally I've found having the same thing with multiple
: names doesn't help at all (I'm looking at you, Ruby).
If we had some kind of partitioning operator, it'd probably be generalized
to sorting into bins by number, where 0 and 1 are degenerate cases for
booleans. But since we'd almost certainly make the general form
(@bin0, @bin1, @bin2...) := classify { calc_int($_ } LIST;
It so happens that something like grep would still be useful for
the case where you're only interested in things that didn't go into
@bin0. And my point is that maybe grep ends up being some more
general form that selects that bin.
But we're probably missing a different useful generalization here.
In Perl 5, to set a slice, you have to write
%hash{ @keys } = @values;
whereas in Perl 6, it'd be nice to be able to say that with all
the keys and values on the right side somehow. Notionally:
%hash = (@keys[0] => @values[0],
@keys[1] => @values[1],
@keys[2] => @values[2],
...);
which says that we want a classify primitive that somehow can turn
LIST and calc_int($_) into
calc_int(LIST[0]) => LIST[0],
calc_int(LIST[1]) => LIST[1],
calc_int(LIST[2]) => LIST[2],
And then you just assign that to @bins, or filter on the pair keys
to get derived functions like grep. I guess you can write that
right now as
map { calc_int($_) => $_ } LIST
I guess that might combine with our new "pair" subscripts to tell assignment
that you want to assign pairs, not values:
@bins:[] = label { calc_int($_) } LIST;
and the corresponding string version:
%bins:{} = label { calc_str($_) } LIST;
Or if we decide :[]/:{} are too hard to see, and go with magical .pairs
and .kv instead (and it would have to be magical to work in lvalue
context):
@bins.pairs = label { calc_int($_) } LIST;
%bins.pairs = label { calc_str($_) } LIST;
I'm assuming there that assignment to .pairs is non-destructive.
Generally if you want to be destructive you should be using "my"
anyway. But maybe we need to clean up the "push" vs = infelicity
as well, and make an assignment operator that pushes.
Then we could have
%bins.pairs = label { calc_str($_) } LIST;
be destructive and
%bins.pairs ,= label { calc_str($_) } LIST;
means
%bins.pairs = %bins.pairs, label { calc_str($_) } LIST;
which the non-destructive variant that is equivalent to
push %bins.pairs, label { calc_str($_) } LIST;
Though arguably you could go at it from the other direction, and if
we are making magical lvalue methods like .pairs and .kv, then clearing
an array is just another adverbial method:
%bins.clear.pairs = label { calc_str($_) } LIST;
or some such. But I still don't really like magical methods
that aren't really methods. I'd rather keep them modifiers or
pseudo-functions that can be visually distinguished from true methods.
additional(pairs(%bins)) = label { calc_str($_) } LIST;
clobber(pairs(%bins)) = label { calc_str($_) } LIST;
additional(kv(%bins)) = labelkv { calc_str($_) } LIST;
clobber(kv(%bins)) = labelkv { calc_str($_) } LIST;
or whatever. But it'd be even nicer if we could avoid the pseudofunction
syntax as well. It does seem rather nice to attach the clobber/nonclobber
distinction to the assignment, so maybe
pairs(%bins) = label { calc_str($_) } LIST;
pairs(%bins) ,= label { calc_str($_) } LIST;
kv(%bins) = labelkv { calc_str($_) } LIST;
kv(%bins) ,= labelkv { calc_str($_) } LIST;
is the cleanest solution. If we came up with a better syntax to mark
macros and pseudofunctions then we could use it, on the order of:
pairs[%bins] = label { calc_str($_) } LIST;
pairs[%bins] ,= label { calc_str($_) } LIST;
kv[%bins] = labelkv { calc_str($_) } LIST;
kv[%bins] ,= labelkv { calc_str($_) } LIST;
or some kind of container coercion:
(%bins but Pair) = label { calc_str($_) } LIST;
(%bins but Pair) ,= label { calc_str($_) } LIST;
(%bins but Kv) = labelkv { calc_str($_) } LIST;
(%bins but Kv) ,= labelkv { calc_str($_) } LIST;
My brainstormer module is tired now.
Larry
"@"... :)
> whereas in Perl 6, it'd be nice to be able to say that with all
> the keys and values on the right side somehow.
Shouldn't a simple
%hash = @keys Y @values;
suffice?
I disagree, though, that --except for the case of initializing the hash
together with its declaration-- having the keys on the LHS is bad. It's
actually very good documentation, and to me, much clearer than any of
your examples:
> @bins:[] = label { calc_int($_) } LIST;
> %bins:{} = label { calc_str($_) } LIST;
> @bins.pairs = label { calc_int($_) } LIST;
> %bins.pairs = label { calc_str($_) } LIST;
Which really all are more complex than the initial example:
> map { calc_int($_) => $_ } LIST
Are commas optional after closures?
> %bins.pairs = %bins.pairs, label { calc_str($_) } LIST;
Is , higher precedence than = now?
> %bins.clear.pairs = label { calc_str($_) } LIST;
As someone who hates methods that return the invocant itself (even if
that isn't technically what happens), I have to object. Such combination
doesn't work well in my brain. I'd prefer:
%bins.clear;
%bins.pairs = ...;
Although I think the current situation with simple assignment is still
much better:
%bins = ...;
Juerd
--
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html
http://convolution.nl/gajigu_juerd_n.html
Cool!
This doesn't solve the general case, but how about a left-side zip:
zip( @keys, @values ) = %hash;
zip( @even, @odd ) = 0...;
- Flavio S. Glock
Didn't the list agree long ago on a `part` builtin? I certainly wrote
List::Part based on that discussion...
--
Brent 'Dax' Royal-Gordon <br...@brentdax.com>
Perl and Parrot hacker
In E06:
($cats, $chattels) = part &is_feline, @animals;
How about a "switch" syntax instead?
part @animals {
when .is_feline() { @cats }
default { @chattels }
}
In the more general case:
part @a {
when $_ < 10 { @a }
when $_ < 20 { @b }
when $_ < 30 { @c }
@d
};
and:
@a.part:{
when $_ < 10 { @a }
when $_ < 20 { @b }
when $_ < 30 { @c }
@d
};
- Flavio S. Glock
Eh? The list can agree all it likes, but if a feature ain't in a
file beginning with 'S' somewhere, it ain't specced yet. And offhand
I don't see anything about 'part' in pugs/docs/AES/S29draft.pod...
Yeah, I know...I should just take a evening or two and finish all
the specs myself... :-/
Larry
> If we had some kind of partitioning operator, it'd probably be generalized
> to sorting into bins by number, where 0 and 1 are degenerate cases for
> booleans. But since we'd almost certainly make the general form
>
> (@bin0, @bin1, @bin2...) := classify { calc_int($_ } LIST;
For me it seems to make more sense that in the higher-order scheme
of things classify presents functions to it's body. Instead of
relying on the return value from the body, it gets a number of
functions that it can invoke to append a function.
This is more general since it allows classification to include
duplicates.
Grep is simply:
sub grep (&filter, *@args) {
classify -> $x, &f {
f($x) if filter($x);
} *@a;
}
--
() Yuval Kogman <nothi...@woobling.org> 0xEBD27418 perl hacker &
/\ kung foo master: /me does not drink tibetian laxative tea: neeyah!