🐡
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()
の際もcopy
2回からcopy -> move
になってますね(後半のmove
はcopy()
されたのが代入によって右辺値として^
なしにmove
されたからだと思われます)。
というわけで、忘れずに、__del__
を実装しましょうという話でした。
Discussion
追記
毎回
__init__
__moveinit__
,__copyinit__
を実装するのは大変なので、@value
デコレータが存在する。Kotlin のdata class
的なやつ。その他をまとめた記事