# Improve currying in Julia Base

**URL:** <https://discourse.julialang.org/t/improve-currying-in-julia-base/61652>\
**Category:** Internals & Design\
**Tags:** proposal\
**Created:** [May 22, 2021, 5:29pm UTC](https://discourse.julialang.org/t/improve-currying-in-julia-base/61652 "2021-05-22T17:29:43Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)\
**Post date:** [May 22, 2021, 5:29pm UTC](https://discourse.julialang.org/t/improve-currying-in-julia-base/61652/1 "2021-05-22T17:29:43Z")

</div>

Before opening an issue on Julia GitHub I would like to ask two things (as I might have missed the relevant discussions - I could find some issues that are related but not something directly the same).

### Question 1.

Many functions allow an optional function as a fists argument, e.g. `sum`, `any`, `maximum`, etc.  
The question is if it would be acceptable to add the following definitions in Julia Base (I am giving one example):

```julia-auto
sum(f::Function) = Base.Fix1(sum, f)

```

### Question 2

Are there any plans for exposing `Base.Fix1` to users (possibly with some nicer syntax/name). If this were provided then Question 1 would be obsolete as one could just use the syntax to get what is intended (assuming the syntax would be easy enough).

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [May 22, 2021, 5:41pm UTC](https://discourse.julialang.org/t/improve-currying-in-julia-base/61652/2 "2021-05-22T17:41:00Z")

</div>

In almost all cases it’s fine to write

```julia
f(x) = y -> f(x, y)

```

There’s very little reason to export `Base.Fix1` / `Fix2` when anonymous functions exist. There are a couple of packages out there like [FixArgs.jl](https://github.com/goretkin/FixArgs.jl) and [ChainedFixes](https://github.com/Tokazama/ChainedFixes.jl) that generalize `Fix1` and `Fix2` to the `N`th argument when such a thing is needed.

If something like [RFC: curry underscore arguments to create anonymous functions by stevengj · Pull Request #24990 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/24990) were ever accepted, and if it was the version that only ever consumes one function call, then perhaps it should produce a `FixN` like type.

> [@bkamins](#):
>
> The question is if it would be acceptable to add the following definitions in Julia Base (I am giving one example):
> 
> ```julia
> sum(f::Function) = Base.Fix1(sum, f)
> 
> ```

I think this is kinda a bad idea because it makes it so that `sum(x)` has a very different semantic meaning depending on whether `x::Function` or not, plus not all callable objects are `<: Function`. However, it’s not a terrible thing.

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [May 22, 2021, 5:41pm UTC](https://discourse.julialang.org/t/improve-currying-in-julia-base/61652/3 "2021-05-22T17:41:22Z")

</div>

For question 2, they were added to the manual recently ([Essentials · The Julia Language](https://docs.julialang.org/en/v1.7-dev/base/base/#Base.Fix1)) in [https://github.com/JuliaLang/julia/pull/36094](https://github.com/JuliaLang/julia/pull/36094), so they are at least part of the public API now, but they don’t have a nicer name/syntax and are not exported.

---

<div class="post-metadata">

**Author:** ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)\
**Post date:** [May 22, 2021, 6:01pm UTC](https://discourse.julialang.org/t/improve-currying-in-julia-base/61652/4 "2021-05-22T18:01:08Z")

</div>

Thank you for sharing these points. Let me give some more perspective of my question:

> [@Mason](#):
>
> There’s very little reason to export `Base.Fix1` / `Fix2` when anonymous functions exist.

AFACIT `Fix1` and `Fix2` exist exactly because anonymous functions are not a good solution in many cases. You can dispatch on `Fix1` and `Fix2`, but you cannot on anonymous function which is a crucial problem (and the reason of my question). If you write a package (like DataFrames.jl) that wants to be efficient you often want to have a special code for common operations. Essentially what I need is to be able to intercept signature like:

```julia
Base.Fix1{typeof(sum), T}) where {T}

```

and run a fast code on it. While with using an anonymous function it is not possible.

For this reason [RFC: curry underscore arguments to create anonymous functions by stevengj · Pull Request #24990 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/24990) in its current state is not good for me (but if it produced FixN it would be OK).

I was aware of the packages, but I would prefer not to add more dependencies to DataFrames.jl if I could avioid this.

Additionally apart from dispatch benefits `Fix1` and `Fix2` reduce compilation latency, as most DataFrames.jl usage by regular is happening in global scope and defining anonymous functions causes recompilation on each call even if the operation is the same as already executed in the same session.

> that `sum(x)` has a very different semantic meaning depending on whether `x::Function` or not

Good point. It is clearly bad.

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [May 22, 2021, 6:01pm UTC](https://discourse.julialang.org/t/improve-currying-in-julia-base/61652/5 "2021-05-22T18:01:42Z")

</div>

> [@Mason](#):
>
> not all callable objects are `<: Function` .

This seems very significant to me. Regardless of whether this change is implemented, I would think the right way to do it is using a `Callable` trait instead of specializing on `::Function`.

---

<div class="post-metadata">

**Author:** ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)\
**Post date:** [May 22, 2021, 6:07pm UTC](https://discourse.julialang.org/t/improve-currying-in-julia-base/61652/6 "2021-05-22T18:07:00Z")

</div>

> [@jzr](#):
>
> a `Callable` trait instead of specializing on `::Function` .

Not all callable objects are `<:Callable`. So this will not resolve this. I used `Function` as in DataFrames.jl I prefer to stick to this as functions are not specialized on `Function` if it is passed through them, while if you allow e.g. `Callable` some specialization happens even with `@nospecialize` and it leads to excessive compilation latency unfortunately.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [May 22, 2021, 6:07pm UTC](https://discourse.julialang.org/t/improve-currying-in-julia-base/61652/7 "2021-05-22T18:07:46Z")

</div>

> [@bkamins](#):
>
> AFACIT `Fix1` and `Fix2` exist exactly because anonymous functions are not a good solution in many cases. You can dispatch on `Fix1` and `Fix2` , but you cannot on anonymous function which is a crucial problem (and the reason of my question). If you write a package (like DataFrames.jl) that wants to be efficient you often want to have a special code for common operations. Essentially what I need is to be able to intercept signature like:

Right, what I meant was that for _most_ people in _most_ circumstances, `Fix1` and `Fix2` do not confer any benefit over anonymous functions. The internals of Julia itself and DataFrames.jl however are somewhat unusual circumstances where these objects can be of benefit.

I didn’t mean to say that these are useless, just that they’re not necessarily the sort of thing `Base` should be exporting.

> [@bkamins](#):
>
> Not all callable objects are `<:Callable` . So this will not resolve this.

I think @jzr is talking about a hypothetical `Callable` trait that can detect if an object has methods, not the current flimsy thing sitting in `Base` as `Base.Callable`.

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [May 22, 2021, 6:11pm UTC](https://discourse.julialang.org/t/improve-currying-in-julia-base/61652/8 "2021-05-22T18:11:04Z")

</div>

> [@Mason](#):
>
> I think @jzr is talking about a hypothetical `Callable` trait, not the current flimsy thing sitting in `Base` as `Base.Callable` .

Yep.

---

<div class="post-metadata">

**Author:** ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)\
**Post date:** [May 22, 2021, 6:11pm UTC](https://discourse.julialang.org/t/improve-currying-in-julia-base/61652/9 "2021-05-22T18:11:40Z")

</div>

> [@Mason](#):
>
> I didn’t mean to say that these are useless, just that they’re not necessarily the sort of thing `Base` should be exporting.

Sure, I just wanted to give more explanation of the reason why I asked. In short:

1. people want DataFrames.jl to be fast
2. people are using DataFrames.jl functions in global scope passing custom functions as transformations.
3. people care a lot about compilation latency (as now in most cases we are at the level of speed where most of the time is spent in compilation for MB sized data and not on doing actual computation)

> I think @jzr is talking about a hypothetical `Callable` trait that can detect if an object has methods

Ah - then it would cover it, but probably still it would not be handled by `@nospecialize` as I would want it to be.
