🐡
Mojo の __moveinit__ を適用させるには __del__ が必要
はじめに
Pythonと互換性がありながら、高速化された新言語 Mojoが一般公開され、色々触ってみています。
Mojo の特徴として、型に以下の3種類が存在することが挙げられます。
- ムーブ・コピー不可
- ムーブ可能
-
__moveinit__の実装が条件
-
- コピー・ムーブ可能
-
__copyinit__の実装が条件 - ムーブの時には
__moveinit__があればそちらがよばれるし、なければ__copyinit__が呼ばれる
-
この3種類をうまく使うことで所有権の管理が可能です。
また
a = b^
のような ^ transfer 演算子が呼ばれた際には、__moveinit__ が呼ばれます。
実験してみる
早速どのようの __copyinit__ や __moveinit__ が呼ばれるのか実験してみましょう!
struct Pair:
var x: Int
var y: Int
fn __init__(inout self, x: Int, y: Int):
print("Running init")
self.x = x
self.y = y
fn __moveinit__(inout self, owned existing: Self):
print("move init")
self.x = existing.x
self.y = existing.x
fn __copyinit__(inout self, existing: Self):
print("copy init")
self.x = existing.x
self.y = existing.y
fn main():
let p = Pair(1, 2)
let copied = p.copy()
print("copy ended\n")
let moved = (p^).copy()
let moved2 = (moved^).copy()
let moved3 = copy(moved2^)
let moved4 = moved3^
結果がこちら
init
copy init
copy init
copy ended
copy init
copy init
copy init
move init
最後の
let moved4 = moved3^
以外で、全然__moveinit__が呼ばれてない!なんで!!
__del__ をつけてみる
そういえばPairには__del__が実装されていませんでした。実装してから試してみましょう!
struct Pair:
var x: Int
var y: Int
fn __init__(inout self, x: Int, y: Int):
print("init")
self.x = x
self.y = y
fn __moveinit__(inout self, owned existing: Self):
print("move init")
self.x = existing.x
self.y = existing.x
fn __copyinit__(inout self, existing: Self):
print("copy init")
self.x = existing.x
self.y = existing.y
fn __del__(owned self): # added here.
print("deleted")
fn copy(owned self) -> Self:
return self
fn copy(owned pair: Pair) -> Pair:
return pair
fn main():
let p = Pair(1, 2)
let copied = p.copy()
print("copy ended\n")
let moved = (p^).copy()
let moved2 = (moved^).copy()
let moved3 = copy(moved2^)
let moved4 = moved3^
結果がこちら
init
copy init
move init
deleted
copy ended
move init
move init
move init
move init
deleted
ちゃんと__moveinit__が呼ばれてる!!
let copied = p.copy()の際もcopy2回からcopy -> move になってますね(後半のmoveはcopy()されたのが代入によって右辺値として^なしにmoveされたからだと思われます)。
というわけで、忘れずに、__del__ を実装しましょうという話でした。
Discussion
追記
毎回
__init____moveinit__,__copyinit__を実装するのは大変なので、@valueデコレータが存在する。Kotlin のdata class的なやつ。その他をまとめた記事