检查是否可以安全地评估符号

Col*_*ers 2 julia

我有一根绳子x。我认为这x是 的子类型类型的字符串表示形式Number。例如,x可能采用值"Float64"。我可以使用以下方法检查这一点:

eval(parse(x)) <: Number
Run Code Online (Sandbox Code Playgroud)

然而,它可能x包含一些危险的东西,比如 的一些变体"rm(something_important)",所以eval在我确定x安全之前使用是一个坏主意。

有什么方法可以安全地检查是否x是 的子类型的字符串表示形式Number

(除了构建所有可能子类型的字符串数组Number并进行比较......)

Mat*_* B. 5

HDF5.jl包必须处理这个问题 通过解析字符串然后在解析之前检查结果来解决这个问题。 eval如果解析后的字符串是它所认为的 a valid_type_expression,那么它就知道在Main命名空间中进行计算应该是安全的。这允许它从主名称空间中获取自定义类型,而这些类型在baremodule.


更多详细信息:解析任意字符串后,您可以检查返回的对象以查看其评估是否“安全”:

julia> dump(parse("Int"))
Symbol Int

julia> dump(parse("Vector{Int}"))
Expr
  head: Symbol curly
  args: Array(Any,(2,))
    1: Symbol Vector
    2: Symbol Int
  typ: Any

julia> dump(parse("""rm("/")"""))
Expr
  head: Symbol call
  args: Array(Any,(2,))
    1: Symbol rm
    2: ASCIIString "/"
  typ: Any
Run Code Online (Sandbox Code Playgroud)

我们希望确保我们永远不会eval有一个可以调用任意行为的表达式。根据您想要支持类型语法的彻底程度,您的解决方案可能非常简单,也可能像我上面链接的 HDF5 解决方案一样复杂。如果您只是追求简单的、非参数化的类型,我们可以大大简化事情:

is_valid_type_expression(ex::Symbol) = true
is_valid_type_expression(ex) = false

function julia_type(string)
    ex = parse(string)
    if is_valid_type_expression(ex)
        try
            typ = eval(Main, ex)
            isa(typ, Type) && typ <: Number && return typ
        end
    end
    error("unsupported type: $string")
end

julia> julia_type("String")
ERROR: unsupported type: String
 in julia_type at none:9

julia> julia_type("Int")
Int64

julia> julia_type("""rm("/")""")
ERROR: unsupported type: rm("/")
 in julia_type at none:9
Run Code Online (Sandbox Code Playgroud)

请注意,任何比符号更复杂的东西都不允许被eval“编辑”。在 ing 表达式之后eval,我们检查以确保该类型是 Type 并且是 的子类型NumberNumber除了内置子类型之外,这还允许自定义子类型,因为我们正在Main命名空间中对其进行评估。