首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在朱莉娅的工会类型上经营

在朱莉娅的工会类型上经营
EN

Stack Overflow用户
提问于 2019-10-13 15:04:18
回答 2查看 707关注 0票数 1

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

代码语言:javascript
复制
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

这是有用的,并回答了许多但不是所有类型的问题。这些失败可分为两类,我到目前为止已经注意到了:

这个模式起作用的

  1. Types给出了相对于朱莉娅文档的错误答案。我找到的唯一例子是String符号,它们都被认为是不可变的,但返回false。有关于这方面的错误报告,所以我的解决方案就是为这些类型编写方法,显式地覆盖此模式失败的behavior
  2. Types,--包括UnionUnionAll类型。两者似乎都有简单的解决办法。在UnionAll的情况下,我们可以使用类型变量的上限对类型的具体化进行测试。对于一个Union{A,B},我们可以比较AB类型的可变性,并推导出联合的可变性。

我继续写了这些解决方案,我认为这是一个合理的类似特性的语法,它部分地奏效了:

代码语言:javascript
复制
"""
    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

如果定义了所有这些方法(最后一个方法),那么mutability函数就会像我预期的那样工作,除了Union{A,B}类型的一个例外,这些类型总是被标记为未知。但是,如果定义了最后一个方法,那么它将匹配像Int64这样的类型,而在函数体中甚至没有绑定B (即在方法的开头添加println(A, B)会导致由于未定义B而导致的错误)。我可以看到,在这个A <: Union{A,B}中有一个模糊的地方,但是如何显式地匹配关于Union类型的查询?在这种情况下,如何防止Type{Union{A,B}}Type{A}上匹配?

另外:还有其他情况是mutability函数标签错误吗?

EN

回答 2

Stack Overflow用户

发布于 2019-10-13 15:59:08

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

代码语言:javascript
复制
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

使用上面的其他方法,这将正确地得到以下所有测试:

代码语言:javascript
复制
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-元素数组{Pair,1}:# String => (Immutable(),true) # Symbol => (Immutable(), true) # Int64 => (Immutable(), true) # Dict{Int64,String} => (Mutable(), false) # Array => (Mutable(), false) # Array{Int64,1} => (Mutable(), false) # Tuple => (UnknownMutability(), false) # Tuple{} => (Immutable(), true) # Tuple{Int64,String,Symbol} => (Immutable(), true) # Union{String, Symbol} => (Immutable(), true) # Union{String, Array} => (UnknownMutability(), false) # Union{Dict, Array} => (Mutable(), false) #

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

票数 0
EN

Stack Overflow用户

发布于 2020-02-05 05:57:16

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

代码语言:javascript
复制
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})   
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58364817

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档