56
\$\begingroup\$

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
\$\endgroup\$
24
  • 4
    \$\begingroup\$ @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. \$\endgroup\$ Apr 19, 2017 at 21:42
  • 8
    \$\begingroup\$ @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. \$\endgroup\$ Apr 19, 2017 at 21:49
  • 7
    \$\begingroup\$ @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 \$\endgroup\$
    – Luis Mendo
    Apr 19, 2017 at 21:58
  • 4
    \$\begingroup\$ 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()? \$\endgroup\$ Apr 19, 2017 at 22:08
  • 3
    \$\begingroup\$ 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. \$\endgroup\$
    – CAD97
    Apr 20, 2017 at 7:06

45 Answers 45

1
2
1
\$\begingroup\$

PowerShell, 86 bytes

$f={$n=$args[0];$f=(gv f).value;{if($args){&$f($args[0]+$n)}else{$n}}.getnewclosure()}

Try it online!

Test code:

&(&(&(&(&(&$f 4)2)7)5)2)

Output: 20

\$\endgroup\$
1
  • \$\begingroup\$ 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. \$\endgroup\$ Apr 20, 2017 at 12:57
1
\$\begingroup\$

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

\$\endgroup\$
0
1
\$\begingroup\$

Python, 69 bytes

def f(a=0,s=[]):
    if a:
        return lambda b=0:f(b,s+[a])
    return sum(s)
\$\endgroup\$
2
  • 1
    \$\begingroup\$ I'm assuming this is python? You should state the language used in your answer. \$\endgroup\$
    – corvus_192
    Apr 20, 2017 at 10:13
  • 1
    \$\begingroup\$ Can you try to golf your answer more? As it stands, it's not very well golfed. \$\endgroup\$
    – Riker
    Apr 20, 2017 at 14:23
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
5
  • 1
    \$\begingroup\$ 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} \$\endgroup\$
    – MickyT
    Apr 20, 2017 at 3:42
  • \$\begingroup\$ 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. \$\endgroup\$ Apr 20, 2017 at 10:21
  • \$\begingroup\$ @KonradRudolph The golfed if was laziness, but the return is just for readability - it gives the same result with or without return. \$\endgroup\$
    – BLT
    Apr 20, 2017 at 14:02
  • \$\begingroup\$ @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. \$\endgroup\$ Apr 20, 2017 at 14:03
  • \$\begingroup\$ 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/… \$\endgroup\$
    – BLT
    Apr 20, 2017 at 14:08
1
\$\begingroup\$

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!

\$\endgroup\$
1
\$\begingroup\$

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!

\$\endgroup\$
1
\$\begingroup\$

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)
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

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
\$\endgroup\$
1
\$\begingroup\$

C#, 91 58 bytes

dynamic f(int x)=>(Func<int, dynamic>)(y=>y<1?x:f(x + y));
\$\endgroup\$
1
  • 3
    \$\begingroup\$ You can get rid of some spaces and the public . \$\endgroup\$ Apr 20, 2017 at 8:25
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

Google Sheets, 39

Based on the explanation here

Named functions:

name args body
F a G(0,a)
G a, b IF(b>0,LAMBDA(c,G(a+b,c)),a)

Score: 34 (body text) + 2 (names) + 3 (args) = 39

Example

Termination call arg is any non-positive number:

=F(2)(4)(0)

gives 6.

\$\endgroup\$
0
\$\begingroup\$

Go, 87 bytes

func f(x int)func(int)any{g:=func(y int)any{if y<1{return x+y}
return f(x+y)}
return g}

Attempt This Online!

Stopping value is 0.

This works because the any in Go represents all types, at the expense of every call after the 2nd needing to be cast with .(func(int)any), like f(3)(4).(func(int)any)(0).

\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.