Arbitrary-length currying

53

3

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

Eugene D. Gubenkov

Posted 2017-04-19T19:08:30.183

Reputation: 657

Can we require a specific non-positive value as the terminator? – Tutleman – 2017-04-19T20:55:20.800

@Tutleman, not sure what it would lead to, let's say any non-positive should be OK to terminate the chain if this option is choosen – Eugene D. Gubenkov – 2017-04-19T20:58:52.637

I don't understand what is being asked here. Can you ellaborate or clarify? What does the notation f(4)(2)(7)() mean? – Luis Mendo – 2017-04-19T21:40:01.943

4@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. – Martin Ender – 2017-04-19T21:42:40.777

@LuisMendo, it means 4 function calls, arguments on first 3 should be summed, because the forth call is "terminating" – Eugene D. Gubenkov – 2017-04-19T21:42:49.660

@MartinEnder Thanks. So does the code need to return a function, or is that just one possible approach? Can it be a function with a "persistent" variable, such that the same function is called several times? This question is more for Eugene I guess – Luis Mendo – 2017-04-19T21:47:28.603

6@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. – Martin Ender – 2017-04-19T21:49:04.830

6@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 – Luis Mendo – 2017-04-19T21:58:41.740

4Can 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()? – Conor O'Brien – 2017-04-19T22:08:22.613

Are functors allowed? – Steadybox – 2017-04-19T23:26:11.273

Apologies, I am not sure I understand. I have a 'plus over' function in k +/ ---- so +/[1 2 3] returns 6, is this incorrect? Do the arguments need to be (1)(2)(3)() - with parentheses AND a null terminator? What is the significance of the null terminator? If it isn't present should the function do nothing?? – Chromozorz – 2017-04-19T23:31:19.970

@EugeneD.Gubenkov Let me know when you clarify the above (whether the function should return a function or simply have memory across calls), so that I can remove my downvote – Luis Mendo – 2017-04-19T23:36:27.340

2@Chromozorz the significance is currying and higher-order functions. I think a better title would be "Arbitrary-length Currying". – Brian McCutchon – 2017-04-20T01:55:17.243

@LuisMendo, Please check out the updated description -- should be more precise now. – Eugene D. Gubenkov – 2017-04-20T06:19:24.547

Arbitrary amount of function calls should be supported I believe some environment won't able to handle more than 1000 recursive call. It will simply throw StackOverflow error. – Thariq Nugrohotomo – 2017-04-20T06:24:49.447

1@ThariqNugrohotomo, let's go with 1000 as maximum sum, it is not critical to the spirit of the challenge – Eugene D. Gubenkov – 2017-04-20T06:37:12.387

3Having 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. – CAD97 – 2017-04-20T07:06:13.887

I have some questions here. We can't use static storage so this function obviously needs some dynamically allocated buffer space. Does f() itself need to take care of that? Can f() take an additional parameter to a pre-allocated buffer? What about stack allocation? That has to be done (and eventually cleaned up) by the caller. – user5434231 – 2017-04-21T02:02:54.617

@CAD97 - I believe it is, although I don't have time to work on it right now. The trick is that you can thread the expected output type of each function invocation backwards through in order to selected a typeclass instance at that invocation. So just like read "123" can return either Int or Float depending on what the code calling it expects, f can have the type either VariadicFunction v => Int -> v or () -> Int depending on what's expected of it... It wouldn't be a short solution, but interestingly it may well be the only statically typed one on the list. – Jules – 2017-04-21T09:45:25.897

it should be f(4)(3)(), or the definitions should be flipped. – Will Ness – 2017-04-21T13:04:23.707

1Does "any non-positive value" mean that we can e.g. specify 0 as the termination value and negative values as unsupported, or does it mean that, if we choose that option, the code must treat all non-positive inputs as termination values? – Ilmari Karonen – 2017-04-21T16:09:59.930

@CAD97 I haven't really learned Haskell yet, but I know that functions are curried by default. Does it have any varargs functionality? I found this.

– Brian McCutchon – 2017-04-21T21:13:10.103

Tangentially related.

– Neil – 2017-05-06T00:55:02.063

Answers

49

JavaScript (ES6), 18 bytes

f=n=>m=>m?f(m+n):n

Pass a falsy value to retrieve the sum. Zeros could be allowed for a cost of 2 bytes.

Try it online

Ungolfed:

f = function(n) {
    return function(m) {
        if (m) {
            return f(m+n);
        } else {
            return n;
        }
    }
}

