Underscore currying in 1.2?

I was wondering what the prospects were of this being resurrected for 1.2. I notice it was on the milestones, but it seemed to me there was a bit of skepticism and I’m not sure what its status is.

I have to admit, I have an irrationally strong desire to have this, and I would probably use it all the time (likely to the point of abuse).

18 Likes

As I understand it:

1.x releases happen on a schedule. (IIRC every 4 months?)
Since at any point in time master both builds and does not contain any breaking changes.
What ever is in master at that point in time, is going to be in 1.x.

This is in contrast to 0.x releases which were basically planned major releases.
Each release was done when all the desired features were done.

As such the question of if X will be in a release is less one of planning,
and more one of what gets done.

BTW: I am also mad keen on that feature.

So is this feature done? or what else need to make it done? I don’t quite get what’s happening now…

1 Like

I instinctively reach for this all the time! Only to remember that it is not available yet :sob:

In short it is more complex than it looks.
Since most solutions have uninutive edge cases.

1 Like

Can anybody distill the essence of whatever was the main objection for me? I don’t exactly feel clear-headed about it after reading the PR thread.

Inability to come to a consensus on what a good rule is for what expression is “consumed by” underscores and becomes the function body.

2 Likes

Looking at the voting on comments on that issue they look pretty unanimous. It’s certainly an awesome idea.

1 Like

I too am irrationally eager to have this. I think it’s especially nice for the simple cases where it streamlines the expression considerably. In the more complicated cases, one might as well use ordinary notation.

I was initially (irrationally? :wink:) eager for this, then after reading about and digesting the corner cases I realized that I would almost always prefer lambdas: for simple cases they work fine, for complex cases I would be scratching my head about corner cases of _ syntax.

1 Like

I think we came to a rough consensus on what the rule should be, but it still needs to be implemented. (The current PR implements a simpler rule, but we decided on something a bit more ambitious to make it easier to use binary/unary operators.) I haven’t gotten around to working on it.

10 Likes

I’m still not sure I understand what the edge cases are that would cause so much ambiguity, but I do think that the way Base and much of the Julia package ecosystem are written promote the tendency to reach for this feature quite often, especially in it’s simplest form. I find myself quite frequently making calls like

findall(myfunction(a, _, c), iter)

or

sort!(x, by=myfunction(_, b))

Unless I’m missing something big, those are not cases that cause much ambiguity, and occur frequently. Those examples look a lot cleaner and more readable than x -> myfunction(a, x) to me. (Not to mention that it’s only it’s not until 1.2 that we get the remaining relational operator currying).

Anyway, if I’m reading the sentiment right, it’s sounding like nobody is entirely opposed to the existence of this feature, so sounds like we’ll have it eventually, even if not in 1.2.

2 Likes

I don’t have much to add here except that I’m also extremely eager to have something like this. I got so used to piping everything in R (which, you may agree or disagree with, but I Love) that I really miss it when I’m working with Julia.

1 Like

I’ve given it a little bit more thought: the only case in which I think I’d get tripped up is nested currying. As in, what is

f(g(_))

I suppose that has to lower to f(g) and not x -> f(g(x)). Still, I can definitely live with that.

Could you summarise what those rules would be, or point to a comment in the issue that summarises them? I haven’t been keeping up and didn’t see in a quick skim.

4 Likes

Basically this comment, plus some subsequent clarifications of edge cases: RFC: curry underscore arguments to create anonymous functions by stevengj · Pull Request #24990 · JuliaLang/julia · GitHub

1 Like

You can cover quite a few cases with a partial function. Then try to write your functions so the thing you most often want to “curry” is first in the parameter list. Which is the case for many functions ( map, reduce, etc ). I also have a swap function if it happens to be in the second position.

partial = (f::Function,y...)->(z...)->f(y...,z...)
# too cheeky?
∂(f::Function,y...) = partial(f,y...)
swap(f::Function) = (a,b...)->f(b...,a)

double = ∂(map, ∂((*), 2))

I’m definitely looking forwards to the _ feature though! Always better to use something standard.

2 Likes

That’s a cool idea. Of course, instead of you could always use the \:curry: (:curry:) emoji :wink:

I couldn’t resist a coding related pun. Also, because friday.

I guess you could say I got curried away.

9 Likes

Has anyone tried Elixir’s way to do short anonymous functions? It looks like &(&1 + &2) for (x,y) -> x+y. So, where the expression stops is pretty explicit.

2 Likes