# Arbitrary-length currying

Write a function, f, that takes in a positive integer and returns a function.

The new function returned should be identical to f. However, when the "termination call" happens, f should instead return the sum of all integers passed.

For example, g=f(4) (if f is the first function) should set g to another function. h=g(3) will do the same. However, when you call h with no arguments (see below for details), it should output 7, as that is the sum of the previous function arguments. Put another way, f(3)(4)() == 7.

Do note this is not the same as f(3,4)().

"Termination call" is one of the following options (your choice):

• call w/o arguments
• null as argument
• any non-positive value

Arbitrary amount of function calls should be supported, there is no predefined limit.

It's guaranteed that total sum will not be bigger than 1'000.

We can assume that there is at least one call is made prior to "termination call".

Your code should not use static, per-program variables, so it should be possible to run the experiment multiple times in the same runtime and observe exactly the same behavior.

Examples:

f(1)() == 1
f(4)(2)(7)() == 13
f(4)(2)(7)(5)(2)() == 20

• @LuisMendo It generally means that f(4) returns a new function. If that new function is called without arguments, it returns 4, but if it's called with another argument then it will again return a new function with the same semantics but with the new argument added to the 4 and so on. Apr 19, 2017 at 21:42
• @LuisMendo It's indeed up to Eugene, but I think that allowing repeated calls would significantly take away from the challenge, because the interesting part isn't to make a stateful function but to make a higher-order function. Apr 19, 2017 at 21:49
• @MartinEnder That makes a lot of sense. Eugene, if that's the intent, please change the wording of the challenge. Write a function that can be infinitely called doesn't suggest at all that the function shoud return a function Apr 19, 2017 at 21:58
• Can we assume that there will only be one instance of the call chain at a time? E.g. No q = f(2)(3); b = f(1)(2)(3); q(); b()? Apr 19, 2017 at 22:08
• Having just recently picked up Haskell, I'm interested in whether this is possible in Haskell. The strong type system makes me think it might not be. Apr 20, 2017 at 7:06

## 43 Answers

PowerShell, 86 bytes

$f={$n=$args[0];$f=(gv f).value;{if($args){&$f($args[0]+$n)}else{$n}}.getnewclosure()}  Test code: &(&(&(&(&(&$f 4)2)7)5)2)


Output: 20

• Very nice. Welcome to PPCG! You can save a byte by doing $n="$args" instead of $n=$args[0]. It won't work on the other $args[0], though, because then you'll get string concatenation rather than addition. Apr 20, 2017 at 12:57 # Python 3, 63 bytes f=lambda n,l=[]:n and(l.append(n)or f)or sum(l)*(l.clear()or 1)  Try it online! Terminates with 0 # Python, 69 bytes def f(a=0,s=[]): if a: return lambda b=0:f(b,s+[a]) return sum(s)  • I'm assuming this is python? You should state the language used in your answer. Apr 20, 2017 at 10:13 • Can you try to golf your answer more? As it stands, it's not very well golfed. Apr 20, 2017 at 14:23 # Octave, 39 bytes function r=f(n)r=@(m)merge(m,f(m+n),n);  *Argument of the termination call is 0. Try it online! *endfunction required to add some other codes. ## R, 54 52 bytes f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g}  Saved 2 bytes thanks to MickyT! Similar to one of the python answers. Ungolfed: f=function(x){ g=function(y=''){ if(y>''){ f(y+x) } else{x} } g }  Runs as > f(1)(2)(4)() [1] 7  • Nice work. You can get rid of the internal braces around the if clause. f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g} Apr 20, 2017 at 3:42 • I’m a bit puzzled why your “ungolfed” version has return. return in R isn’t the same as in other languages, it performs a premature abort. Not using return is idiomatic. On the other hand your ungolfed version still has the golfed if. Apr 20, 2017 at 10:21 • @KonradRudolph The golfed if was laziness, but the return is just for readability - it gives the same result with or without return. – BLT Apr 20, 2017 at 14:02 • @BLT Hm. I feel strongly that gratuitous in R return decreases readability because it signals the wrong thing (premature exit) and is an instance of cargo cult programming. Apr 20, 2017 at 14:03 • Cool, I learned something new again. That's one reason I keep coming back. Thanks @KonradRudolph, also this Stack Overflow question is interesting: stackoverflow.com/questions/11738823/… – BLT Apr 20, 2017 at 14:08 # Lua, 89 bytes function f(...)n,p=...p=p or 0 return n and loadstring("return f(...,"..n+p..")")or p end  Well it's not exactly the shortest I see (Lua never is), but it was an interesting challenge. Had a lot of attempted arithmetic on a function and attempted to call a number along the way before the aha moment. As a slight bonus though, it does work with non-positive numbers since nil and false are the only false values in Lua. In many golfing challenges, 0 ~= false is a drawback but not here! # C++ (gcc), 95 91 bytes struct f{int s;f(int t):s(t){}int operator()(){return s;}f operator()(int t){return s+t;}};  Try it online! ## Clojure, 29 bytes (defn f[n]#(if %(f(+ n %))n))  Example: (for [f (->> [3 2 1 4 10] (reductions (fn [f val] (f val)) f) rest)] (f nil)) (3 5 6 10 20)  # k, 22 bytes Call with a null value to terminate {$[^y;+/x;.z.s[y,x]@]}


Example:

k)f:{$[^y;+/x;.z.s[y,x]@]} k)g:f[3] k)h:g[4] k)h[0N] //0N is null integer in k 7  C#, 53 bytes Func<int,dynamic>f(int i)=>m=>m<0?(dynamic)i:f(m+i);  Any negative number can act as the stop value int j = f(5)(3)(4)(-1); // j = 12 int j = f(-1); // Compile Error, must be 2 or more calls  # C#, 91 58 bytes dynamic f(int x)=>(Func<int, dynamic>)(y=>y<1?x:f(x + y));  • You can get rid of some spaces and the public . Apr 20, 2017 at 8:25 # Attache, 20 bytes {If[_,$&Sum[__],_2]}


Try it online!

## Explanation

{If[_,$&Sum[__],_2]} { } lambda, taking parameters stored in __ If[_, ] If the first parameter _ is truthy (nonzero):$                    return this function
&                   bonded with
Sum[__]            the current running sum
,        otherwise:
_2         return the sum


Since (f&n)[x] is equivalent to f[x, n], this will continue returning itself with the updated sum until n = 0.

If you want computation to occur after the final 0, then one could do this for 28 bytes:

{If[_,Fold[&,$'__],Sum!__]}  This is much the same thing, except we use Fold[&,$'__] to bond \$ with each individual argument.

# Nim, 135 bytes

import sugar
type X=object
case t:int8
of 0:i:int
else:f:int->X
func s(x:int):int->X=(y:int)=>(if y<0:X(t:0,i:x)else:X(t:1,f:s x+y))


Try it online!

Like the JavaScript answer, but with type safety.