Neil

Posted 2017-04-19T19:08:30.183

Reputation: 95 035

Brilliant submission! – Eugene D. Gubenkov – 2017-04-19T19:21:09.963

21

Haskell (GHC), 118 bytes

This is 98 bytes for the code and 20 bytes for the GHC compiler flag -XFlexibleInstances, which enables a type system extension.

class F a where f::Int->a
instance F(()->Int)where f n()=n
instance F a=>F(Int->a)where f=(f.).(+)

This defines a "function" f, which can be called with an arbitrary number of integers followed by the unit (), after which it returns an integer. Type annotations are required. Try it online!

Explanation

Forcing Haskell's strict type system to allow this requires some magic, namely, enabling the GHC extension for flexible typeclass instances. How this works is that f is a parametrically polymorphic function restricted by a type class constraint: its type is F a => Int -> a. This means that f takes an integer and returns a value of type a, for any type a that belongs to the typeclass F. F is just the name of the typeclass that provides the function f; it's declared on the first line.

The next two lines are two instances of F for different types a. The second line states that the type of functions from () to integers belongs to F (where () is the unit type whose only member is the value ()), and the implementation is f n () = n; the function returns its first argument. The last line states that if a belongs to F, then so does the type of functions from integers to a: from a function f :: Int -> a we can generate another function f :: Int -> Int -> a. The implementation is f m n = f (m+n) (the code uses combinators to make it shorter), where the f on the left is the new one, and the f on the right is the old one. This essentially gives f a new integer argument, which is added to the next one. Multiple arguments are summed together like this:

  f  a1   a2   a3   a4   a5  ()
= f (a1 + a2)  a3   a4   a5  ()
= f (a1 + a2 + a3)  a4   a5  ()
= f (a1 + a2 + a3 + a4)  a5  ()
= f (a1 + a2 + a3 + a4 + a5) ()
=    a1 + a2 + a3 + a4 + a5

The f on each line has a different type.

Haskell functions are curried automatically, so if you give f only integers, you get a function.

Zgarb

Posted 2017-04-19T19:08:30.183

Reputation: 39 083

1Maybe I'm nitpicking, but it's not quite what the challenge asks for. You're defining two(!) functions, both called f, not a single function that does the job. However, this is as close as you can get in Haskell. I don't think it's possible to solve the task with a single function because of the strict type system. – nimi – 2017-04-20T20:45:00.623

3@nimi This defines not two functions called f, but infinitely many functions called f. (One for each possible number of arguments.) These functions (from this infinite family) have two sorts of definitions, one sort when the number of arguments is zero, and another when it is not. – ShreevatsaR – 2017-04-21T04:44:14.777

@ShreevatsaR: I see two definitions, f n()=n and f=(f.).(+), so I'd call it defining two functions. – nimi – 2017-04-21T05:27:00.727

7@nimi There are two definitions, but not two functions. The number of definitions need not be the number of functions. For example, you can define the factorial function with the two definitions g 0 = 1 and g n = g (n-1) * n, where there are two definitions but just one function. Here we have two definitions but infinitely many functions. (Each of a different type.) – ShreevatsaR – 2017-04-21T05:53:48.577

@ShreevatsaR: of course your example of the factorial function is just a single function. The two definitions in the code above are two individual definitions, because they are in different where contexts. Both f are of type Int -> a, so why shouldn't they be functions? – nimi – 2017-04-21T15:06:37.060

@nimi The first line says that, for a type a to belong to type class F, there must exist a function named f of type Int -> a. The next two lines declare that some types a belong to class F: namely types ()->Int, Int->(()->Int), Int->(Int->(()->Int)) and so on. For each of these types (call them a1, a2, ...), the "justification" that the type belongs to class F is given by defining corresponding (different) functions f, which are of types Int->a1, Int->a2, and so on. We could add more definitions for new types. (E.g. we could add instance F Char where f n = 'z'.) – ShreevatsaR – 2017-04-21T18:32:27.463

1@nimi BTW in ghci load the above and try :t f— it will say f :: F a => Int -> a (meaning that if a is an instance of class f, then f is a function Int -> a). So we could consider this as either one function or infinitely many, but although it has two sorts of definitions (just like the factorial function) I don't see any good basis for considering it to be two functions. – ShreevatsaR – 2017-04-21T18:34:05.587

Bending the rules a bit you could declare an instance for Int instead of ()->Int and claim that you "need" to use use 0 as a final argument, even though it isn't required, this would save you 7 bytes. Using () is nicer, but then again this is codegolf :)

