任意长度弯曲


53

编写一个函数,该函数f接受一个正整数并返回一个函数。

返回的新函数应与相同f。但是,当“终止调用”发生时,f应该返回所有传递的整数之和。

例如,g=f(4)(如果f是第一个功能)应设置g为另一个功能。h=g(3)会做同样的。但是,当您h不带任何参数调用时(请参见下文以了解详细信息),它应该输出7,因为这是以前的函数参数的总和。换句话说f(3)(4)() == 7

请注意,这与f(3,4)()

“终止呼叫”是以下选项之一(您的选择):

  • 不带参数调用
  • null作为参数
  • 任何非正值

应该支持任意数量的函数调用,没有预定义的限制。

保证总和不会超过1000。

我们可以假设在“终止呼叫”之前至少进行了一次呼叫。

您的代码不应使用静态的,针对每个程序的变量,因此应该可以在同一运行时中多次运行实验,并观察到完全相同的行为。

例子:

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

4
@LuisMendo通常意味着f(4)返回一个新函数。如果调用该新函数时不带参数,则返回4,但如果调用另一个参数时,它将再次返回具有相同语义但将新参数添加到的新函数4,依此类推。
Martin Ender

6
@LuisMendo确实取决于Eugene,但是我认为允许重复调用将大大摆脱挑战,因为有趣的部分不是创建有状态函数,而是创建高阶函数。
Martin Ender

6
@MartinEnder这很有道理。尤金(Eugene),如果这样做的话,请更改挑战的措词。写一个可以被无限调用的函数根本不暗示该函数应该返回一个函数
Luis Mendo

4
我们是否可以假设一次只存在一个调用链实例?例如不q = f(2)(3); b = f(1)(2)(3); q(); b()
Conor O'Brien

3
最近刚接过Haskell,我对在Haskell中是否有可能感兴趣。强类型系统使我认为可能不是。
CAD97

Answers:


49

JavaScript(ES6),18个字节

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

传递一个伪造的值来检索总和。零可能会花费2字节。

在线尝试

取消高尔夫:

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

辉煌的提交!
尤金·古本科夫

21

Haskell(GHC),118个字节

这是代码的98个字节,GHC编译器标志的20个字节-XFlexibleInstances,它启用类型系统扩展。

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

这定义了一个“函数” f,可以使用任意数量的整数(后跟该单位)来调用“函数” (),此后它返回一个整数。类型注释是必需的。 在线尝试!

说明

强制Haskell的严格类型系统允许这样做需要一些魔术,即为灵活的类型类实例启用GHC扩展。它的工作原理是f受类型类约束限制的参数多态函数:其类型为F a => Int -> a。这意味着对于属于typeclass的任何类型,都f将使用整数并返回type的值。 只是提供功能的类型类的名称; 在第一行中声明。aaFFf

接下来的两行是F不同类型的的两个实例a。第二行指出从from ()到integers 的函数类型所属F(其中()unit类型,其唯一成员是value ()),实现是f n () = n; 该函数返回其第一个参数。最后一行指出,如果a属于F,则函数的类型也是如此,从整数到a:从一个函数f :: Int -> a我们可以生成另一个函数f :: Int -> Int -> a。实现是f m n = f (m+n)(代码使用组合器使其更短),其中f左侧的是新的,f右侧的是旧的。这本质上给了f一个新的整数参数,该参数将添加到下一个参数中。多个参数汇总如下:

  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

f每行具有不同的类型。

Haskell函数会自动进行咖喱处理,因此,如果f仅给出整数,则会得到一个函数。


1
也许我在挑剔,但这并不是挑战所要求的。您要定义两个(!)函数,都称为f,而不是一个单独的函数来完成任务。但是,这与您在Haskell中可以找到的非常接近。由于严格的类型系统,我认为不可能用单个功能来解决任务。
nimi

3
@nimi这不是定义两个函数f,而是定义了多个函数f。(对于每个可能的参数数目,一个。)这些函数(来自这个无限家族)具有两种定义,一种是当参数数目为零时定义,另一种则不是。
ShreevatsaR

@ShreevatsaR:我看到两个定义,f n()=nf=(f.).(+),所以我称它为定义两个函数。
nimi

7
@nimi有两个定义,但没有两个功能。定义的数量不必是功能的数量。例如,您可以定义与两个定义阶乘函数g 0 = 1g n = g (n-1) * n,其中有两个定义,但只是一个功能。在这里,我们有两个定义,但功能无限。(每种不同的类型。)
ShreevatsaR

1
@nimi BTW在ghci上面加载并尝试:t f-它会说f :: F a => Int -> a(这意味着,如果a是class的实例f,则f是一个函数Int -> a)。因此,我们可以将其视为一个函数或无限多个函数,但是尽管它具有两种定义(就像阶乘函数一样),但我认为将其视为两个函数并没有任何好的依据。
ShreevatsaR '17

15

Python 2,42 41 36字节

该解决方案永远不会溢出,因为Python支持任意精度的整数。零是“特殊值”。

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

在线尝试

取消高尔夫:

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

14

C,62 58字节,边界竞争

感谢Kevin,节省了4个字节!(仍然不删除typedef,因为它是被调用所必需的。)

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

调用的函数是f;您停止调用它,并通过使用非正数(例如)来调用它来获得结果0在线尝试测试工具!

因此,据我所知,具有多个返回类型的“ curry”函数的唯一方法是执行以下操作之一:

  1. 将结果转换为一个函数,以告知编译器您希望再次调用该结果;
  2. 或创建union/ struct拥有的类型int和功能/自引用亚型。

我尝试做(2),但是这似乎与问题的精神背道而驰,坦率地说,这几乎是不可挽回的。因此,为了迎接挑战的精神,我选择了选项(1)。这需要将每个返回的函数转换为可以使用的函数。

这种“令人毛骨悚然”的语法看起来有些奇怪,但是非常相似。要模仿f(21)(1),就得写((B)((B)f(21))(1))(0)。我将B类型定义为采用整数的函数,并返回指向采用整数的函数的指针。展开后,看起来像:

   ( (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

如果您说它仅在0处终止,那么您将需要进行强制转换(在C中执行此操作,因为C无法正确定义返回自身的函数),而您需要清除两次调用之间的全局调用(我认为这是完全合理的),您可以将整个过程简化为q;f(x){return x?(q+=x,f):q;}
凯文


1
@Kevin但是,根据站点规则,功能必须可重用。如果q每次运行后我都不为零,则该功能将不再可用
Conor O'Brien

也许函数指针?您每次都必须取消引用,但可能值得一试
Downgoat

1
@ ConorO'Brien我刚刚实现了您的联合方法。它比这更长,但距离也不远。
雅各布

13

Mathematica,25个字节

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

在线尝试!(使用数学。)

通过移植JavaScript答案,可以减少3个字节,但是我想提出一种更惯用的Mathematica解决方案。该@只是有点语法糖,这使得该解决方案等价于:

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

因此,是的,是在Mathematica中,您不仅可以定义函数f[x_],还可以将值直接附加到包含的更复杂的表达式中f,例如f[x_],传递另一个参数。通过为此设置两个定义,我们可以获得所需的行为:

  • 第一个定义将一个f[x][y]调用折叠为f[x+y],从而使用一个“调用”并将其内部的参数加起来。该规则将一直适用,直到我们离开为止f[sum][]
  • 第二个定义通过定义要求值的整个事物来解开最后的情况sum

1
<3符号编程
朱利安·沃尔夫

8

C ++,72个字节

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

这定义了一个F用作请求函数的类型,以及f要调用的该类型的变量。它自C ++ 11起有效,并且可与GCC,clang,icc和VC ++的在线版本一起使用。

用法:

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

说明:

经过预处理和重新格式化后,它看起来像:

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

通常可以这样写:

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

return a;return {+a};执行相同的操作,因为一元+不会更改该值,并且允许在返回值周围使用多余的花括号。int mint(m)做同样的事情,因为允许在变量名前后加上多余的括号,包括函数参数。return {m+a};并且return {int(m)+a};做同样的事情,因为mfrom的int转换int不会改变其值。这些更改使两个operator()重载在语法上更加接近,从而允许单个宏定义被调用两次。为三个成员选择正确的顺序,也可以将下一行(int)的第一个单词也包含在宏定义中。


1
美丽。不仅仅是高尔夫解决方案...过载operator()使这项工作特别酷。
雷·托尔

6

Ruby,23个字节

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

用法:

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


4

Math.JS,38个字节

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

叫它 f(number_a)(number_b)(...)(negative_number)

如果允许我们指定初始调用,f(x)=i(x,0)\n则可以删除12个字节(),并且可以使用i(number_one,0)(number_two)(...)(negative_number)

试试吧!

解释

胶乳!

如上面的LaTex所示,f(x)仅调用i(x,0),然后i(x,y)返回yif 的值x小于0,或者返回带有j(z)=i(z,x+y)一个参数的function ,该函数循环。加上的值y


4

C,232个 206字节

#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;}

这可能是一个不错的选择,但是可以用作概念证明,可以使用C,无需任何语言扩展*,即可通过不带参数而不是带有魔术值的调用来解决此问题。

* @hvd指出,尽管使用gcc可以立即使用,但是某些行为未在C标准中定义,这意味着这可能不可移植。使用风险自负!

取消高尔夫:

#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;
}

编译并运行gcc arbitrary-length-currying.c -o arbitrary-length-currying && ./arbitrary-length-currying输出(在出现一些警告之后)

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

“没有任何语言扩展” – 不能保证在一系列宏调用之间g进行h切换以及继续进行宏调用的技巧,因为尚不确定下一个是否在第一个g扩展的上下文中出现g。C11在6.10.3.4中添加了一个示例,以说明该示例未指定。(IIRC,TenDRA的预处理器无法按照您想要的方式进行扩展。)除此之外,该语言的任何版本均不支持空宏参数和隐式int,因此有效的C程序不能同时使用两者。:)仍然,不错的答案。您是否想进一步打高尔夫球?
hvd

