erg/doc/zh_CN/syntax/24_closure.md
Cai BingJun 8281c3194f trifle
2023-01-07 19:54:57 +08:00

98 lines
No EOL
2.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 闭包
[![badge](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com%2Fdefault%2Fsource_up_to_date%3Fowner%3Derg-lang%26repos%3Derg%26ref%3Dmain%26path%3Ddoc/EN/syntax/24_closure.md%26commit_hash%3De959b3e54bfa8cee4929743b0193a129e7525c61)](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/syntax/24_closure.md&commit_hash=e959b3e54bfa8cee4929743b0193a129e7525c61)
Erg子例程有一个称为"闭包"的功能,可以捕获外部变量
```python
outer = 1
f x = outer + x
assert f(1) == 2
```
与不可变对象一样,可变对象也可以被捕获
```python
sum = !0
for! 1..10, i =>
sum.add!i
assert sum == 45
p!x=
sum.add!x
p!(1)
assert sum == 46
```
但是请注意,函数不能捕获可变对象
如果可以在函数中引用可变对象,则可以编写如下代码
```python,compile_fail
# !!! 这段代码实际上给出了一个错误!!!
i = !0
f x = i + x
assert f 1 == 1
i.add! 1
assert f 1 == 2
```
该函数应该为相同的参数返回相同的值,但假设被打破了
请注意,`i`仅在调用时进行评估
如果您想在定义函数时获取可变对象的内容,请调用`.clone`
```python
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
```python
# Erg
sum = !0
for! 1..10, i =>
sum.add!i
assert sum == 45
```
上面的等效程序可以用Python编写如下:
```python,checker_ignore
# Python
sum = 0
for i in range(1, 10):
sum += i
assert sum == 45
```
但是Erg 建议使用更简单的表示法
与其使用子例程和可变对象来传递状态,不如使用一种使用函数来定位状态的风格。这称为函数式编程
```python
# 功能风格
sum = (1..10).sum()
assert sum == 45
```
上面的代码给出了与之前完全相同的结果,但是您可以看到这个代码要简单得多
`fold`函数可以用来做比sum更多的事情
`fold`是一个迭代器方法,它为每次迭代执行参数`f`
累加结果的计数器的初始值在`init`中指定,并在`acc`中累加
```python
# 从0开始结果会
sum = (1..10).fold(init: 0, f: (acc, i) -> acc + i)
assert sum == 45
```
Erg被设计为对使用不可变对象进行编程的自然简洁描述
<p align='center'>
<a href='./23_subroutine.md'>上一页</a> | <a href='./25_module.md'>下一页</a>
</p>