Fix1 (analogue of Base.Fix2)

question

#1

I was very happy to see Base.Fix2 since it saves typing for creating closures.

Would it make sense to introduce a Fix1 that does the same, except for fixing the first argument?


#2

On the other hand, https://github.com/JuliaLang/julia/pull/24990 would turn Fix2(f, x) into f(_, x) and the hypothetical Fix1(f, x) into f(x, _) which I personally like quite a lot.

I guess another question would be whether you want the result of Fix1(f, x) to be y -> f(x, y) as above or the more general (args...) -> f(x, args...) ? Fix2 seems more clear in its purpose, since it assumes that f has exactly two arguments, but it feels odd for Fix1 to make the same assumption.


#3

I don’t remember where I saw the discussion, but last I heard the core devs seemed quite resolved to support general currying with _ as in #24990, just not in 1.0. (I think I remember seeing 1.x, but I don’t want to put words in anyone’s mouth.) So, I have a pretty strong feeling that this is something we’ll have in the not-so-distant future.


#4

I would distinguish

  1. having a parametric type that embodies partial application, eg Fix2 above,

  2. surface syntax for partial application, eg the proposed syntax with _.

(1) exposes the components of what would be an otherwise opaque closure, and allows neat things like a show method for certain function/argument combinations (this is what I want to use it for, actually).

(2) is syntactic sugar.

They can be done independently.


#5

I guess I’m lacking in imagination. Could you give an example of what you have in mind?


#6

Sure, want to make a PR?


#7

Imagine an interface with

loglikelihood(model::SomeModel, parameters)

where SomeModel is a user-defined type.

Now with

loglikelihood(model) = Fix1(loglikelihood, model) # hypothetical

function Base.show(io::IO, l::Fix1{typeof(loglikelihood), M}) where M
    println(io, "log likelihood callable for model $(l.x)")
end

one could do custom printing.


#8

Yes, will make on tomorrow.


#9

Note that this is already planned. See e.g. https://github.com/JuliaLang/julia/pull/26436#issuecomment-373490587


#10

PR done:


#11

Merged.


#12

Would it make sense to go in the direction of C++ std::bind (see examples section)?