【问题标题】:Recursive unitless element type递归无单位元素类型
【发布时间】:2018-05-20 16:44:17
【问题描述】:

我正在尝试提出一个函数,它可以为我提供递归无单位元素类型。因此,例如,为了缩短它让我们称之为ruet,我想拥有:

A = zeros(5,5)
reut(A) == Float64
using Unitful
A = zeros(5,5)*1u"kg"
reut(A) == Float64
AA = [zeros(5,5) for i in 1:5]
reut(AA) == Array{Float64,2}
AofA = [copy(A) for i in 1:5]
reut(AofA) == Array{Float64,2}
using StaticArrays
AofSA = [@SVector [2.0,3.0] for i in 1:5]
reut(AofSA) == SVector{2,Float64}
AofuSA = [@SVector [2.0u"kg",3.0u"kg"] for i in 1:5]
reut(AofuSA) == SVector{2,Float64}

所以基本上去掉了单位,但仍然返回正确的元素类型,可能是一个数组。数组部分很难。我可以递归:

recursive_eltype(a) = recursive_eltype(eltype(a))
recursive_eltype{T<:Number}(a::Type{T}) = eltype(a)

然后获取无单位元素类型:

uEltype = recursive_eltype(u)
uEltypeNoUnits = typeof(one(uEltype))

但是这始终是数字类型,当它是数组数组时,我似乎找不到返回数组类型的好方法,即在上面的所有示例中,此方法都返回Float64 .我想知道这里是否需要在静态数组上调度并使用similar_type

请注意,如果可能的话,我希望解决方案对 Unitful.jl 没有要求。可以通过one(u)获取数字的无单位类型,所以我认为这应该是可能的。

(有点相关的 Julia 问题:https://github.com/JuliaLang/julia/issues/22216

【问题讨论】:

  • 我几乎可以肯定你不想要这样的东西:reut(A) = eval(parse(replace(repr(eltype(A)), repr(recursive_eltype(A)), repr(typeof(one(recursive_eltype(A))))))) 但谁知道呢? :)
  • 我不想评估。我希望这是可推断的。

标签: arrays recursion types julia


【解决方案1】:

使用 Julia 版本 0.6.2-something(代码肯定不是很便携):

function _reut(T)
    try
        T.name == Quantity.body.body.body.name && return _reut(T.parameters[1])
        getfield(T.name.module, T.name.name){_reut.(collect(T.parameters))...}
    catch
        T
    end
end
reut(T) = _reut(eltype(T))

问题中的测试通过了。仍然无法推断,但将eval 替换为getfield(Module,Symbol)。你从哪里得到这些问题?

【讨论】:

  • “你从哪里得到这些问题的?”开发DifferentialEquations.jl 是关于通用算法的无限问题来源。这个comes from a current issue.
  • 如果您将Base.@pure 添加为功能,此解决方案确实可以正确推断。甜的!这可以在 v0.7/1.0 上检查吗?
  • 进行此推断的另一种方法可能只是使其成为@generated 函数。
  • 嗯,这不是我想要的,因为它似乎需要依赖 Unitful.jl 而不仅仅是像 oneoneunit 这样的基本工具来获得无单元类型。
【解决方案2】:

我想出了:

Base.@pure recursive_unitless_eltype(a) = recursive_unitless_eltype(eltype(a))
Base.@pure recursive_unitless_eltype{T<:StaticArray}(a::Type{T}) = similar_type(a,recursive_unitless_eltype(eltype(a)))
Base.@pure recursive_unitless_eltype{T<:Array}(a::Type{T}) = Array{recursive_unitless_eltype(eltype(a)),ndims(a)}
Base.@pure recursive_unitless_eltype{T<:Number}(a::Type{T}) = typeof(one(eltype(a)))

这仍然不是完全通用的,但适用于相当广泛的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-08
    • 1970-01-01
    • 2013-02-26
    • 1970-01-01
    • 2015-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多