Skip to content

Instantly share code, notes, and snippets.

@0racle
Last active March 23, 2020 00:54
Show Gist options
  • Save 0racle/ea0523759e2da15758d4 to your computer and use it in GitHub Desktop.
Save 0racle/ea0523759e2da15758d4 to your computer and use it in GitHub Desktop.
where is grep

One of Larry's purported factors in the design of Camelia (and by extension, Perl 6) was to appeal to 7 year old girls (and by extension, people new to programming in general).

In addition, another design principle of Perl6 was to make it "less Unix centric". Whereas Perl had s/// and tr///, Perl 6 retains these but adds subst and trans, which is friendlier to new programmers, and self-documenting to some degree.

It seems odd, then, that we still have the grep operator named so. Even in Perl, grep - as in globally search a regular expression and print - bears little resemblance to what it actually does. It's more of a filter, filtering elements out that do not evaluate True to a given expression.

What then would be it's alternative friendly name? Taking into account these design principles...

  • Context Sensitive: A term or symbol might do different things in different context
  • Maximum reuse: Syntax and concepts are reused wherever possible to minimize the stuff you have to remember

I propose where.

This make a lot of sense when you consider how similar a grep expression is to the context that where is currently used (in defining a subset).

Here's a demonstration to highlight the similarities

> (^10).grep(* %% 2) 
(0 2 4 6 8)
> subset Even of Int where * %% 2;
> (^10).grep(Even)
(0 2 4 6 8)
> my Int $even where * %% 2
> (^10).grep($even)
(0 2 4 6 8)
> 

Here it becomes very clear. The * %% 2 expression appears directly after both grep and where. Contextually they are similar. We can also give a subset to grep and it does as expected. Conceptually they are almost identical.

Here's some hypothetical code that uses a newly named where method that aliases grep.

my @even = @numbers.where(* %% 2)
my @prod = @servers.where(*.status eq 'Production')
my @matches = @data.where(/pattern/)

Please note, I'm not advocating for the removal of grep at all... I'm proposing an additional nickname for it. One more relevant, logical, and friendly to new (all?) programmers, including 7 year old girls.

Update - 2016-03-31 : Module!

This is now a (kind of) fully fledged module in the ecosystem.

https://github.com/0racle/p6-wig

Update - 2016-04-04 : Prior Art

Some prior art on the use of the word where to filter a list

Powershell

$evens = 0..10 | Where { $_ % 2 -eq 0 }

C#

int[] evens = array.Where(i => (i % 2) == 0).ToArray();

SQL

SELECT v INTO #evens FROM #nos WHERE v % 2 = 0

Haskell

import Data.Array
ary = listArray (1,10) [1..10]
evens = listArray (1,n) l where
  n = length l
  l = [x | x <- elems ary, even x]

Dart

numbers.where((i) => i.isEven);

Interesting to note, when looking at Filter - Rosetta Code, the only examples that have a grep operator are UNIX shell, Perl, and Sidef ( a language implemented in perl5 ).

@MattOates
Copy link

I think given you used the verb filter in your description that fits even better. Where feels a lot more control flowy to me like if. In Perl 6 where clauses data isn't being filtered flow of execution is. Also this is the most bike sheddy of bike sheds. A 7 year old girl is likely to come across Unix in school thanks to stuff like Raspberry Pi >:3

@0racle
Copy link
Author

0racle commented Mar 24, 2016

Thanks for your comments, Matt. I think we often overlook terms like grep that seem so common to us. As a network engineer I work with teams of people who work in a terminal all day; they SSH into a Linux jump box and then SSH or telnet to managed network gear. Most of them don't know what grep is/does/means.

I understand this is a glorious bike shed. I was just trying to make my point using design principles, ideals, and goals that define Perl 6.

@0racle
Copy link
Author

0racle commented Mar 30, 2016

I was not online when this happened, but this discussion supports my point.
http://irclog.perlgeek.de/perl6/2016-03-30#i_12259953

