web-dev-qa-db-ja.com

ジュリアのフィールドとプロパティの違いは何ですか?

ジュリアにはセッター関数setproperty!およびsetfield!と、構造体を操作するゲッター関数getpropertygetfieldジュリアのプロパティとフィールドの違いは何ですか?

たとえば、次の例は同じことを示しているようです。

Julia> mutable struct S
           a
       end

Julia> s = S(2)
S(2)

Julia> getfield(s, :a)
2

Julia> getproperty(s, :a)
2

Julia> setfield!(s, :a, 3)
3

Julia> s
S(3)

Julia> setproperty!(s, :a, 4)
4

Julia> s
S(4)
23

fieldsは単に構造体の「コンポーネント」です。構造体

_struct A
   b
   c::Int
end
_

フィールドbおよびcがあります。 getfieldを呼び出すと、フィールドにバインドされているオブジェクトが返されます。

_Julia> a = A("foo", 3)
A("foo", 3)

Julia> getfield(a, :b)
"foo"
_

Juliaの初期のバージョンでは、構文_a.b_は「低く」使用されていました。つまり、getfield(a, :b)を記述するのと同じです。現在変更されているのは、デフォルトのフォールバックで_a.b_がgetproperty(a, :b)に低下することです。

_getproperty(a::Type, v::Symbol) = getfield(a, v)
_

したがって、デフォルトでは何も変更されていません。ただし、構造体の作成者はgetpropertyをオーバーロードして(getfieldをオーバーロードすることはできません)、ドット構文に追加の機能を提供できます。

_Julia> function Base.getproperty(a::A, v::Symbol)
           if v == :c
               return getfield(a, :c) * 2
           elseif v == :q
               return "q"
           else
               return getfield(a, v)
           end
       end

Julia> a.q
"q"

Julia> getfield(a, :q)
ERROR: type A has no field q

Julia> a.c
6

Julia> getfield(a, :c)
3

Julia> a.b
"foo"
_

したがって、ドット構文に機能を追加できます(必要に応じて動的に)。これが役立つ具体的な例としては、以前は_pyobject[:field]_を記述しなければならなかったパッケージPyCall.jlがありますが、今では_pyobject.field._を記述できるように実装することが可能です。

_setfield!_と_setproperty!_の違いは、上記で説明したgetfieldgetpropertyの違いに似ています。

さらに、REPLでプロパティのタブ補完を提供するために、関数_Base.propertynames_にフックすることが可能です。デフォルトでは、フィールド名のみが表示されます。

_Julia> a.<TAB><TAB>
b c
_

しかし、propertynamesをオーバーロードすることで、追加のプロパティqも表示させることができます。

_Julia> Base.propertynames(::A) = (:b, :c, :q)

Julia> a.<TAB><TAB>
b c q
_
27