英文原文档链接: https://book.clarity-lang.org/ch02-03-composite-types.html
复合类型
这些是包含许多其他类型的更复杂的类型。复合类型可以让编写更大智能合约程序变得更加容易。
optional 类型
Clarity 中的类型不允许空值。这意味着布尔值始终为真或假,而整数始终包含一个数字。但有时您希望能够表达一个变量,它可能有一些值,也可能没有。为此,您使用 optional 类型。此类型包装不同的类型,可以是 none 或该类型的值。optional 类型非常强大,工具将执行检查以确保它们在代码中得到正确处理。让我们看几个例子。
包装一个 uint:
(some u5)
包装一个 ASCII 编码的字符串:
(some "An optional containing a string.")
包装主体用户:
(some 'ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE)
关键字 none 表示什么都没有:
none
可能会或可能不会返回值的函数往往会返回一个 optional 类型。正如我们在上一节中看到的,element-at 和 index-of 都返回了 (some ...)。这是因为对于某些输入,找不到匹配的值。我们可以采用相同的列表,但这次尝试检索索引大于列表总大小的元素。我们看到它导致一个 none 值。
(element-at (list 4 8 15 16 23 42) u5000)
在编写智能合约程序时,开发人员必须处理返回 (some ...) 与返回 none 时不同的情况。
为了访问 optional 中包含的值,您必须解开它。
(unwrap-panic (some u10))
尝试解包 none 会导致错误,因为没有任何东西可以解包。unwrap-panic 中的“panic”应该放弃它。
(unwrap-panic none)
后面关于错误处理和定义自定义函数的章节将深入探讨如何处理此类错误以及它们对链状态的影响。
元组
元组 Tuples 是在命名字段中保存多个值的记录。每个字段都有自己的类型,这使得一次性传递结构化数据非常有用。元组有自己的特殊格式并使用花括号。
{
id: u5, ;; a uint
username: "ClarityIsAwesome", ;; an ASCI string
address: 'ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE ;; and a principal
}
元组内的成员是无序的。您可以按名称检索它们,并且无法对其进行迭代。可以使用 get 函数读取特定成员。
(get username { id: 5, username: "ClarityIsAwesome" })
元组与其他值一样,一旦定义就不可改变。这意味着它们无法更改。但是,您可以将两个元组合并在一起以形成一个新元组。合并是从左到右完成的,并将覆盖具有相同键的值。
(merge
{id: 5, score: 10, username: "ClarityIsAwesome"}
{score: 20, winner: true}
)
上面的表达式将产生一个元组,其中两个键合并,分数设置为 20 。
由于合并函数返回一个全新的元组,成员类型实际上可以被序列中较晚的元组覆盖。
(merge
{id: u6, score: 10}
{score: u50}
)
响应
Response 响应是一种复合类型,它像 optional 类型一样包装了另一种类型。然而,不同的是,响应类型包括特定操作是成功还是失败的指示。当响应由公共函数返回时,具有特殊效果。我们将在有关函数的章节中介绍这些效果。
响应采用 (ok ...) 或 (err ...) 的具体形式。在具体响应中包装一个值很简单:
(ok true)
开发人员通常会提出自己的规则来指示错误状态。例如,您可以使用无符号整数来表示特定的错误代码。
(err u5) ;; something went wrong.
对于您应该为响应包装哪些类型没有明确的规则。目前正在提出一些标准,我们将在 Stacks 区块链改进提案 (SIPs) 一章中讨论一些标准。
响应可以像 optional 类型一样展开:
(unwrap-panic (ok true))
尽管不是必需的,私有函数和只读函数也可以返回响应类型。