modern-move-syntax

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

modern-move-syntax

现代Move语法

MCP tool: When available in your environment, also query the Sui documentation MCP server (
https://sui.mcp.kapa.ai
) for up-to-date answers. Use it for verification and for details not covered by these reference files.
MCP工具: 当你的环境中可用时,也可以查询Sui文档MCP服务器(
https://sui.mcp.kapa.ai
)获取最新答案。用它来验证内容以及获取这些参考文件未涵盖的细节。

Overview

概述

The Move 2024 edition introduced method syntax and several convenience features. AI agents frequently fall back to pre-2024 function-call patterns from training data. This skill covers every modern syntax pattern.
Move 2024版本引入了方法语法和多个便捷特性。AI代理经常会从训练数据中退回到2024年之前的函数调用模式。本技能涵盖了所有现代语法模式。

Method Syntax for Common Operations

常见操作的方法语法

Use method-call syntax (dot notation) instead of module function calls.
使用方法调用语法(点表示法)替代模块函数调用。

Coin and Balance

Coin与Balance

move
// WRONG — legacy function-call syntax
let value = coin::value(&payment);
let balance = coin::into_balance(payment);
balance::join(&mut pool.reserve, balance);
let coin = coin::from_balance(balance::split(&mut pool.reserve, amount), ctx);

// CORRECT — method syntax
let value = payment.value();
let balance = payment.into_balance();
pool.reserve.join(balance);
let coin = coin::from_balance(pool.reserve.split(amount), ctx);

// BEST — chained method calls
let balance = payment.split(amount, ctx).into_balance();
move
// 错误——旧版函数调用语法
let value = coin::value(&payment);
let balance = coin::into_balance(payment);
balance::join(&mut pool.reserve, balance);
let coin = coin::from_balance(balance::split(&mut pool.reserve, amount), ctx);

// 正确——方法语法
let value = payment.value();
let balance = payment.into_balance();
pool.reserve.join(balance);
let coin = coin::from_balance(pool.reserve.split(amount), ctx);

// 最佳实践——链式方法调用
let balance = payment.split(amount, ctx).into_balance();

TxContext

TxContext

move
// WRONG
tx_context::sender(ctx)

// CORRECT
ctx.sender()
move
// 错误
tx_context::sender(ctx)

// 正确
ctx.sender()

UID and Object

UID与Object

move
// WRONG
object::delete(id);

// CORRECT
id.delete();
move
// 错误
object::delete(id);

// 正确
id.delete();

String Literals

字符串字面量

Use quoted string literals directly, not
std::string::utf8()
or byte-string conversion.
move
// WRONG
use std::string;
let s = string::utf8(b"hello");

// ALSO WRONG — unnecessary conversion
let s = b"hello".to_string();

// CORRECT — direct string literals (2024 edition)
let s = "hello";                    // String (UTF-8)
let ascii = "hello";                // also works for ASCII strings
let s = b"hello".to_string();      // still valid but prefer quoted form
let ascii = b"hello".to_ascii_string(); // explicit ASCII when needed
直接使用带引号的字符串字面量,而非
std::string::utf8()
或字节字符串转换。
move
// 错误
use std::string;
let s = string::utf8(b"hello");

// 同样错误——不必要的转换
let s = b"hello".to_string();

// 正确——直接字符串字面量(2024版)
let s = "hello";                    // String(UTF-8)
let ascii = "hello";                // 同样适用于ASCII字符串
let s = b"hello".to_string();      // 仍然有效,但优先使用带引号的形式
let ascii = b"hello".to_ascii_string(); // 需要时显式声明ASCII

Vector Literals and Methods

向量字面量与方法

Use vector literal syntax and method calls instead of module functions.
move
// WRONG
let mut v = vector::empty();
vector::push_back(&mut v, 10);
let first = vector::borrow(&v, 0);
let len = vector::length(&v);

// CORRECT
let mut v = vector[10];
let first = &v[0];
let len = v.length();
v.push_back(20);
使用向量字面量语法和方法调用替代模块函数。
move
// 错误
let mut v = vector::empty();
vector::push_back(&mut v, 10);
let first = vector::borrow(&v, 0);
let len = vector::length(&v);

