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

105 lines
3.9 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/18_mutability.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/18_mutability.md&commit_hash=e959b3e54bfa8cee4929743b0193a129e7525c61)
正如我们已经看到的,所有 Erg 变量都是不可变的。但是Erg 对象具有可变性的概念
以下面的代码为例
```python
a = [1, 2, 3]
a = a + [4, 5, 6]
print! a # [1, 2, 3, 4, 5, 6]
```
上面的代码实际上不能被 Erg 执行。这是因为它不可重新分配
可以执行此代码
```python
b = ![1, 2, 3]
b.concat! [4, 5, 6]
print! b # [1, 2, 3, 4, 5, 6]
```
`a, b` 的最终结果看起来一样,但它们的含义却大不相同
虽然 `a` 是表示 `Nat` 数组的变量,但第一行和第二行指向的对象是不同的。名称`a`相同,但内容不同
```python
a = [1, 2, 3]
print! id! a # 0x000002A798DFE940
_a = a + [4, 5, 6]
print! id! _a # 0x000002A798DFE980
```
`id!` 过程返回对象驻留的内存地址
`b` 是一个 `Nat` "动态" 数组。对象的内容发生了变化,但变量指向的是同一个东西
```python
b = ![1, 2, 3]
print! id! b # 0x000002A798DFE220
b.concat! [4, 5, 6]
print! id! b # 0x000002A798DFE220
```
```python
i = !0
if! True. do!
do! i.inc!() # or i.add!(1)
do pass
print! i # 1
```
`!` 是一个特殊的运算符,称为 __mutation 运算符__。它使不可变对象可变
标有""的对象的行为可以自定义
```python
Point = Class {.x = Int; .y = Int}
# 在这种情况下 .x 是可变的,而 .y 保持不变
Point! = Class {.x = Int!; .y = Int}
Point!.
inc_x! ref!(self) = self.x.update! x -> x + 1
p = Point!.new {.x = !0; .y = 0}
p.inc_x!()
print! p.x # 1
```
## 常量
与变量不同,常量在所有范围内都指向同一事物
常量使用 `=` 运算符声明
```python
PI = 3.141592653589
match! x:
PI => print! "this is pi"
```
常量在全局以下的所有范围内都是相同的,并且不能被覆盖。因此,它们不能被 ``=`` 重新定义。此限制允许它用于模式匹配
`True` 和 `False` 可以用于模式匹配的原因是因为它们是常量
此外,常量总是指向不可变对象。诸如 `Str!` 之类的类型不能是常量
所有内置类型都是常量,因为它们应该在编译时确定。可以生成非常量的类型,但不能用于指定类型,只能像简单记录一样使用。相反,类型是其内容在编译时确定的记录
## 变量、名称、标识符、符号
让我们理清一些与 Erg 中的变量相关的术语
变量是一种为对象赋予名称以便可以重用(或指向该名称)的机制
标识符是指定变量的语法元素
符号是表示名称的语法元素、记号
只有非符号字符是符号,符号不称为符号,尽管它们可以作为运算符的标识符
例如,`x` 是一个标识符和一个符号。`x.y` 也是一个标识符,但它不是一个符号。`x` 和 `y` 是符号
即使 `x` 没有绑定到任何对象,`x` 仍然是一个符号和一个标识符,但它不会被称为变量
`x.y` 形式的标识符称为字段访问器
`x[y]` 形式的标识符称为下标访问器
变量和标识符之间的区别在于,如果我们在 Erg 的语法理论意义上谈论变量,则两者实际上是相同的
在 C 中,类型和函数不能分配给变量; int 和 main 是标识符,而不是变量(严格来说可以赋值,但有限制)
然而在Erg语中"一切都是对象"。不仅函数和类型,甚至运算符都可以分配给变量
<p align='center'>
<a href='./17_iterator.md'>上一页</a> | <a href='./19_ownership.md'>下一页</a>
</p>