MadcapJake often doesn't think to use grep because it's not a known/common term for him. What follows is a discussion of certain terminology in Perl 6. Some quotes from the discussion...

MadcapJake teatime: There's been a few things [...] jarring for an outsider like myself: grep [...]

MadcapJake [...] it's partly just the name that makes it tough for me to remember to use it, I look at the problem and say "I want to filter this" not "I want to grep this"

teatime .grep in perl is kindof a misnomer;
teatime .filter would have probably been my choice, and I *am* a unix nerd.

* jnthn is glad we got something a bit shorter than filter, without having to abbreviate :)

@pprince
Copy link

pprince commented Mar 30, 2016

Since I was quoted as a .filter() supporter, I'd like to put it on record that I no longer support .filter() and would instead vote for adding .where() (and keeping .grep()).

(It was pointed out that .filter() is logically inverted in various languages.)

@0racle
Copy link
Author

0racle commented Mar 31, 2016

It is born: https://github.com/0racle/p6-wig
PR's/suggestions welcome!

Also... I just wanted to put this here, because it means a lot coming from such a legend of the perl community

lizmat : fwiw, I like the idea of "where" instead of "grep" - Source

@AlexDaniel
Copy link

Oh, there's a gist!

I'll quote myself:

<AlexDaniel> I'd love to see some alternative to “grep”. Just so that I don't have to explain what grep is to non-unixers

Meaning that “.where” or even “.filter” is much better for teaching purposes. That being said, I don't like that the word “where” will have two different meanings (and I don't really buy the idea that these are somewhat similar). In perl, different things are written differently, so I'd be happy to see it this way. But “filter” is not any better at all.

Any other alternatives? What about “grab”?

@AlexDaniel
Copy link

@0racle
Copy link
Author

0racle commented Apr 4, 2016

This idea of this in core is over for now. TimToady ruled against it...

TimToady | I really don't think we're changing anything here; 'where' in particular has
         | no current auto-iterative meaning, it's only used where something external is
         | looking for a boolean smartmatch, so that would be confusing to overload

I still like my suggestion, and at the least, it started a discussion which showed there is a desire for an alternate name. However it seems to have caused more fallout than I was prepared for.

I just wanted to put down a few remaining thoughts...

I updated the top post with some prior art, just to show that the use of where in this context is not unheard of.

To those who also liked my suggestion, I say thanks for making me feel a little less weird. Specifically, I want to thank lizmat for her support and kind words.

Thanks also to Larry for Perl. I was a late comer to perl5 (only a couple years ago) and I love it dearly.

Without a love of perl5 I might have been one of those people who dismissed Perl 6 off-hand, and subsequently would have missed out on what an utterly enjoyable language it is to use. Thanks to all those working on Perl 6 and it's ecosystem. I am exited for the future of Perl 6.

I hope the augment/precomp issues can be ironed out soon so that ideas like this can live better lives in the module ecosystem.

In the meantime, I still have a version in rakudobrew with this this idea built into core that I can fire up occasionally and reminisce about that time I almost changed Perl 6 fundamentally {[: )

@trosel
Copy link

trosel commented Feb 21, 2017

filter has become a standard of sorts, but it is a misnomer because one does not know if the boolean should apply to what you're keeping or what you're filtering out.

my @nums = (^10).filter(* %% 2)

Am I keeping even numbers or rejecting them? This is the natural English thought, to me at least.

my @nums = (^10).grep(* %% 2)

grep has the same issue as filter for me. Compounded by the fact that it isn't even a recognizable English word.


For this reason, I like keep and reject.

my @nums = (^10).keep(* %% 2)

There is no doubt that @nums contain even numbers.

my @nums = (^10).reject(* %% 2)

Again, there is no doubt that @nums contain odd numbers.


Having said that, Perl6's gather/take functionality is fairly similar and quite clear. It's just a very new system to a lot of people.

my @nums = gather for ^10 { take if $_ %% 2 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment