累加器工厂

作者:Kodi Arfer

Paul Graham 提出了一个问题,即创建一个接受单个(数字)参数并返回另一个作为累加器的函数的函数。 返回的累加器函数依次也接受一个数字参数,并返回到目前为止传递给该累加器的所有数值的总和(包括创建累加器时传递的初始值)。

详细规则位于 http://paulgraham.com/accgensub.html,为了简单起见,此处重复(并添加了一些内容)。

任务

确保函数

  • 接受一个数字 n 并返回一个函数(我们称之为 g),该函数接受一个数字 i,并返回 n 加上每次调用函数 g(i) 时 i 的累加值。(尽管不需要使用这些确切的函数和参数名称)。

  • 适用于任何数字类型——即可以同时接受整数和浮点数,并返回可以同时接受整数和浮点数的函数。(仅仅将所有输入转换为浮点数是不够的。一个只见过整数的累加器必须返回整数。)(即,如果语言不允许数字多态性,则必须使用重载或类似的东西)

  • 生成返回传递给它们的每个数字的总和的函数,而不仅仅是最近的数字。(这需要一块状态来保存累加值,这反过来意味着纯函数式语言不能用于此任务。)

  • 返回一个真正的函数,这意味着您可以在可以使用在程序文本中以普通方式定义的函数的任何地方使用它。(在此处遵循您的语言约定。)

  • 不要以可能导致它们被其他代码无意中修改的方式存储累加值或返回的函数。(没有全局变量或其他类似的东西。)

示例

如果在示例之后,您添加了以下代码(使用虚构的语言),其中工厂函数称为 foo

x = foo(1);
x(5);
foo(3);
print x(2.3);

它应该打印 8.3。(无需打印 foo(3) 返回的累加器函数的形式;它根本不是任务的一部分。)

目的

此任务的目的是创建一个实现所述规则的函数。它不需要处理上述任何特殊的错误情况。实现所述任务的最简单方法通常是使用闭包,前提是该语言支持它们。

更多

http://rosettacode.org/wiki/Accumulator_factory#Raku

这里有什么有趣的地方?

  • 返回一个 sub

  • 是副本

  • $^var

  • subs 中的静态变量

源代码:accumulator-factory.pl

use v6;

sub accum ($n is copy) { sub { $n += $^x } }

my $a = accum 5;
$a(4.5);
say $a(.5);   # Prints "10".