3

私は次のことをしようとしています

type Foo{T}
  x::changeType(T)
end

関数changeTypeは型パラメーターを他の型に変更します。関数である必要はありません。辞書やマクロを使用したり、これを行う方法が必要なだけです。

関数と辞書の両方で試してみましたが、どちらもエラーになりました。

4

1 に答える 1

3

これは完全には不可能だと思います。ただし、いくつかの回避策で遊ぶことができます。

  1. の型を制約せず、手動で適切な型xでインスタンス化するだけです。x

    type Foo{T}
        x
        y::T
    end
    
    >>> f = Foo{Int32}(5.0f0, 2)
    Foo{Int32}(5.0f0,2)
    >>> typeof(f.x), typeof(f.y)
    (Float32, Int32)
    
  2. オブジェクトを関数でラップできます。

    const types = Dict(Int64 => Float32)
    
    type Foo{T}
        x::T
    end
    
    foo(k) = Foo{get(types, T, T)}
    

    次に、のオブジェクトを作成しますFoo

    >>> foo(Int64)
    Foo{Float32}
    
  3. 同じタイプのフィールドを混在させたい場合type(例:Tとのフィールドmap(T))、コンストラクターを少し変更できます。

    const types = Dict(Int64 => Float32)
    
    type Foo{T}
        x
        y::T
    
        Foo(x=0, y=0) = new(get(types, T, T)(x), y)
    end
    

    これにより、次のようにマッピングしながらFooasを作成できます。Foo{Int64}xFloat32

    >>> Foo{Int64}(5, 2)
    Foo{Int64}(5.0f0, 2)     # x is Float32, y is Int64
    
  4. そして最後で、おそらく最も実行可能なもの: 最初に辞書を定義しtype、両方でラップしますtypes:

    const types = Dict(Int64 => Float32)
    
    type Foo{T, V}
        x::V
        y::T
    end
    

    Fooオブジェクトの構築を関数にラップします。

    foo(T) = Foo{T, get(types, T, T)}
    foo(T, args...) = Foo{T, get(types, T, T)}(args...)
    

    fooFoo関数は、最初のパラメーターが型を指定する型Tのオブジェクトを作成Fooし、その型は辞書Vから動的に推測されます。types

    >>> foo(Int64)
    Foo{Int64,Float32}
    >>> foo(Int64, 5, 2)
    Foo{Int64,Float32}(5.0f0,2) # x is Float32, y is Int64
    

注: 上記の両方のメソッドで、が辞書でT定義されていない場合、関数は戻り、したがってにマップされます。マッピングを必要としない型のフォールバック メソッドです。たとえば、3 番目のオプションの場合:typesgetTxT

>>> Foo{Int32}(5, 2)
Foo{Int32}(5,2)

xとの両方yは、マッピング dict に含まれていないInt32ためです。4 番目のオプションの場合:Int32types

>>> foo(Int32)
Foo{Int32,Int32}

x現在、 の型をの関数としてコンパイル時に指定することはできないと思いますTが、上記の回避策でうまくいくはずです。

Juliaコンパイラがどれほどスマートかはわかりません..types辞書が一定であることを考えると、いくつかのスマートなことを行い、そこから型を推測する可能性がありますx(開発者はこれに答えるか、さらに改善することができます)。

于 2016-04-15T09:30:12.820 に答える