Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Renaming grep

37 views
Skip to first unread message

Ilmari Vacklin

unread,
Nov 17, 2005, 8:31:10 PM11/17/05
to Perl 6 language mailing list
Hi all,

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>

Larry Wall

unread,
Nov 18, 2005, 2:36:33 PM11/18/05
to Perl 6 language mailing list
On Fri, Nov 18, 2005 at 03:31:10AM +0200, Ilmari Vacklin wrote:
: Hi all,

:
: 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).

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

Juerd

unread,
Nov 18, 2005, 2:48:16 PM11/18/05
to Perl 6 language mailing list
Larry Wall skribis 2005-11-18 11:36 (-0800):

> 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.

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

Flavio S. Glock

unread,
Nov 18, 2005, 4:36:05 PM11/18/05
to Perl 6 language mailing list
Larry Wall wrote:
> 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.

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

Brent 'Dax' Royal-Gordon

unread,
Nov 18, 2005, 4:41:33 PM11/18/05
to Perl 6 language mailing list
Larry Wall <la...@wall.org> wrote:
> 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.

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

Flavio S. Glock

unread,
Nov 18, 2005, 9:15:11 PM11/18/05
to Perl 6 language mailing list
2005/11/18, Brent 'Dax' Royal-Gordon <br...@brentdax.com>:

> Larry Wall <la...@wall.org> wrote:
> > 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.
>
> Didn't the list agree long ago on a `part` builtin? I certainly wrote
> List::Part based on that discussion...

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

Larry Wall

unread,
Nov 18, 2005, 9:19:23 PM11/18/05
to Perl 6 language mailing list
On Fri, Nov 18, 2005 at 01:41:33PM -0800, Brent 'Dax' Royal-Gordon wrote:
: Larry Wall <la...@wall.org> wrote:
: > 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.
:
: Didn't the list agree long ago on a `part` builtin? I certainly wrote
: List::Part based on that discussion...

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

Yuval Kogman

unread,
Nov 19, 2005, 5:35:03 AM11/19/05
to Perl 6 language mailing list
On Fri, Nov 18, 2005 at 11:36:33 -0800, Larry Wall wrote:

> 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!

0 new messages