Methods 在Julia中的并集类型上操作

Methods 在Julia中的并集类型上操作,methods,types,julia,dispatch,union-types,Methods,Types,Julia,Dispatch,Union Types,在Julia中,isimmutable函数可以告诉您对象何时是不可变的。但是,它不适用于类型,所以我想为类型编写一个版本。根据我在别处找到的建议,一个好的开端是: isimmtype(t::Type) = error("Type $t has not defined isimmtype") isimmtype(t::DataType) = begin if !t.isconcretetype error("Abstract types are neither immuta

在Julia中,
isimmutable
函数可以告诉您对象何时是不可变的。但是,它不适用于类型,所以我想为类型编写一个版本。根据我在别处找到的建议,一个好的开端是:

isimmtype(t::Type) = error("Type $t has not defined isimmtype")
isimmtype(t::DataType) = begin
    if !t.isconcretetype
        error("Abstract types are neither immutable nor mutable")
    else 
        return !t.mutable
    end
end
这很有用,并且回答了许多但不是所有类型的问题。到目前为止,我注意到的故障分为两类:

  • 此模式适用的类型,但相对于Julia文档给出了错误的答案。我找到的唯一示例是字符串符号,这两种类型都假定是不可变的,但返回false。有很多关于这方面的bug报告,所以我下意识的解决方案是只为这些类型编写方法,显式重写 行为
  • 此模式失败的类型。这些类型包括
    Union
    UnionAll
    类型。两者似乎都有简单的解决方案。在
    UnionAll
    的情况下,我们可以使用类型变量的上限对类型的具体化进行测试。对于
    Union{a,B}
    ,我们可以比较
    a
    B
    类型的可变性,并推断Union的可变性
  • 我继续写了这些解决方案,我认为这是一个合理的特性,比如语法,它部分有效:

    """
        Mutability
    The Mutability type is an abstract trait type with children Mutable, Immutable,
    and UnknownMutability.
    """
    abstract type Mutability end
    struct Mutable <: Mutability end
    struct Immutable <: Mutability end
    struct UnknownMutability <: Mutability end
    const MUT_TYPE = Mutable()
    const IMM_TYPE = Immutable()
    const UNK_TYPE = UnknownMutability()
    
    """
        mutability(obj)
    Yields an object of type Mutable, Immutable, or UnknownMutability depending on
    whether the given type object is mutable, immutable, or unknown.
    """
    mutability(T::Type) = UNK_TYPE
    isimmtype(T::Type) = IMM_TYPE === mutability(T)
    
    mutability(T::DataType) = begin
        if !T.isconcretetype
            return UNK_TYPE
        elseif T.mutable
            return MUT_TYPE
        else
            return IMM_TYPE
        end
    end
    mutability(::Core.TypeofBottom) = UNK_TYPE
    mutability(T::UnionAll) = mutability(T{T.var.ub})
    mutability(::Type{String}) = IMM_TYPE
    mutability(::Type{Symbol}) = IMM_TYPE
    # This one causes problems:
    mutability(::Type{Union{A,B}}) where {A,B} = begin
        let mA=mutability(A), mB=mutability(B)
            if mA === UNK_TYPE || mB === UNK_TYPE || mA !== mB
                return UNK_TYPE
            else
                return mA
            end
        end
    end
    
    “”“
    易变性
    可变性类型是一种抽象的特质类型,其子代是可变的、不可变的,
    和不可知的可改变性。
    """
    抽象类型可变端
    
    struct Mutable自从发布问题以来,我意识到一个可能的答案是在默认方法中显式测试
    Union
    类型:

    mutability(T::Type) = begin
        if typeof(T) !== Union
            return UNK_TYPE
        else
            let mA=mutability(T.a), mB=mutability(T.b)
                if mA === UNK_TYPE || mB === UNK_TYPE || mA !== mB
                    return UNK_TYPE
                else
                    return mA
                end
            end
        end
    end
    
    使用上述其他方法,可正确进行以下所有测试:

    map(k->k=>(mutability(k), isimmtype(k)), 
        [String, Symbol, Int64,
         Dict{Int64,String}, Array, Array{Int64,1},
         Tuple, Tuple{}, Tuple{Int64,String,Symbol},
         Union{String,Symbol}, Union{String,Array}, Union{Array,Dict}])
    
    #12元素数组{对,1}: #字符串=>(不可变(),true)
    #Symbol=>(不可变(),true)
    #Int64=>(不可变(),true)
    #Dict{Int64,String}=>(可变(),false)
    #数组=>(可变(),false)
    #数组{Int64,1}=>(可变(),false)
    #Tuple=>(UnknownMutability(),false) #元组{}=>(不可变(),true)
    #元组{Int64,String,Symbol}=>(不可变(),true)
    #联合{String,Symbol}=>(不可变(),true)
    #联合{String,Array}=>(UnknownMutability(),false) #联合{Dict,Array}=>(可变(),false) #


    所有这些在我看来都是正确的。然而,我仍然想知道是否有其他解决方案在
    Union
    上显式匹配,以及是否有其他实例中这些函数无法正确检测可变性

    发布问题后,我意识到一个可能的答案是在默认方法中显式测试
    Union
    类型:

    mutability(T::Type) = begin
        if typeof(T) !== Union
            return UNK_TYPE
        else
            let mA=mutability(T.a), mB=mutability(T.b)
                if mA === UNK_TYPE || mB === UNK_TYPE || mA !== mB
                    return UNK_TYPE
                else
                    return mA
                end
            end
        end
    end
    
    使用上述其他方法,可正确进行以下所有测试:

    map(k->k=>(mutability(k), isimmtype(k)), 
        [String, Symbol, Int64,
         Dict{Int64,String}, Array, Array{Int64,1},
         Tuple, Tuple{}, Tuple{Int64,String,Symbol},
         Union{String,Symbol}, Union{String,Array}, Union{Array,Dict}])
    
    #12元素数组{对,1}: #字符串=>(不可变(),true)
    #Symbol=>(不可变(),true)
    #Int64=>(不可变(),true)
    #Dict{Int64,String}=>(可变(),false)
    #数组=>(可变(),false)
    #数组{Int64,1}=>(可变(),false)
    #Tuple=>(UnknownMutability(),false) #元组{}=>(不可变(),true)
    #元组{Int64,String,Symbol}=>(不可变(),true)
    #联合{String,Symbol}=>(不可变(),true)
    #联合{String,Array}=>(UnknownMutability(),false) #联合{Dict,Array}=>(可变(),false) #


    所有这些在我看来都是正确的。然而,我仍然想知道是否有其他解决方案在
    Union
    上显式匹配,以及是否有其他实例中这些函数无法正确检测可变性

    只要您不关心
    struct
    类型需要对
    isimmtype(::Type{TheStructType})
    进行显式定义,这就可以:

    isimmtype(x::Type) = throw(ErrorException("isimmtype($x) is not defined"))
    
    function isimmtype(::Type{T}) where {T}
      if !T.isconcretetype
        throw(DomainError("Abstract types are neither immutable nor mutable"))
      else
        return !T.mutable
      end
    end
    
    isimmtype(::Type{Symbol}) = true
    isimmtype(::Type{String}) = true
    
    function isimmtype(x::Union)
        return all(isimmtype, Base.uniontypes(x))
    end
    
    isimmtype(x::UnionAll) = isimmtype(x{x.var.ub})   
    

    只要您不关心
    struct
    类型将需要对
    isimmtype(::Type{TheStructType})
    进行显式定义,这就可以:

    isimmtype(x::Type) = throw(ErrorException("isimmtype($x) is not defined"))
    
    function isimmtype(::Type{T}) where {T}
      if !T.isconcretetype
        throw(DomainError("Abstract types are neither immutable nor mutable"))
      else
        return !T.mutable
      end
    end
    
    isimmtype(::Type{Symbol}) = true
    isimmtype(::Type{String}) = true
    
    function isimmtype(x::Union)
        return all(isimmtype, Base.uniontypes(x))
    end
    
    isimmtype(x::UnionAll) = isimmtype(x{x.var.ub})   
    
    你可能对……感兴趣你可能对……感兴趣