Docsの目次

所有権

文字列や配列を自作関数へ渡すと、そのデータの所有権が関数へ移ります。これをmoveと呼びます。渡した変数をもう一度使うとエラーになります。数値などのコピーできる値は、そのまま繰り返し使えます。

def use_name(name: str):
    print(name)

def main():
    name = "alice"
    use_name(name)
    # print(name) はmove後の使用
このページの目次

classのフィールドを取り出す

文字列のフィールドを別の変数へ代入すると、その文字列の所有権が移ります。移動したフィールドは再利用できませんが、移動していない別のフィールドは使えます。

class Person:
    name: str
    age: i64

def main():
    person = Person(name="Nagi", age=1)
    name = person.name
    print(name)
    print(person.age)
    # print(person.name) はmove後の使用

元のフィールドも残したい場合は、上の代入をname = copy(view(person.name))に変更します。コピーはmoveする前に作ってください。printやlenで読み取るだけなら、文字列はmoveしません。

関数に読み取り用の値を渡す例は、読むだけならviewで借りるにあります。

ループで同じ値を使う

ループの外で作った文字列を、毎回所有値として渡すと、1周目でmoveして次の周回で使えなくなります。checkはこの再利用を拒否します。フィールドを取り出す場合や、whileの条件で値を渡す場合も同じです。

元の値を残して渡すには、周回ごとにコピーを作ります。読むだけの関数なら、引数をview[str]にしてview(name)を渡せます。

def use_name(name: str):
    print(name)

def main():
    name = "Nagi"
    for number in range(2):
        use_name(copy(view(name)))
    print(name)

次の周回までに新しい値を代入する方法もあります。

def use_name(name: str):
    print(name)

def main():
    name = "first"
    for number in range(2):
        use_name(name)
        name = "next"
    print(name)

分岐で再代入する場合は、次の周回へ進むすべての経路で値を用意してください。returnで関数を終える経路は、次の周回や後続の処理へ影響しません。ループ内で新しく作った値は周回ごとに使えます。

検査は実行回数を計算せず、繰り返しと0回の実行を考慮します。そのため、ループ内の代入だけでは、ループ後に値が使えるとは限りません。whileの条件は、ループを抜けるときにも評価されます。

借用と検査の範囲

for value in valuesは、走査する配列を借用します。次の周回へ進む経路では、その配列のappend・再代入・moveをcheckで拒否します。view(values)や、そのviewを変数に入れて走査する場合も同じです。別の配列は変更でき、ループが終了すれば走査の借用は終わります。

def main():
    values = [1, 2]
    output: List[i64] = []
    for value in values:
        append(output, value * 2)
    append(values, 3)

フィールドの借用は場所ごとに追跡します。例えばview(data.values)が生きていても、別のdata.nameを取り出せます。data全体やdata.valuesの移動はできません。

viewが借りているデータの移動・再代入・appendも制限します。借用はコードのブロックをもとに追跡します。Rustほど細かく、借用を使い終わった位置を判定するわけではありません。

フィールドの一部を移す場合や、複雑な分岐・借用では、Nagiの検査だけでは判定しきれないことがあります。生成したRustでも借用を検査し、両方を通ったコードを実行ファイルにします。そのため、checkが成功してもbuildで失敗する場合があります。

元のデータとは別に保持したいときは、copy(view(data))で所有するコピーを作ります。

Nagi 0.1のドキュメントこのページのソース