– ბიმო – 2018-04-14T15:29:29.273

15

Python 2, 42 41 36 bytes

This solution will never have an overflow, since Python supports arbitrary-precision integers. Zero is the "special value".

f=lambda n:lambda m:m and f(m+n)or n

Try it online

Ungolfed:

def f(n):
    def g(m=''):
        return f(m+n)if m<''else n
    return g

mbomb007

Posted 2017-04-19T19:08:30.183

Reputation: 21 944

14

C, 62 58 bytes, borderline competing

Saved 4 bytes thanks to Kevin! (Still not removing typedef because it's something needed in order to be called.)

typedef(*(*B)(_))(_);q;f(x,o,_){x=x?(q+=x,f):(x=q,q=0,x);}

The function to call is f; you stop calling it and get the result by calling it with a non-positive number like 0. Try a test harness online!

So, as far as I can tell, the only way to "curry" functions that have multiple return types is to do one of the following:

  1. Cast the result to a function to tell the compiler you wish to call the result again;
  2. or create a union/struct type that has an int and function/self-referential subtypes.

I tried doing (2), but it seemed a bit against the spirit of the question and, quite frankly, nigh undoable. Thus, in keeping with the spirit of the challenge, I have opted for option (1). This requires casting each returned function into a function, that it may be used.

This "currying" syntax looks a bit odd, but is quite similar. To emulate f(21)(1), one would have to write ((B)((B)f(21))(1))(0). I defined the B type to be a function that takes an integer and returns a pointer to a function that takes an integer. Expanded, this looks like:

   ( (B)( (B) f(21) )(1) )(0)
//            f(21)            - call f with 21
//        (B)                  - cast to B, a function pointer
//      (           )(1)       - call with 1
//   (B)                       - cast to a function pointer
// (                     )(0)  - call with 0

Conor O'Brien

Posted 2017-04-19T19:08:30.183

Reputation: 36 228

If you say it terminates on 0 only, you're going to require the casting (which you do in C because C can't properly define a function that returns itself), and you leave clearing the global between runs to the caller (which I think is perfectly reasonable), you can simplify the entire thing to q;f(x){return x?(q+=x,f):q;}. – Kevin – 2017-04-20T06:48:45.960

Try it online! – Kevin – 2017-04-20T06:48:49.953

1@Kevin yet, as per site rules, a function must be reusable. If I didn't zero q after each run, then the function would no longer be useable – Conor O'Brien – 2017-04-20T11:14:17.597

Maybe function pointers? You'd have to de reference every time but might be worth checking out – Downgoat – 2017-04-20T14:04:51.980

Shame. Still, you can get rid of the typedef and simplify to q;f(x,o){return x?(q+=x,f):(x=q,q=0,x);} (Try it online!)

– Kevin – 2017-04-22T03:21:41.160

@Kevin That's fantastic! – Conor O'Brien – 2017-04-22T05:18:30.610

1

@ConorO'Brien I just implemented your union approach. It's longer than this one, but it's not far off.

– Jakob – 2018-05-24T20:00:34.087

This solution seems to work fine when the function signature of f is reduced to just f(x)

– Phlarx – 2018-08-29T20:42:48.517

13

Mathematica, 25 bytes

f[x_]@y_=f[x+y]
f[x_][]=x

Try it online! (Using Mathics.)

It's possible to do three bytes less by porting the JavaScript answer, but I wanted to present a more idiomatic Mathematica solution. The @ is just a bit of syntactic sugar, which makes the solution equivalent to:

f[x_][y_]=f[x+y]
f[x_][]=x

So yeah the idea is that in Mathematica you can't just define a function f[x_] but you can directly attach a value to a more complicated expression containing f, e.g. f[x_] being passed another argument. By setting up two definitions for this, we can get the desired behaviour:

  • The first definition collapses one f[x][y] call into f[x+y], thereby consuming one "call" and adding up the arguments inside. This rule applies until we're left with f[sum][].
  • The second definition unpacks this final case by defining the entire thing to evaluate to sum.

Martin Ender

Posted 2017-04-19T19:08:30.183

Reputation: 184 808

1<3 symbolic programming – Julian Wolf – 2017-04-19T23:41:40.813

8

C++, 72 bytes

#define O(P)operator()(P){return{P+a};}int
struct F{F O(int(m))O()a;}f;

This defines a type F which acts as the requested function, and a variable f of that type to invoke. It's valid as of C++11 and works with online versions of GCC, clang, icc and VC++.

