erg/doc/EN/syntax/24_closure.md
Cai BingJun e959b3e54b trifle
2023-01-07 19:20:12 +08:00

96 lines
2.1 KiB
Markdown

# Closure
Erg subroutines have a feature called a "closure" that captures external variables.
```python
outer = 1
f x = outer + x
assert f(1) == 2
```
As with immutable objects, mutable objects can also be captured.
```python
sum = !0
for! 1..10, i =>
sum.add!i
assert sum == 45
p!x=
sum.add!x
p!(1)
assert sum == 46
```
Note, however, that functions cannot capture mutable objects.
If a mutable object can be referenced in a function, you can write code like the following.
```python,compile_fail
# !!! This code actually gives an error !!!
i = !0
f x = i + x
assert f 1 == 1
i.add! 1
assert f 1 == 2
```
The function should return the same value for the same arguments, but the assumption is broken.
Note that `i` is evaluated only at call time.
Call `.clone` if you want the contents of the mutable object at the time the function was defined.
```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
```
The equivalent program above can be written in Python as follows:
```python,checker_ignore
# Python
sum = 0
for i in range(1, 10):
sum += i
assert sum == 45
```
However, Erg recommends a simpler notation.
Instead of carrying around state using subroutines and mutable objects, use a style of localizing state using functions. This is called functional programming.
```python
# Functional style
sum = (1..10).sum()
assert sum == 45
```
The code above gives exactly the same result as before, but you can see that this one is much simpler.
The `fold` function can be used to do more than sum.
`fold` is an iterator method that executes the argument `f` for each iteration.
The initial value of the counter that accumulates results is specified in `init` and accumulated in `acc`.
```python
# start with 0, result will
sum = (1..10).fold(init: 0, f: (acc, i) -> acc + i)
assert sum == 45
```
Erg is designed to be a natural succinct description of programming with immutable objects.
<p align='center'>
<a href='./23_subroutine.md'>Previous</a> | <a href='./25_module.md'>Next</a>
</p>