// 正确
let mut v = vector[10];
let first = &v[0];
let len = v.length();
v.push_back(20);

Collection Index Syntax

集合索引语法

move
// WRONG
let val = vec_map::get(&map, &key);

// CORRECT
let val = &map[&key];
move
// 错误
let val = vec_map::get(&map, &key);

// 正确
let val = &map[&key];

Option Macros

Option宏

Use macros instead of manual
is_some
/
destroy_some
patterns.
move
// WRONG
if (opt.is_some()) {
    let value = opt.destroy_some();
    call_function(value);
};

// CORRECT
opt.do!(|value| call_function(value));
使用宏替代手动
is_some
/
destroy_some
模式。
move
// 错误
if (opt.is_some()) {
    let value = opt.destroy_some();
    call_function(value);
};

// 正确
opt.do!(|value| call_function(value));

Default values

默认值

move
// WRONG
let value = if (opt.is_some()) { opt.destroy_some() } else { default };

// CORRECT
let value = opt.destroy_or!(default);
move
// 错误
let value = if (opt.is_some()) { opt.destroy_some() } else { default };

// 正确
let value = opt.destroy_or!(default);

Loop Macros

循环宏

move
// WRONG — manual counter loop
let mut i = 0;
while (i < 32) {
    do_action();
    i = i + 1;
};

// CORRECT — do! macro
32u8.do!(|_| do_action());
move
// 错误——手动计数器循环
let mut i = 0;
while (i < 32) {
    do_action();
    i = i + 1;
};

// 正确——do!宏
32u8.do!(|_| do_action());

Range-based loops

基于范围的循环

move
// Iterate over a numeric range
let mut sum = 0;
10u64.do!(|i| { sum = sum + i });  // i goes 0..9

// With index for more complex logic
let mut results = vector[];
5u64.do!(|i| results.push_back(i * i));  // [0, 1, 4, 9, 16]
move
// 遍历数值范围
let mut sum = 0;
10u64.do!(|i| { sum = sum + i });  // i从0到9

// 带索引的复杂逻辑
let mut results = vector[];
5u64.do!(|i| results.push_back(i * i));  // [0, 1, 4, 9, 16]

Vector iteration

向量遍历

move
// WRONG
let mut i = 0;
while (i < vec.length()) {
    call_function(&vec[i]);
    i = i + 1;
};

// CORRECT
vec.do_ref!(|e| call_function(e));
move
// 错误
let mut i = 0;
while (i < vec.length()) {
    call_function(&vec[i]);
    i = i + 1;
};

// 正确
vec.do_ref!(|e| call_function(e));

Vector creation from range

从范围创建向量

move
// WRONG
let mut v = vector[];
let mut i = 0;
while (i < 32) { v.push_back(i); i = i + 1; };

// CORRECT
let v = vector::tabulate!(32, |i| i);
move
// 错误
let mut v = vector[];
let mut i = 0;
while (i < 32) { v.push_back(i); i = i + 1; };

// 正确
let v = vector::tabulate!(32, |i| i);

Fold and filter

折叠与过滤

move
// fold
let sum = source.fold!(0, |acc, v| { acc + v });

// filter (requires T: drop)
let filtered = source.filter!(|e| e > 10);
move
// 折叠
let sum = source.fold!(0, |acc, v| { acc + v });

// 过滤(要求T: drop)
let filtered = source.filter!(|e| e > 10);

Struct Unpacking:
..
Syntax

结构体拆包:
..
语法

Use
..
to ignore unused fields when destructuring in 2024 edition.
move
// WRONG
let MyStruct { id, field_1: _, field_2: _, field_3: _ } = value;

// CORRECT
let MyStruct { id, .. } = value;
在2024版中,使用
..
忽略解构时未使用的字段。
move
// 错误
let MyStruct { id, field_1: _, field_2: _, field_3: _ } = value;

// 正确
let MyStruct { id, .. } = value;

Renamed Standard Library Functions

重命名的标准库函数

Some standard library functions have been renamed. Using the old name produces a deprecation warning or compile error.
move
// WRONG — deprecated, renamed
dynamic_field::exists_(&id, key)

// CORRECT
dynamic_field::exists(&id, key)
部分标准库函数已被重命名。使用旧名称会产生弃用警告或编译错误。
move
// 错误——已弃用、已重命名
dynamic_field::exists_(&id, key)

