如何在Julia中实例化过程中更改参数类型

3

我正试图完成以下操作

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

这里的函数changeType是用来将类型参数更改为其他类型。它不一定非得是一个函数,也可以使用字典或宏等方式,只要能实现这个功能即可。

我尝试过使用函数和字典,但都出现了错误。

1个回答

3

我相信这并不完全可能。但是,您可以尝试使用一些变通方法。

  1. Do not constrain the type of x and just instantiate x with the proper type manualy:

    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. You can wrap your object in a function:

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

    Then create an object of Foo

    >>> foo(Int64)
    Foo{Float32}
    
  3. If you want to have mixed type fields in the same type (e.g. fields of T and map(T)) you can modify a bit the constructor:

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

    This will allow you to create Foo as Foo{Int64} while mapping x to Float32:

    >>> Foo{Int64}(5, 2)
    Foo{Int64}(5.0f0, 2)     # x is Float32, y is Int64
    
  4. And the last, and probably the most viable one: first define the dictionary and wrap your type in both types:

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

    Now wrap the construction of a Foo object into a function:

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

    foo function creates objects of type Foo where the first parameter specifies the type T of Foo and the type V is dynamically inferred from the types dictionary.

    >>> foo(Int64)
    Foo{Int64,Float32}
    >>> foo(Int64, 5, 2)
    Foo{Int64,Float32}(5.0f0,2) # x is Float32, y is Int64
    
注意:在上述两种方法中,如果T没有在types字典中定义,get函数将返回T,因此x将被映射到T。这是一种针对不需要映射的类型的后备方法。例如,对于第三个选项:
>>> Foo{Int32}(5, 2)
Foo{Int32}(5,2)

由于Int32不在映射字典types中,因此xy都是Int32类型。至于第四个选项:

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

目前我认为无法在编译时将x的类型作为T函数的一部分进行指定,但上述解决方法应该能够解决问题。

我不知道Julia编译器有多聪明...鉴于types字典是常量,它可能会从中推断出x的类型(也许开发人员可以回答这个问题或提供更进一步的改进)。


2
const types = Dict(…) 并不会使字典变成不可变的,它只是意味着绑定 types 将始终引用该字典。因此 Julia 无法对类型转换进行编译时推理。如果您想使其类型稳定,可以改用方法分派:change_type{T}(::Type{T}) = T; change_type(::Type{Int64}) = Float64 - mbauman
@MattB。哇,感谢您的澄清。我一直以为const会使字典不可变,但是在终端中尝试后,就像您所说的那样,它允许我添加新项。您提到的change_type可能是替换字典的最佳选项 :) - Imanol Luengo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接