modern-move-syntax について
Move 2024 の現代的な構文を扱う、開発者と AI エージェント向けのリファレンススキルです。コレクション、オプション、ループ、構造体、列挙型で旧式の呼び出しに代わる書き方を説明します。
主な機能
- 01一般的な操作にメソッド構文を使用
- 02文字列とベクターのリテラルを直接記述
- 03オプションとループのマクロを適用
- 04範囲、fold、filter のパターンを使用
- 05位置フィールド構造体と列挙型を定義
活用シーン
- 01旧式の Move 記述を現代構文に更新
- 02簡潔なコレクション操作の記述
- 03マクロによるオプション値の処理
- 04列挙型や位置フィールドによるデータモデリング
MCP 対応
利用可能な環境では、ガイドの検証や資料にない詳細の確認に Sui ドキュメント MCP サーバー https://sui.mcp.kapa.ai を参照するよう案内します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mystenlabs/ skills --skill modern-move-syntaxインストール後、Claude Code で/modern-move-syntaxを入力して読み込まれたか確認します。
同梱ファイルevals/code-evals.jsonevals/evals.json
詳細
modern-move-syntax
MCP ツール: 利用環境で使用できる場合は、最新の回答を得るために Sui ドキュメント MCP サーバー(
https://sui.mcp.kapa.ai)にも問い合わせてください。検証や、これらのリファレンスファイルに記載されていない詳細の確認に使用します。
概要
Move 2024 エディションでは、メソッド構文と、いくつかの便利な機能が導入されました。AI エージェントは、トレーニングデータに含まれる 2024 年以前の関数呼び出しパターンを頻繁に使用します。このスキルでは、最新の構文パターンをすべて解説します。
すべてのパターンの出典:https://move-book.com/guides/code-quality-checklist
よく使う操作のメソッド構文
モジュール関数を呼び出すのではなく、メソッド呼び出し構文(ドット記法)を使用します。
Coin と Balance
// 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();
TxContext
// WRONG
tx_context::sender(ctx)
// CORRECT
ctx.sender()
UID と Object
// WRONG
object::delete(id);
// CORRECT
id.delete();
文字列リテラル
std::string::utf8() やバイト文字列変換ではなく、引用符で囲んだ文字列リテラルを直接使用します。
// 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
Vector リテラルとメソッド
モジュール関数ではなく、vector リテラル構文とメソッド呼び出しを使用します。
// 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);
コレクションのインデックス構文
// WRONG
let val = vec_map::get(&map, &key);
// CORRECT
let val = &map[&key];
Option マクロ
is_some / destroy_some を手動で使用するパターンではなく、マクロを使用します。
// WRONG
if (opt.is_some()) {
let value = opt.destroy_some();
call_function(value);
};
// CORRECT
opt.do!(|value| call_function(value));
デフォルト値
// WRONG
let value = if (opt.is_some()) { opt.destroy_some() } else { default };
// CORRECT
let value = opt.destroy_or!(default);
ループマクロ
// WRONG — manual counter loop
let mut i = 0;
while (i < 32) {
do_action();
i = i + 1;
};
// CORRECT — do! macro
32u8.do!(|_| do_action());
範囲ベースのループ
// 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]
Vector の反復処理
// WRONG
let mut i = 0;
while (i < vec.length()) {
call_function(&vec[i]);
i = i + 1;
};
// CORRECT
vec.do_ref!(|e| call_function(e));
範囲からの Vector の作成
// 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);
畳み込みとフィルタリング
// fold
let sum = source.fold!(0, |acc, v| { acc + v });
// filter (requires T: drop)
let filtered = source.filter!(|e| e > 10);
構造体の分解:.. 構文
2024 エディションでは、分解時に使用しないフィールドを無視するために .. を使用します。
// WRONG
let MyStruct { id, field_1: _, field_2: _, field_3: _ } = value;
// CORRECT
let MyStruct { id, .. } = value;
標準ライブラリ関数の名称変更
標準ライブラリ関数の一部は名称が変更されています。古い名前を使用すると、非推奨の警告またはコンパイルエラーが発生します。
// WRONG — deprecated, renamed
dynamic_field::exists_(&id, key)
// CORRECT
dynamic_field::exists(&id, key)
位置フィールド(タプル構造体)
構造体では、名前付きフィールドの代わりに位置フィールドを使用できます。
// 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;
位置フィールドを持つ構造体は、newtype ラッパーや動的フィールドキーに便利です(naming-conventions スキルを参照)。
パブリック構造体
構造体の public キーワードは、そのフィールドの可視性を制御します。public を指定しない場合、フィールドはモジュール内でのみ参照でき、構造体を定義したモジュールだけが構造体を構築または分解できます。
// 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 }
ほかのモジュールからフィールドを読み取ったり、構造体を構築または分解したりする必要がある場合は、public を使用します。カプセル化する場合は省略します。
Enum
Move 2024 は enum 型をサポートしています。
public enum Color {
Red,
Green,
Blue,
Custom(u8, u8, u8),
}
public fun is_red(c: &Color): bool {
match (c) {
Color::Red => true,
_ => false,
}
}
Enum には、位置フィールド、名前付きフィールド、またはフィールドなしのバリアントを指定できます。網羅的なパターンマッチには match 式を使用します。Enum は key 能力を持てないため、直接オブジェクトにすることはできませんが、オブジェクト内のフィールドとして格納できます。
クイックリファレンス
| 従来のパターン | 最新の 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 |