Usage:

int main() {
  return f(1)(2)(3)(); // returns 6
}

Explanation:

After preprocessing and reformatting, it looks like:

struct F {
  F operator()(int(m)) { return{int(m)+a}; }
  int operator()() { return {+a}; }
  int a;
} f;

This would normally be written:

struct F {
  F operator()(int m) { return {m+a}; }
  int operator()() { return a; }
  int a;
} f;

return a; and return {+a}; do the same thing, as unary + doesn't change the value, and redundant braces around the return value are allowed. int m and int(m) do the same thing, as redundant parentheses around a variable name are allowed, including function parameters. return {m+a}; and return {int(m)+a}; do the same thing, as a cast of m from int to int does not change its value. These changes get the two operator() overloads closer in syntax, allowing a single macro definition to be invoked twice. Picking the right order for the three members allows the first word of the next line (int) to be included in the macro definition as well.

hvd

Posted 2017-04-19T19:08:30.183

Reputation: 3 664

1Beautiful. And not just the golfed solution...overloading operator() to make this work was especially cool. – Ray Toal – 2017-11-02T03:10:33.430

6

Ruby, 23 bytes

f=->n{->m{m ?f[n+m]:n}}

Usage:

f[1][2][3][nil]
=> 6

daniero

Posted 2017-04-19T19:08:30.183

Reputation: 17 193

6

C, 104 96 bytes

#define a(i)s(i)|b
#define b(i)u(i)|c
#define c(i)u(i)|b
b,c,d;s(i){b=c=i;i=d;}u(i){c=b+=i;i=d;}

Uses the method from the link that @JulianWolf shared. Last argument must be 0.

Try it online!

betseg

Posted 2017-04-19T19:08:30.183

Reputation: 8 493

Comments are not for extended discussion; this conversation has been moved to chat.

– Dennis – 2017-04-20T18:54:42.497

4

Math.JS, 38 Bytes

f(x)=i(x,0)
i(x,y)=x<0?y:j(z)=i(z,y+x)

Call it with f(number_a)(number_b)(...)(negative_number)

If we're allowed to specify the initial call, 12 bytes (f(x)=i(x,0)\n) can be dropped, and it can be called with i(number_one,0)(number_two)(...)(negative_number)

Try it!

Explination

LaTeX!

As shown in the above LaTex, f(x) simply calls i(x,0), then, i(x,y) returns the value of y if x is less than 0, or the function j(z)=i(z,x+y), which takes one argument, which loops. Adding to the value of y.

ATaco

Posted 2017-04-19T19:08:30.183

Reputation: 7 898

4

C, 232 206 bytes

#include<string.h>
#include<stdlib.h>
#define f(X)s(""#X)?0:g
#define g(X)u(""#X)?0:h
#define h(X)u(""#X)?0:g
g=0,h=0;s(char*s){g=h=atoi(s);return 0;}u(char*s){char*a=strlen(s)?s:"0";g=h+=atoi(a);return 0;}

This can probably be golfed significantly, but should serve as a proof of concept that C can be used, without any language extensions*, to solve this problem by calling without arguments rather than with a magic value.

* @hvd has noted that, while this works out of the box using gcc, some of the behavior is not defined in the C standard, meaning that this may not be portable. Use at your own risk!

Ungolfed:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define f(X) start("" #X) ? 0 : f0
#define f0(X) update("" #X) ? 0 : f1
#define f1(X) update("" #X) ? 0 : f0

long f0 = 0;
long f1 = 0;

int start(const char *s) {
    f0 = f1 = strtol(s, NULL, 10);

    return 0;
}

int update(const char *s) {
    const char *a = strlen(s) ? s : "0";
    f0 = f1 += strtol(a, NULL, 10);

    return 0;
}

int main() {
    printf("f(1)()          -> %ld\n", f(1)());
    printf("f(1)(2)(0)(3)() -> %ld\n", f(1)(2)(0)(3)());
    printf("f(1)(-2)(3)()   -> %ld\n", f(1)(-2)(3)());
    printf("f()             -> %ld\n", f());

    return 0;
}

Compiling and running with gcc arbitrary-length-currying.c -o arbitrary-length-currying && ./arbitrary-length-currying outputs (after some warnings)

f(1)()          -> 1
f(1)(2)(3)(0)() -> 6
f(1)(-2)(3)()   -> 2
f()             -> 0

Julian Wolf

Posted 2017-04-19T19:08:30.183

Reputation: 1 139

"without any language extensions" -- The trick of alternating between g and h to continue a chain of macro invocations is not guaranteed to work, as it's unspecified whether the next g appears in the context of the expansion of the first g. C11 adds an example to 6.10.3.4 to spell out that it's unspecified. (IIRC, TenDRA's preprocessor is one that wouldn't expand it the way you want.) Aside from that, no version of the language supports both empty macro arguments and implicit int, so a valid C program cannot use both. :) Still, nice answer. Are you looking to golf it further? – hvd – 2017-04-22T14:18:23.617