@hvd:是的,可能要过几天再回到那里,看看我是否可以打下去。您肯定是对的,这是未指定的行为,但是我认为这里的标准处理方法是由语言的实现定义它们,因此只要与gcc配合使用,我就很高兴。
朱利安·沃尔夫

我只是在回答您包含在答案中的注释,它不依赖任何语言扩展。是的,即使有语言扩展,它也可以作为此处的答案,但这并不意味着没有其他建议。
hvd

啊,那绝对是公平的。没错,我应该规定,尽管不需要额外的标志,但这可能不是可移植的。
朱利安·沃尔夫

您可以使用*s代替来测试空字符串strlen(s)。C字符串是隐式长度,以a终止,并char带有value 0。不错的宏技巧,允许带有/不带有arg的调用!
彼得·科德斯

4

8086机器代码,27个字节

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

该机器码必须位于地址0x100上,并采用微型代码模型(cs = ds = es = ss)。但是,可以在不花费额外字节的情况下更改函数位置。将其放置在偏移处0将节省一个字节(xor si,si而不是mov si, 0x100

要求的通话惯例

假定调用方已在堆栈上预分配了至少27个字节。它在中接受一个数字ax,并在中返回一个函数指针bx。用调用此指针将ax=0终止链,并返回中的总和bx
因此,对于第一个电话:

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

然后,对于每个后续调用:

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

终止:

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

脱开(注释机器码的拆卸):

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

在使用非零AX调用之后,bx = sp缓冲区中填充了来自的机器代码的修改后的副本function。第一条指令中的16位立即数保存总数。(由之前的最后一条指令编写ret。)

push di/ pop bx可以用mov bx, di(before rep movsb)代替,使其更简单,但没有节省。

要求调用者将指针传递到dst缓冲区di将节省4个字节(相对于相对于计算而言)sp

使函数起始地址与函数大小相同将节省一个字节(mov cx, si)。


如果您包括反汇编的机器代码字节,这将是一个更好的答案。机器码答案肯定需要非公开版本。例如使用objdump -b binary代替hexdump -C
彼得·科德斯

更新后带有注释的反汇编。可能的节省:要求调用者传递一个dst指针di(4个字节)。使函数的起始地址= size:mov cx, si而不是mov cx, 0x1b
彼得·科德斯

2

C#,62个字节

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

要以负数结束通话,例如

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

我想通过传入null或不传递任何参数来使其工作。但是,我尝试的所有方法都花了更长的时间
TheLethalCoder

可以!m代替m<0null0作为最后一个参数使用吗?
betseg

@betseg在C#中不,只能将a Boolean用作Boolean...。我尝试过,null但是时间更长。我想使用??这意味着如果LHS不为空,则执行RHS,但是如果我不希望LHS不为空,则执行此操作,否则我将不执行RHS。
TheLethalCoder

2

Scala,58个字符

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

在线尝试

取消高尔夫:

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

说明:

这段代码定义了一个case classf,其构造函数采用int形式。定义一个case类,该类将生成equals,hashcode,toString和copy方法,以及一个同名的同伴对象,以使无需new关键字即可创建对象。

此类具有重载的apply方法:一个方法使用另一个整数来添加并创建一个具有更新后总和的新对象,而一个不带参数的对象将获取该总和。

在Scala中,具有apply方法的任何对象都可以像方法一样调用,o.apply(x)也可以写为o(x)。它在标准库中用于数组,列表,映射和Function1由匿名函数实现的特征


2

Pyth,19个字节

DhdDebR?bh+dbdR$end

在线尝试!

我印象深刻的是Javascript击败了Pyth,但随后Pyth的设计还不是完全可以传递函数。


2

Perl 5,36个字节

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

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

那需要-M5.016什么呢?看来您应该能够删除-M5.016然后又删除my并保存几个字节。如果只是say,您可以改用-E不会激活的标志use strict,因此仍可以删除my
克里斯(Chris)

@Chris,您是对的,它不需要5.16,我的初始修订版本确实使用(使用了__SUB__),但是我在提交之前进行了更改,并且没有删除有关5.16的内容。我将其删除。我不认为删除my会是正确的。
hobbs

(并且不,我不算say是代码的一部分,仅用于说明目的)
hobbs'Apr

1
如果删除my不带use strict$n则隐式为全局变量。在适当的perl脚本中,这是一种不好的形式,但在单行代码中却很常见,并且似乎可以在这里使用。
克里斯(Chris)2007年

2

Brain-Flak,6个字节

实际上,我只是注意到,由于ToS是一种有效的返回格式,因此并不需要真正弹出0,这样可以节省2个字节:

({{}})

在线尝试!

原始提交,8个字节

使用0的特殊值:

({{}}{})

在线尝试!

说明

给定参数a 1a 2,…,a n0,堆栈最初看起来像这样:

                                                       一个ñ

                                                       

                                                       一个2

                                                       一个1

                                                       0

然后,该代码的推移,每弹出一个,他们积累,持久性有机污染物的0增加了他们和推动的结果:

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

替代解决方案,8字节

除了弹出0并将其添加到总和之外,我们还可以交换堆栈,因为右边的堆栈最初是空的:

({{}}<>)

在线尝试!

使用-r标志0会在堆栈的顶部,因此我们可以先将其弹出:

({}{{}})

在线尝试!

{}({{}})

在线尝试!


哦,我的天哪……太好了!
尤金·古本科夫

2

C(GCC),83个字节

我的第一个C高尔夫!还有其他一些C解决方案,但这有点不同。预处理器的使用纯粹是装饰性的。Conor O'Brien 在这里的回答中首先讨论了这种方法。

#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;}

最终值为零。返回值是一个并集,因此要调用结果,请使用field f,并访问最终值,请使用field v,例如

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

在线试用

局限性

全局变量保存运行总计。尽管明确禁止这样做,但是提交确实支持重复调用(在终端调用中重置了总调用),这似乎是禁止全局状态的原因。

指向该对象的指针f通过该int成员存储到返回的联合中,因此这显然是不可移植的。我不确定这是否适用于所有平台上的GCC或仅适用于Linux或仅适用于x86或仅适用于ELF或...。如果有人知道有关此的任何详细信息,请发表评论或发送消息!


2

APL(Dyalog Classic)48 47 46 44 32字节

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

0f

在线尝试!

通过传入零终止。调用语法:((0 f 1) 2) 0

-15个字节,感谢@ngn

需要 ⎕IO←0

欢迎打高尔夫球!


如果您可以使用0作为终止符值,请更改:If x<0:If×x“ if”和“ else”子句并将其互换
ngn

德普 我没有看到,它说:“不积极”
扎卡里

你知道这个把戏吗?r←⍎condition⊃'else' 'then'
ngn


以为说22 ......> _ <
扎卡里


1

Dyvil,34个字节

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

用法

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

尾随()可以省略。

说明

定义一个并置运算符,它接受两个int并将它们相加。该参数j具有默认值,0以支持不带参数的调用。在0上述示例中是不是名字,而是一个文字。


1

朱莉娅 v0.5 +,52字节

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

呼叫为F。通过采用较少的OO方法,这可能会变得更短,但是我一直很喜欢有机会使用这个习惯用法。

如果可以假定“将在终止呼叫之前至少进行一次呼叫”,则可以删除第二行以节省6个字节。



1

R,40个字节

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

0用作此处的停止值。对于另外两个字节,我们可以忽略它。

问题是R缺少简洁的内置lambda。但是,如果添加一个,则代码可以达到26个字节

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

(是的,这是有效的R。只需要导入即可。)


1

PHP,44字节

来自@ user63956的想法

终止通话 0

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

在线版本

与终端的呼叫NULL需要一个投[$i][+$i]

PHP,47字节

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

在线版本

PHP,52字节

终止调用NULL或任何其他在PHP中为false的值

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

如果程序必须在输出替换print$sdie("$s")+ 2个字节后终止

在线版本


1
我认为函数应该返回(不打印)$s。这样您就可以return$i?f:$s在结尾处做类似的事情
Conor O'Brien

@ ConorO'Brien我不知道,但如果你的思想是正确的就可以节省5个字节谢谢
约尔格Hülsermann

1
可以使用超全局变量保存一些字节:function f($i){return[$_GET[0]+=$i][$i]?:f;}
user63956 '17

@ user63956一个非常不错的主意
约尔格Hülsermann

1

PowerShell,86字节

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

在线尝试!

测试代码:

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

输出: 20


非常好。欢迎来到PPCG!您可以通过$n="$args"代替来保存一个字节$n=$args[0]。但是,它不会在另一$args[0]端起作用,因为那样您将获得字符串连接而不是加法。
AdmBorkBork '17


1

Python,69个字节

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

1
我假设这是python吗?您应说明答案中使用的语言。
corvus_192 '17

你能尝试更多的答案吗?就目前而言,打高尔夫球不是很好。
Rɪᴋᴇʀ

1

八度,39字节

function r=f(n)r=@(m)merge(m,f(m+n),n);

*终止呼叫的参数为0。

在线尝试!

* endfunction需要添加一些其他代码。


1

R,54 52字节

f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g}

多亏了MickyT,节省了2个字节!

类似于python答案之一。取消高尔夫:

f=function(x){
  g=function(y=''){
    if(y>''){
      f(y+x)
      }
      else{x}
  }
  g
}

运行为

> f(1)(2)(4)()
[1] 7

1
辛苦了 您可以摆脱if子句周围的内部括号。f=function(x){g=function(y='')'if'(y>'',f(x+y),x);g}
MickyT

我有点疑惑,为什么您的“ unolfed”版本具有此功能returnreturnR语言与其他语言不同,它会过早中止。不使用return是惯用的。另一方面,您的非高尔夫版本仍然有高尔夫球if
康拉德·鲁道夫

@KonradRudolph打高尔夫球的人if很懒惰,但这return只是为了提高可读性-无论是否带,它都能得到相同的结果return
BLT

@BLT嗯。我强烈感觉到R语言中的免费语言会return 降低可读性,因为它表示错误的信息(过早退出),并且是货物崇拜编程的一个实例。
Konrad Rudolph

酷,我又学到了新东西。这就是我不断回来的原因之一。感谢@KonradRudolph,这个堆栈溢出问题也很有趣:stackoverflow.com/questions/11738823/…–
BLT

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.