elves / elvish

Powerful scripting language & versatile interactive shell

Home Page:https://elv.sh/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

New built function: filter

da-tubi opened this issue · comments

How about add a new built-in filter:

fn filter {|pred @rest|
  each {|x|
    if ($pred $x) {
      put $x
    }
  } $@rest
}

If so, I would like an option &not to invert the sense of the test. And perhaps even an option &out (defaulting to $put~) to specify an output function.

Here is my current filter function:

fn filter {|pred~ @items &not=$false &out=$put~|
  var ck~ = $pred~
  if $not { set ck~ = {|item| not (pred $item)} }
  each {|item| if (ck $item) { $out $item }} $@items
}

Here is the scala code snippet of filter and filterNot:

scala> Seq(1, 2, 3).filter(x => x % 2 == 0)
res0: Seq[Int] = List(2)

scala> Seq(1, 2, 3).filterNot(x => x % 2 == 0)
res2: Seq[Int] = List(1, 3)

@hanche

I would like an option &not to invert the sense of the test.

I think you're better off using composable functions instead:

fn fnot {|f| put {|@args| not ($f $@args) }}
fn even {|n| == (% $n 2) 0 }

range 5 | filter (fnot $even~)(num 1)(num 3)

Even better, define a comp function:

fn even {|n| == (% $n 2) 0 }

range 5 | filter (fn:comp $not~ $even~)(num 1)(num 3)

And perhaps even an option &out (defaulting to $put~) to specify an output function.

I think this breaks the pipeline nature of the shell. Again, you can compose things so nicely with pipes:

fn even {|n| == (% $n 2) 0 }
fn exclaim {|s| put $s! }

range 5 | filter (fn:comp $not~ $even~) | each $exclaim~
▶ 1!
▶ 3!

I have had a filter command in my Elvish config for a long time (see https://github.com/krader1961/elvish-lib/):

# Filters a sequence of items and outputs those for whom the function outputs
# $true.
fn filter {|&out=$false func~ @inputs|
    if $out {
        each {|item| if (not (func $item)) { put $item } } $@inputs
    } else {
        each {|item| if (func $item) { put $item } } $@inputs
    }
}

This arguably should be a builtin but only if doing so improves the performance.