Skip to content

表达式

在 Tact 中,每个运算符都形成一个表达式,但 Tact 提供了广泛的表达式选择,还有更多内容值得探索。

字面量

字面量代表 Tact 中的值。这些是固定的值——不是变量——你在代码中直接提供的值。所有字面量本身都是表达式。

你还可以直接在字面值上调用定义在某些原始类型上的扩展函数:

solidity
// 在整数字面量上调用为 Int 类型定义的 toString() 函数:
42.toString();
 
// 在字符串字面量上调用为 String 类型定义的 asComment() 函数:
"Tact is awesome!".asComment();

整数字面量

整数字面量可以用十进制(基数 10)、十六进制(基数 16)、八进制(基数 8)和二进制(基数 2)表示:

  • 十进制整数字面量是数字(0-9)的序列。
  • 0x(或 0X)开头表示十六进制整数字面量。它们可以包括数字(0-9)和字母 a-f 以及 A-F。注意,字符的大小写不改变其值。因此:0xa = 0xA = 100xf = 0xF = 15
  • 0o(或 0O)开头表示八进制整数字面量。它们只能包括数字(0-7)。
  • 0b(或 0B)开头表示二进制整数字面量。它们只能包括数字 0 和 1。

注意,在 Tact 中,带前导 0 的整数字面量仍被视为十进制,这与 JavaScript/TypeScript 中的表示八进制的前导 0 不同!

整数字面量的一些示例:

solidity
// 十进制,基数 10:
0, 42, 1_000, 020
 
// 十六进制,基数 16:
0xABC, 0xF, 0x0011
 
// 八进制,基数 8:
0o777, 0o001
 
// 二进制,基数 2:
0b01111001_01101111_01110101_00100000_01100001_01110010_01100101_00100000_01100001_01110111_01100101_01110011_01101111_01101101_01100101

有关整数和 Int 类型的更多信息,请参阅专门页面:Integers。

布尔字面量

Bool 类型只有两个字面值:true 和 false。

solidity
true == true;
true != false;

有关布尔值和 Bool 类型的更多信息,请参阅专门章节:Booleans。

字符串字面量

字符串字面量是零个或多个字符,包含在双引号(")中。所有字符串字面量都是 String 类型的对象。

solidity
"foo"
"1234"
 
// 注意,目前 Tact 字符串中不能有转义字符:
"line \n another"; // 语法错误!参见:https://github.com/tact-lang/tact/issues/25
 
// 这意味着字符串内的双引号也是禁止的:
"this \"can't be!\""; // 语法错误!

有关字符串和 String 类型的更多信息,请参阅:Primitive types。

null 字面量

null 值用 null 字面量表示。它不是一个标识符,也不指代任何对象。它也不是任何原始类型的实例。相反,null 代表缺乏标识和故意缺乏任何值。

solidity
let var: Int? = null; // 可以持有 null 值的变量
var = 42;
if (var != null) {
    var!! + var!!;
}

有关处理 null 的更多信息,请参阅专门页面:Optionals。

标识符

标识符是代码中的一系列字符,用于标识变量、常量、映射和函数,以及 Struct、Message、合约、特征或它们的字段和方法。标识符区分大小写,不加引号。

在 Tact 中,标识符可以包含拉丁小写字母(a-z)、拉丁大写字母(A-Z)、下划线(_)和数字(0-9),但不能以数字开头。标识符与字符串的区别在于,字符串是数据,而标识符是代码的一部分。

注意,原始类型的标识符以大写字母开头。用户定义的复合类型,如 Structs 和 Messages,也必须大写。

实例化

你可以创建以下类型的实例:

  • Structs
  • Messages
solidity
struct StExample {
    fieldInit: Int = 1;
    fieldUninit: Int;
}
 
fun example() {
    StExample{ fieldUninit: 2 };               // 实例化时 fieldInit 使用默认值
    StExample{ fieldInit: 0, fieldUninit: 2 }; // 设置两个字段的实例
}

字段访问

你可以直接访问以下类型的字段:

  • Structs
  • Messages
solidity
struct StExample {
    fieldInit: Int = 1;
    fieldUninit: Int;
}
 
fun example(): Int {
    let struct: StExample = StExample{ fieldUninit: 2 }; // 实例化
 
    struct.fieldInit;          // 访问字段
    return struct.fieldUninit; // 从函数返回字段值
}

扩展函数调用

扩展函数仅在特定类型上定义。它们的调用类似于许多其他语言中的方法调用:

solidity
42.toString(); // toString() 是在 Int 类型上定义的标准库函数

静态函数调用

在函数体的任何地方,都可以调用全局静态函数或合约的内部函数:

solidity
contract ExampleContract {
    init() {}
    receive() {
        now(); // now() 是标准库的静态函数
        let expiration: Int = now() + 1000; // 操作和变量声明
        expiration = self.answerQuestion(); // 内部函数
    }
    fun answerQuestion(): Int {
        return 42;
    }
}

initOf

表达式 initOf 计算合约的初始状态(StateInit):

solidity
//                     合约 init() 函数的参数值
//                     ↓   ↓
initOf ExampleContract(42, 100); // 返回一个 Struct StateInit{}
//     ---------------
//     ↑
//     合约名称

其中 StateInit 是一个内置的 Struct,包括:

字段类型描述
codeCell合约的初始代码(编译后的字节码)
dataCell合约的初始数据(合约 init() 函数的参数)