28

Haskell curries its functions. Clojure does not though it permits partial and function macros as a comparable approach for doing the same.

I thought I recalled hearing/reading the reason behind Hickey's decision. Does someone recall what that reason was or where I could find it?

I was hoping to learn something from the rationale.

Mario
  • 6,572
  • 3
  • 42
  • 74
  • 1
    I assume at least part of the reason is Clojure is not 100% lazy and application cannot be deferred – guilespi Jul 13 '15 at 00:08
  • 3
    Your first sentence is not accurate. Haskell curries *all* functions, no matter how many arguments are supplied. In truth, all Haskell functions take one input and return one output. https://wiki.haskell.org/Currying https://wiki.haskell.org/Composing_functions_with_multiple_values . In Haskell the **uncurry** function doesn't actually uncurry; instead, it takes the first two functions in the chain and composes them into one function which takes a **pair** as its single input. – itsbruce Jul 13 '15 at 11:47
  • 3
    paying homage to Haskell Curry. – rem Jul 13 '15 at 12:42
  • 4
    I'm pretty sure this is because java functions can be polyvariadic (having variable argument numbers), so clojure should follow suit. – AJF Jul 13 '15 at 22:26
  • In short, fixed-parameter functions are well-suited to auto-currying while multi-arity functions are not. Thus, when you develop an api, if you want auto-currying, avoid the latter and prefer the former. – Mario Jul 09 '18 at 19:32
  • Seems like this would've been a bug inducing feature because of Clojure's dynamic nature. – raianmr Jul 17 '23 at 06:36

1 Answers1

28

As functions can have multiple arities, you could have a direct function call instead of a currying function. Next, if in case you have only one arity, and you miss an argument, arity error is not detected and instead generate a currying function. A very bad and hard case to debug, especially if the function returns a function with the same asked arity, or if function is passed as an argument to another function.

So specifically creating a currying function seems legit.

Ivan Pierre
  • 808
  • 7
  • 9
  • 3
    I was working on a bit Clojure inspired code and trying to make currying and variadic functions work in tandem and I had discovered the same problems you mention. It's reaffirming to hear it from you. – Mario Jul 13 '15 at 01:38
  • 5
    To give a concrete example for posterity and for people who don't necessarily know what "arities" are, you need `(+ 1 2)` to simultaneously be `3` and a composable function because you're asking for both `(print (+ 1 2))` to put `3` to the console (normal evaluation), and `((+ 1 2) 3)` to be an expression yielding `6` (currying). Ways we know that do both (e.g. "Church numerals") tend to fail on expressions like `((* 1 2) 3)` also being `6`. – CR Drost Jul 13 '15 at 03:39
  • 5
    whereas in haskell a function's arity is statically-known part of its type (e.g. `f :: Int -> (Int -> (Int -> Int))`), and at each stage of partial application the type checker tracks its type (e.g. `f 41 42 :: Int -> Int`) – jberryman Jul 13 '15 at 14:40