内部コンストラクターと外部コンストラクターについて
Affine変換のコードを参考にしつつ、内部コンストラクタと外部コンストラクタについて理解を深める
module My
struct Affine
W
b
end
function (a::Affine)(x)
a.W * x + a.b
end
end
using .My
Affine = My.Affine
W = rand(2,3)
b = rand(2)
x = rand(3)
a = Affine(W, b);
@assert a(x) ≈ keisan(W, b, x)
ここで、a = Affine()の引数を制限したいような時でも、関数が動くようにしたい。
この時、外部コンストラクターと内部コンストラクターで二通り考えられる。
1 外部コンストラクターについて
module My
struct Affine
W
b
end
function Affine(W::Matrix)
r, c = size(W)
b = zeros(r)
Affine(W, b)
end
function (a::Affine)(x)
a.W * x + a.b
end
end
using .My
keisan(W, b, x) = W * x + b
W = rand(2, 3)
x = rand(3)
a = Affine(W) # 引数をWに制限した
@assert a(x) ≈ keisan(W, zeros(2), x)
もちろん、引数がW,bの場合でも実行可能である。
W = rand(2,3)
b = rand(2)
x = rand(3)
a = Affine(W, b);
@assert a(x) ≈ keisan(W, b, x)
2 内部コンストラクターについて
structの内部で関数を定義しても上とほぼ同様の振る舞いができる。
module My
struct Affine
W
b
function Affine(W::Matrix)
r, c = size(W)
b = zeros(r)
new(W, b)
end
#Affine(W, b) = new(W, b) #これを入れないと、引数にW,bを入れた時にエラーが出る。
end
function (a::Affine)(x)
a.W * x + a.b
end
end
using .My
Affine = My.Affine
keisan(W, b, x) = W * x + b
W = rand(2, 3)
x = rand(3)
a = Affine(W)
@assert a(x) ≈ keisan(W, zeros(2), x)
先ほどの外部コンストラクタの例とは異なる点として、W,bが引数の場合は実行できない。
内部コンストラクタによって、structのAffineのフィールドW,bが強く制限される。そのため、決められた引数(この場合W)以外は受け付けないようにすることができる。
W = rand(2,3)
b = rand(2)
x = rand(3)
a = Affine(W, b);
@assert a(x) ≈ keisan(W, b, x)
上を実行したい場合は、structの中にAffine(W, b) = new(W, b)
を含ませる必要がある。