関数はMoveプログラムの構成要素です。ユーザートランザクション[TODO]や他の関数から呼び出され、実行可能なコードを再利用可能な単位にグループ化します。関数は引数を取り、値を返すことができます。モジュールレベルでfunキーワードを使用して宣言されます。他のモジュールメンバーと同様に、デフォルトではプライベートであり、モジュール内からのみアクセス可能です。

module book::math {
    /// この関数は2つの`u64`型の引数を取り、その合計を返します。
    /// `public`可視性修飾子により、この関数はモジュール外からアクセス可能になります。
    public fun add(a: u64, b: u64): u64 {
        a + b
    }

    #[test]
    fun test_add() {
        let sum = add(1, 2);
        assert!(sum == 3, 0);
    }
}

この例では、add関数を定義しています。この関数は2つのu64型の引数を取り、その合計を返します。関数は同じモジュール内にあるテスト関数test_addから呼び出されています。テストではadd関数の結果を期待値と比較し、結果が異なる場合に実行を中断します。

関数の宣言

Moveでは、関数名にsnake_case命名規則を使用する慣習があります。つまり、関数名はすべて小文字で、単語はアンダースコアで区切られます。例えば、do_somethingaddget_balanceis_authorizedなどです。

関数はfunキーワードの後に関数名(有効なMove識別子)、括弧内の引数リスト、そして戻り値の型を記述して宣言します。関数本体は、一連の文と式を含むコードブロックです。関数本体の最後の式が関数の戻り値となります。

fun return_nothing() {
    // 空の式、関数は`()`を返します
}

関数へのアクセス

他のモジュールメンバーと同様に、関数はインポートしてパスを通じてアクセスできます。パスはモジュールパスと関数名を::で区切って構成されます。例えば、bookパッケージのmathモジュールにaddという関数がある場合、そのパスはbook::math::addとなります。モジュールがインポートされている場合はmath::addとなります。

module book::use_math {
    use book::math;

    fun call_add() {
        // 関数はパスを通じて呼び出されます
        let sum = math::add(1, 2);
    }
}

複数の戻り値

Move関数は複数の値を返すことができます。これは、関数から複数の値を返す必要がある場合に便利です。関数の戻り値の型は型のタプルとなります。戻り値は式のタプルです。

fun get_name_and_age(): (vector<u8>, u8) {
    (b"John", 25)
}

タプルを返す関数呼び出しの結果は、let (tuple)構文を使用して変数に展開する必要があります:

// タプルは要素にアクセスするために分解する必要があります。
// nameとageは不変変数として宣言されます。
let (name, age) = get_name_and_age();
assert!(name == b"John", 0);
assert!(age == 25, 0);

宣言された値のいずれかを可変として宣言する必要がある場合は、変数名の前にmutキーワードを配置します:

// nameを可変として宣言し、ageを不変として宣言
let (mut name, age) = get_name_and_age();

引数の一部が使用されない場合は、_記号を使用して無視できます:

// nameを無視し、ageのみを使用
let (_, age) = get_name_and_age();