闭包

badge

Erg子例程有一个称为"闭包"的功能,可以捕获外部变量

outer = 1
f x = outer + x
assert f(1) == 2

与不可变对象一样,可变对象也可以被捕获

sum = !0
for! 1..10, i =>
    sum.add!i
assert sum == 45

p!x=
    sum.add!x
p!(1)
assert sum == 46

但是请注意,函数不能捕获可变对象 如果可以在函数中引用可变对象,则可以编写如下代码

# !!! 这段代码实际上给出了一个错误!!!
i = !0
f x = i + x
assert f 1 == 1
i.add! 1
assert f 1 == 2

该函数应该为相同的参数返回相同的值,但假设被打破了 请注意,i仅在调用时进行评估

如果您想在定义函数时获取可变对象的内容,请调用.clone

i = !0
immut_i = i.clone().freeze()
fx = immut_i + x
assert f 1 == 1
i.add! 1
assert f 1 == 1

avoid mutable state, functional programming

# Erg
sum = !0
for! 1..10, i =>
    sum.add!i
assert sum == 45

上面的等效程序可以用Python编写如下:

# Python
sum = 0
for i in range(1, 10):
    sum += i
assert sum == 45

但是,Erg 建议使用更简单的表示法 与其使用子例程和可变对象来传递状态,不如使用一种使用函数来定位状态的风格。这称为函数式编程

# 功能风格
sum = (1..10).sum()
assert sum == 45

上面的代码给出了与之前完全相同的结果,但是您可以看到这个代码要简单得多

fold函数可以用来做比sum更多的事情 fold是一个迭代器方法,它为每次迭代执行参数f 累加结果的计数器的初始值在init中指定,并在acc中累加

# 从0开始,结果会
sum = (1..10).fold(init: 0, f: (acc, i) -> acc + i)
assert sum == 45

Erg被设计为对使用不可变对象进行编程的自然简洁描述