// 正确
dynamic_field::exists(&id, key)

Positional Fields (Tuple Structs)

位置字段(元组结构体)

Structs can use positional fields instead of named fields:
move
// Named fields (traditional)
public struct Wrapper has copy, drop, store { value: u64 }

// Positional fields (2024 edition)
public struct Wrapper(u64) has copy, drop, store;

// Access by position
let w = Wrapper(42);
let val = w.0;
Positional structs are useful for newtype wrappers and dynamic field keys (see
naming-conventions
skill).
结构体可以使用位置字段替代命名字段:
move
// 命名字段(传统方式)
public struct Wrapper has copy, drop, store { value: u64 }

// 位置字段(2024版)
public struct Wrapper(u64) has copy, drop, store;

// 通过位置访问
let w = Wrapper(42);
let val = w.0;
位置结构体适用于新类型包装器和动态字段键(参见
naming-conventions
技能)。

Public Structs

公共结构体

The
public
keyword on structs controls visibility of the struct's fields. Without
public
, fields are module-private — only the defining module can construct or destructure the struct.
move
// Fields visible only within this module
struct Config has key { id: UID, admin: address }

// Fields visible to other modules
public struct Token has key, store { id: UID, value: u64 }
Use
public
when other modules need to read fields or construct/destructure the struct. Omit it for encapsulation.
结构体上的
public
关键字控制结构体字段的可见性。没有
public
时,字段是模块私有——只有定义该模块的代码可以构造或解构结构体。
move
// 字段仅在本模块内可见
struct Config has key { id: UID, admin: address }

// 字段对其他模块可见
public struct Token has key, store { id: UID, value: u64 }
当其他模块需要读取字段或构造/解构结构体时使用
public
。为了封装性则省略该关键字。

Enums

枚举

Move 2024 supports enum types:
move
public enum Color {
    Red,
    Green,
    Blue,
    Custom(u8, u8, u8),
}

public fun is_red(c: &Color): bool {
    match (c) {
        Color::Red => true,
        _ => false,
    }
}
Enums can have variants with positional fields, named fields, or no fields. Use
match
expressions for exhaustive pattern matching. Enums cannot have the
key
ability — they cannot be objects directly, but they can be stored as fields inside objects.
Move 2024支持枚举类型:
move
public enum Color {
    Red,
    Green,
    Blue,
    Custom(u8, u8, u8),
}

public fun is_red(c: &Color): bool {
    match (c) {
        Color::Red => true,
        _ => false,
    }
}
枚举可以包含带位置字段、命名字段或无字段的变体。使用
match
表达式进行穷举模式匹配。枚举不能拥有
key
能力——它们不能直接作为对象,但可以作为对象内部的字段存储。

Quick Reference

快速参考

Legacy PatternModern 2024 Syntax
coin::value(&c)
c.value()
coin::into_balance(c)
c.into_balance()
balance::join(&mut b, v)
b.join(v)
balance::split(&mut b, n)
b.split(n)
tx_context::sender(ctx)
ctx.sender()
object::delete(id)
id.delete()
string::utf8(b"x")
"x"
(or
b"x".to_string()
)
vector::empty()
vector[]
vector::push_back(&mut v, x)
v.push_back(x)
vector::length(&v)
v.length()
opt.is_some() + destroy_some
opt.do!(|v| ...)
while (i < n) { ... i++ }
n.do!(|_| ...)
let S { a, b: _ } = x
let S { a, .. } = x
旧版模式2024现代语法
coin::value(&c)
c.value()
coin::into_balance(c)
c.into_balance()
balance::join(&mut b, v)
b.join(v)
balance::split(&mut b, n)
b.split(n)
tx_context::sender(ctx)
ctx.sender()
object::delete(id)
id.delete()
string::utf8(b"x")
"x"
(或
b"x".to_string()
vector::empty()
vector[]
vector::push_back(&mut v, x)
v.push_back(x)
vector::length(&v)
v.length()
opt.is_some() + destroy_some
opt.do!(|v| ...)
while (i < n) { ... i++ }
n.do!(|_| ...)
let S { a, b: _ } = x
let S { a, .. } = x