@hvd: yeah, probably gonna come back to it in a couple of days and see if I can golf it down. You're definitely right that this is unspecified behavior, but I think the standard treatment on here is that languages are defined by their implementation, so as long as it works with gcc I'm happy. – Julian Wolf – 2017-04-22T14:55:51.983

I was just addressing the comment you included in your answer that it doesn't rely on any language extensions. Yes, even with language extensions, it's perfectly valid as an answer here, didn't mean to suggest otherwise. – hvd – 2017-04-22T15:04:25.447

Ah, that's definitely fair. You're right that I should stipulate that, while no extra flags are required, this may not be portable. – Julian Wolf – 2017-04-22T15:58:54.370

You can test for the empty string with *s instead of strlen(s). C strings are implicit-length, terminated by a char with value 0. Nice macro hack to allow call with/without an arg! – Peter Cordes – 2018-05-04T20:02:30.667

4

8086 machine code, 27 bytes

00000000  bb 00 00 85 c0 74 13 01  d8 be 00 01 89 e7 47 47  |.....t........GG|
00000010  57 b9 1b 00 f3 a4 5b 89  47 01 c3                 |W.....[.G..|
0000001b

This machine code must be at address 0x100, and assumes the tiny code model (cs=ds=es=ss). The function location can be changed without costing extra bytes, though. Putting it at offset 0 would save a byte (xor si,si instead of mov si, 0x100)

Required calling convention

This assumes the caller has pre-allocated at least 27 bytes on the stack. It takes a number in ax, and returns a function pointer in bx. Calling this pointer with ax=0 terminates the chain, and returns the sum in bx.
So for the first call:

mov bp, sp
sub sp, 28
mov ax, number_to_add
call function
; new function pointer in bx

Then, for each subsequent call:

sub sp, 28
mov ax, number_to_add
call bx
; new function pointer in bx

To terminate:

mov ax, 0
call bx
; result in bx
mov sp, bp

Ungolfed (commented disassembly of the machine code):

00000000  BB0000            mov bx,0x0      ; 0 is replaced after copying
00000003  85C0              test ax,ax
00000005  7413              jz 0x1a         ; if(ax==0) ret (with value in bx)
00000007  01D8              add ax,bx       ; arg += total
00000009  BE0001            mov si,0x100    ; address of the original: ds:0x100
0000000C  89E7              mov di,sp
0000000E  47                inc di
0000000F  47                inc di          ; dst = sp+2 = above return address
00000010  57                push di
00000011  B91B00            mov cx,0x1b
00000014  F3A4              rep movsb         ; copy the function code.
00000016  5B                pop bx            ; bx = start of copy destination
00000017  894701            mov [bx+0x1],ax   ; update total in the copied code
0000001A  C3                ret               ; with bx = function pointer

After calling this with non-zero AX, bx = sp and the buffer is filled with a modified copy of the machine code from function. The 16-bit immediate in the first instruction holds the total. (It's written by the last instruction before the ret.)

push di / pop bx could be replaced with mov bx, di (before rep movsb), making it simpler but no savings.

Requiring the caller to pass a pointer to the dst buffer in di would save 4 bytes vs. calculating it relative to sp.

Making the function start address the same as the function size would save a byte (mov cx, si).

user5434231

Posted 2017-04-19T19:08:30.183

Reputation: 1 576

This would be a better answer if you included disassembly of the machine-code bytes. machine-code answers definitely need an ungolfed version. e.g. use objdump -b binary instead of hexdump -C – Peter Cordes – 2018-05-04T20:05:39.660

Updated with commented disassembly. Possible savings: require the caller to pass a dst pointer in di (4 bytes). Make the function start address = size: mov cx, si instead of mov cx, 0x1b. – Peter Cordes – 2018-05-05T17:34:16.920

2

Pyth, 19 bytes

DhdDebR?bh+dbdR$end

Try it online!

I'm impressed that Javascript beats Pyth, but then again Pyth is not quite designed to be passing functions.

Steven H.

Posted 2017-04-19T19:08:30.183

Reputation: 2 841

2

C#, 62 bytes

dynamic f(int n)=>(System.Func<int,dynamic>)(m=>m<0?n:f(n+m));

To end the call pass in a negative number e.g.

f(1)(2)(3)(-1) == 6

TheLethalCoder

Posted 2017-04-19T19:08:30.183

Reputation: 6 930

I'd like to get it to work by passing in null or no parameters to end. However, all the ways I tried were a lot longer – TheLethalCoder – 2017-04-20T09:54:14.813

Can you use !m instead of m<0 and pass null or 0 as the last parameter? – betseg – 2017-04-20T10:19:05.797

@betseg No in C# only a Boolean can be be used as a Boolean... I tried with null but it just got longer. I wanted to use ?? which means if LHS is null do RHS, but as I need if LHS is not null do this else do RHS I couldn't. – TheLethalCoder – 2017-04-20T10:23:07.963

2

Scala, 58 chars

case class f(n:Int){def apply(m:Int)=f(n+m)
def apply()=n}

Try it online

Ungolfed:

case class f(n:Int){
  def apply(m:Int)=f(n+m)
  def apply()=n
}

Explanation:

This code defines a case class called f with a constructor taking an int. Definind a case class which will generate the equals, hashcode, toString and copy methods, and a companion object with the same name to enable object creation without the new keyword.

This class has an overloaded apply method: One takes another integer to add and creates a new object with the updated sum, and one without arguments to get the sum.

In Scala, any object with an apply method can be called like a method, that is o.apply(x) can be written as o(x). This is used in the standard libary for arrays, lists, maps and the Function1 trait implemented by anonymous functions

corvus_192

Posted 2017-04-19T19:08:30.183

Reputation: 1 889

2

Perl 5, 36 bytes

sub f{my$n=pop;sub{@_?f($n+pop):$n}}

say f(1)->(); # 1
say f(1)->(2)->(3)->(); # 6

hobbs

Posted 2017-04-19T19:08:30.183

Reputation: 2 403

What about this requires -M5.016? It seems like you should be able to drop -M5.016 and then also drop my and save a couple bytes. If it's just say, you can use the flag -E instead, which doesn't activate use strict, so you can still drop the my. – Chris – 2017-04-22T22:30:22.093

@Chris you're right, it doesn't need 5.16, my initial revision did (using __SUB__) but I changed that before submit and didn't remove the bit about 5.16. I'll remove that. I don't think dropping my would be correct though. – hobbs – 2017-04-23T00:14:04.480

(and no, I'm not counting say as part of the code, it's only for illustrative purposes) – hobbs – 2017-04-23T00:14:50.407

1If you remove my without use strict, $n is implicitly a global variable. It's bad form in proper perl scripts, but it's pretty common in one-liners, and it seems to work here. – Chris – 2017-04-23T04:02:43.950

2

Brain-Flak, 6 bytes

Actually I just noticed that since the ToS is a valid return format popping the 0 is not really needed which saves 2 bytes:

({{}})

Try it online!

Original submission(s), 8 bytes

Uses 0 as the special value:

({{}}{})

Try it online!

Explanation

Given the arguments a1, a2, … , an, 0 the stack initially looks like this:

                                                       an

                                                       

                                                       a2

                                                       a1

                                                       0

The code then goes on, pops every ai, accumulates them, pops the 0 adds them and pushes the result:

(      )  -- push the following value:
 {  }     --   while ToS ≠ 0 (sums the runs):
  {}      --     pop 1 element
     {}   --   pop the remaining 0 & add it

Alternative solutions, 8 bytes

Instead of popping the 0 and adding it to the sum, we can also swap stacks since the right one is initially empty:

({{}}<>)

Try it online!

Using the -r flag the 0 is on the top of the stack, so we could pop it first:

({}{{}})

Try it online!

{}({{}})

Try it online!

ბიმო

Posted 2017-04-19T19:08:30.183

Reputation: 15 345

Oh my goodness... Great one! – Eugene D. Gubenkov – 2018-04-15T15:29:12.610

2

C (GCC), 83 bytes

My first C golf! There are a couple of other C solutions, but this one's a bit different. Preprocessor use is purely cosmetic. This approach was first discussed in Conor O'Brien's answer here.

#define r union r
t=0;r{int v;r(*f)();};r e;r f(a){t+=a;e.v=a?f:t;t*=a>0;return e;}

The terminal value is zero. The return value is a union, so to call the result, use field f, and to access the final value, use field v, e.g.

f(1).f(2).f(3).f(0).v

Try It Online

Limitations

A global variable holds the running total. While this is explicitly disallowed, the submission does support repeated invocations (the total is reset in the terminal call), which seems to be the reason for the ban on global state.

A pointer to f is stored to the returned union through the int member, so this is clearly not portable. I'm not sure if this works on GCC on all platforms or just on Linux or just on x86 or just with ELF or... If anyone knows any details about this, please comment or send a message!

Jakob

Posted 2017-04-19T19:08:30.183

Reputation: 2 428

2

APL (Dyalog Classic), 48 47 46 44 32 bytes

∇r←(a f)x
r←⍎'(a+x)f'↓⍨-0=x
∇
0f

Try it online!

Terminates by passing in zero . Call syntax: ((0 f 1) 2) 0

-15 bytes thanks to @ngn

Requires ⎕IO←0

Any golfing tips are welcome!

Zacharý

Posted 2017-04-19T19:08:30.183

Reputation: 5 710

if you can use 0 as terminator value, change :If x<0 to :If×x and swap the "if" and "else" clauses – ngn – 2018-05-25T03:22:12.290

Derp. I didn't see that it said "non-positive" – Zacharý – 2018-05-25T03:33:53.297

do you know this trick? r←⍎condition⊃'else' 'then' – ngn – 2018-05-25T04:42:13.113

32 bytes – ngn – 2018-05-25T04:59:04.317

Thought that said 22... >_< – Zacharý – 2018-05-25T18:11:18.857

1

C#, 91 58 bytes

dynamic f(int x)=>(Func<int, dynamic>)(y=>y<1?x:f(x + y));

Eugene D. Gubenkov

Posted 2017-04-19T19:08:30.183

Reputation: 657

2You can get rid of some spaces and the public. – Kevin Cruijssen – 2017-04-20T08:25:56.037

1

Julia v0.5+, 52 bytes

type F n end
F()=0
(f::F)()=f.n
(f::F)(x)=(f.n+=x;f)

Call as F. This could probably be made a lot shorter by adopting a less OO method, but I always like getting the chance to use this idiom.

If it can be assumed that "at least one call will be made before the termination call", the second line can be removed to save 6 bytes.

Julian Wolf

Posted 2017-04-19T19:08:30.183

Reputation: 1 139

1

Perl 6, 31 bytes

sub f(\n){->$m?{$m??f n+$m!!n}}

Sean

Posted 2017-04-19T19:08:30.183

Reputation: 4 136

1

PHP, 44 Bytes

An Idea from @user63956

Termination call 0

function f($i){return[$_GET[0]+=$i][$i]?:f;}

Online Version

Termination call with NULL need a càst [$i] to [+$i]

PHP, 47 Bytes

function f($i){global$s;return$i?f.!$s+=$i:$s;}

Online Version

PHP, 52 Bytes

Termination call NULL or any other value that is false in PHP

function f($i){global$s;$i?$s+=$i:print$s;return f;}

if the program must terminate after the Output replace print$s with die("$s") + 2 Bytes

Online Version

Jörg Hülsermann

Posted 2017-04-19T19:08:30.183

Reputation: 13 026

1I think the function should return (not print) $s. so you could do something like return$i?f:$s at the end – Conor O'Brien – 2017-04-19T22:35:02.383

@ConorO'Brien I am not sure but if your Thinking is right it could save 5 Bytes Thank You – Jörg Hülsermann – 2017-04-19T23:07:58.020

1A few bytes can be saved with superglobal variables: function f($i){return[$_GET[0]+=$i][$i]?:f;}. – user63956 – 2017-04-20T05:46:05.047

@user63956 a very nice idea – Jörg Hülsermann – 2017-04-20T10:54:35.840

1

Dyvil, 34 bytes

infix int apply(i:int,j:int=0)=i+j

Usage:

0() // = 0
0(1)() // = 1
0(1)(2)() // = 3

The trailing () can be omitted.

Explanation:

Defines a juxtaposition operator that takes two ints and adds them. The parameter j has the default value 0 to support the call without arguments. The 0 in the examples above is not the name, but a literal.

Clashsoft

Posted 2017-04-19T19:08:30.183

Reputation: 835

1

Julia 0.5, 18 bytes

!n=k->k>0?!(n+k):n

Try it online!

Dennis

Posted 2017-04-19T19:08:30.183

Reputation: 196 637

1

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

BLT

Posted 2017-04-19T19:08:30.183

Reputation: 931

1Nice 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} – MickyT – 2017-04-20T03:42:12.857

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. – Konrad Rudolph – 2017-04-20T10:21:37.337

@KonradRudolph The golfed if was laziness, but the return is just for readability - it gives the same result with or without return. – BLT – 2017-04-20T14:02:18.700

@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.

– Konrad Rudolph – 2017-04-20T14:03:30.010

Cool, I learned something new again. That's one reason I keep coming back. Thanks @KonradRudolph, also this Stack Overflow question is interesting: http://stackoverflow.com/questions/11738823/explicitly-calling-return-in-a-function-or-not

– BLT – 2017-04-20T14:08:06.923

1

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

ovs

Posted 2017-04-19T19:08:30.183

Reputation: 21 408

1

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!

Neil

Posted 2017-04-19T19:08:30.183

Reputation: 95 035

1

Python, 69 bytes

def f(a=0,s=[]):
    if a:
        return lambda b=0:f(b,s+[a])
    return sum(s)

Zhengqun Koo

Posted 2017-04-19T19:08:30.183

Reputation: 21

1I'm assuming this is python? You should state the language used in your answer. – corvus_192 – 2017-04-20T10:13:19.773

Can you try to golf your answer more? As it stands, it's not very well golfed. – Rɪᴋᴇʀ – 2017-04-20T14:23:15.413

1

R, 40 bytes

f=function(x)function(y)`if`(y,f(x+y),x)

0 acts as the stop value here. For two more bytes, we can omit it.

The problem is that R lacks a concise built-in lambda. But if we add one, we can get the code to 26 bytes:

f=x->(y->`if`(y,f(x+y),x))

(Yes, that’s valid R. It just needs an import.)

Konrad Rudolph

Posted 2017-04-19T19:08:30.183

Reputation: 1 067

1

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

Andrei Odegov

Posted 2017-04-19T19:08:30.183

Reputation: 939

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. – AdmBorkBork – 2017-04-20T12:57:50.567

1

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.

rahnema1

Posted 2017-04-19T19:08:30.183

Reputation: 5 435

1

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

skeevey

Posted 2017-04-19T19:08:30.183

Reputation: 4 139

1

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.

Conor O'Brien

Posted 2017-04-19T19:08:30.183

Reputation: 36 228

0

Python, 61 bytes

f=lambda n="":0if n==""else lambda m="":n if m==""else f(n+m)

Much longer than the other Python version, but uses the no-argument syntax rather than a magic number. Can probably be improved upon.

If it can be assumed that "at least one call will be made before the termination call", this can be reduced to 44 bytes:

f=lambda n:lambda m="":n if m==""else f(n+m)

Julian Wolf

Posted 2017-04-19T19:08:30.183

Reputation: 1 139

You can use 0 as default value and gain a bunch of bytes rearranging things: f=lambda n=0:n and(lambda m=0:m and f(n+m)or n)or n – PieCot – 2018-05-06T11:17:10.643

0

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!

Blab

Posted 2017-04-19T19:08:30.183

Reputation: 451

0

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)

