Live data from Hacker News

A case against currying

emi-h.com

81–90 of 135 posts

Re: A case against currying

#81
post #78

Earlier quoted context omitted.

As noted in the article: > This feature does have some limitations, for instance when we have multiple nested function calls, but in those cases an explicit lambda expression is always still possible. I've also complained about that a while ago https://news.ycombinator.com/item?id=35707689 --- The solution is to delimit the level of expression the underscore (or dollar sign suggested in the article) belongs to. In Ko…

I think I like the explicit lambda better; I prefer to be judicious with syntactic sugar and special variable names. fun x => add(subtract(x, 2), 3) // Virgil

Coming from Scala to Kotlin, this is what I thought as well. Seeing `it` felt very wrong, then I got used to it.

Re: A case against currying

#82
post #80

Earlier quoted context omitted.

Let us postulate two functions. One is named foobinade, and it takes three arguments. The other is named foobinadd, and it only takes two arguments. (Yes, I know, shoot anybody who actually names things that way.) When someone writes f = foobinade a b g = foobinadd c d there is no confusion to the compiler. The problem is the reader . Unless you have the signatures of foobinade and foobinadd memorized, you have no wa…

> Unless you have the signatures of foobinade and foobinadd memorized, you have no way to tell that f is a curried function and g is an actual result. Yes, but the exact FP idea here is that this distinction is meaningless; that curried functions are "actual results". Or rather, you never have a result that isn't a function; `0` and `lambda: 0` (in Python syntax) are the same thing. It does, of course, turn out that…

Fine, it's a regular type. It's still not the type I think it is. If it's an Int -> Int when I think it's an Int, that's still a problem, no matter how much Int -> Int is an "actual result".

Re: A case against currying

#83
post #56

I couldn't agree more. Having spent a lot of time with a language with currying like this recently, it seems very obviously a misfeature. 1. Looking at a function call, you can't tell if it's returning data, or a function from some unknown number of arguments to data, without carefully examining both its declaration and its call site 2. Writing a function call, you can accidentally get a function rather than data if…

> I think programming languages have a tendency to pick up cute features that give you a little dopamine kick when you use them, but that aren't actually good for the health of a substantial codebase.

That's not the case with Haskell.

Haskell has a tendency to pick up features that have deep theoretical reasoning and "mathematical beauty". Of course, that doesn't always correlate with codebase health very well either, and there's a segment of the community that is very vocal about dropping features because of that.

Anyway, the case here is that a superficial kind of mathematical beauty seems to conflict with a deeper case of it.

Re: A case against currying

#84
> curried functions often don't compose nicely

Same for imperative languages with "parameter list" style. In python, with

def f(a, b): return c, d

def g(k, l): return m, n

you can't do

f(g(1,2))

but have to use

f(*g(1,2))

what is analogical to uncurry, but operate on value rather than function.

TBH I can't name a language where such f(g(1,2)) would work.

Re: A case against currying

#85
post #80

Earlier quoted context omitted.

Let us postulate two functions. One is named foobinade, and it takes three arguments. The other is named foobinadd, and it only takes two arguments. (Yes, I know, shoot anybody who actually names things that way.) When someone writes f = foobinade a b g = foobinadd c d there is no confusion to the compiler. The problem is the reader . Unless you have the signatures of foobinade and foobinadd memorized, you have no wa…

> Unless you have the signatures of foobinade and foobinadd memorized, you have no way to tell that f is a curried function and g is an actual result. Yes, but the exact FP idea here is that this distinction is meaningless; that curried functions are "actual results". Or rather, you never have a result that isn't a function; `0` and `lambda: 0` (in Python syntax) are the same thing. It does, of course, turn out that…

> Yes, but the exact FP idea here is that this distinction is meaningless; that curried functions are "actual results".

Everyone knows that. At least everyone who would click a post titled "A case against currying." The article's author clearly knows that too.

That's not the point. The point is that this distinction is very meaningful in practice, as many functions are only meant to be used in one way. It's extremely rare that you need to (printf "%d %d" foo). The extra freedom provided by currying is useful, but it should be opt-in.

Just because two things are fundamentally equivalent, it doesn't mean it's useless to distinguish them. Mathematics is the art of giving the same name to different things; and engineering is the art of giving different names to the same thing depending on the context.

Re: A case against currying

#88
post #80

Earlier quoted context omitted.

> Unless you have the signatures of foobinade and foobinadd memorized, you have no way to tell that f is a curried function and g is an actual result. Yes, but the exact FP idea here is that this distinction is meaningless; that curried functions are "actual results". Or rather, you never have a result that isn't a function; `0` and `lambda: 0` (in Python syntax) are the same thing. It does, of course, turn out that…

Fine, it's a regular type. It's still not the type I think it is . If it's an Int -> Int when I think it's an Int, that's still a problem, no matter how much Int -> Int is an "actual result".

Come on, just write

    let f :: Int = foobinade a b
And the compiler immediately tells you that you are wrong: your type annotation does not unify with compiler’s inferred type.

And if you think this is verbose, well many traditional imperative languages like C have no type deduction and you will need to provide a type for every variable anyways.

Re: A case against currying

#89
post #80

Earlier quoted context omitted.

Let us postulate two functions. One is named foobinade, and it takes three arguments. The other is named foobinadd, and it only takes two arguments. (Yes, I know, shoot anybody who actually names things that way.) When someone writes f = foobinade a b g = foobinadd c d there is no confusion to the compiler. The problem is the reader . Unless you have the signatures of foobinade and foobinadd memorized, you have no wa…

> Unless you have the signatures of foobinade and foobinadd memorized, you have no way to tell that f is a curried function and g is an actual result. Yes, but the exact FP idea here is that this distinction is meaningless; that curried functions are "actual results". Or rather, you never have a result that isn't a function; `0` and `lambda: 0` (in Python syntax) are the same thing. It does, of course, turn out that…

If 0 and a function that always returns 0 are the same thing, does that make `lambda: lambda: 0` also the same? I suppose it must do, otherwise `0` and `lambda: 0` were not truly the same.

Re: A case against currying

#90
post #80

Earlier quoted context omitted.

Let us postulate two functions. One is named foobinade, and it takes three arguments. The other is named foobinadd, and it only takes two arguments. (Yes, I know, shoot anybody who actually names things that way.) When someone writes f = foobinade a b g = foobinadd c d there is no confusion to the compiler. The problem is the reader . Unless you have the signatures of foobinade and foobinadd memorized, you have no wa…

> Unless you have the signatures of foobinade and foobinadd memorized, you have no way to tell that f is a curried function and g is an actual result. Yes, but the exact FP idea here is that this distinction is meaningless; that curried functions are "actual results". Or rather, you never have a result that isn't a function; `0` and `lambda: 0` (in Python syntax) are the same thing. It does, of course, turn out that…

It’s not at all clear or the same to the new reader of the code.
Post reply on HN