Why are there no curried versions of map & filter?

I’ve written the following code today:

branches = filter(strip.(readlines(`git branch --merged`))) do branch
    branch != "master" && !startswith(branch, '*')
end

It’s OK, but I’d love to be able to write

branches = readlines(`git branch --merged`)
    .|> strip
    |> filter(branch -> branch != "master" && !startswith(branch, '*'))
end

as it reads better (reading order corresponds to evaluation order and “how I think about this” order).

I think that would be possible if Base provided a single-argument version of a filter function. I know I can add this myself, but I wonder why it isn’t provided out of the box?

Are there some performance concerns with returning partially-applied functions? Or is it just not what idiomatic Julia looks like?

Maybe a macro can help

using Lazy: @>>

branches = @>> readlines(`git branch --merged`) begin
    x->strip.(x)
    filter(brach -> branch != "master" && !startswith(branch, '*'))
end
julia> Base.filter(f::Function) = Base.Fix1(filter, f)
julia> Base.filter(iter) = Base.Fix2(filter, iter)
julia> [1,2,3] |> filter(isodd)
2-element Array{Int64,1}:
 1
 3
julia> isodd |> filter([1,2,3])
2-element Array{Int64,1}:
 1
 3

It’s certainly easy to implement. I don’t know if there’s any reason not to do it, but I think it would be a useful option to have.

3 Likes

Thanks for the Fix1 and Fix2 !!!

1 Like

Also see https://github.com/JuliaLang/julia/issues/35293. The problem, at least with map, is that map(f) already does something.

3 Likes

Since you’re not just piping but also constructing an anonymous function for filter, you may like this package:

using Underscores

branches = @_ readlines(`git branch --merged`)) .|> strip |> 
	filter(_ != "master" && !startswith(_, '*'), __)