NikoNyrh

Posted 2017-04-19T19:08:30.183

Reputation: 2 361

0

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

John ClearZ

Posted 2017-04-19T19:08:30.183

Reputation: 131

0

Java 8, 111 bytes

A lambda from int to a function. Calls are terminated by passing zero.

i->new java.util.function.Function<Long,Object>(){int t=i;public Object apply(Long x){t+=x;return x<1?t:this;}}

Try It Online

Ungolfed

i ->
    new java.util.function.Function<Long, Object>() {
        int t = i;
        public Object apply(Long x) {
            t =+ x;
            return x < 1 ? t : this;
        }
    }

Due to an interesting interplay between byte counts of primitive and object integer types, intermediate functions take a Long as a parameter, but the total is stored in and returned as an int.

Limitations

The returned function is mutated when called, so, for instance, it's not possible to obtain two integer results without two calls of the lambda. However, the functions returned by separate calls to the lambda are fully independent, so it seems the challenge requirements are met.

Liberal casting is required when constructing expressions that use the lambda. See the TIO for a usage example.

Jakob

Posted 2017-04-19T19:08:30.183

Reputation: 2 428

It's actually a lambda from int to an Object. – Zacharý – 2018-05-25T01:59:30.883

Well you can cast it that way, but the actual return type isn't Object. – Jakob – 2018-05-25T05:19:39.910