我有一根绳子x。我认为这x是 的子类型类型的字符串表示形式Number。例如,x可能采用值"Float64"。我可以使用以下方法检查这一点:
eval(parse(x)) <: Number
Run Code Online (Sandbox Code Playgroud)
然而,它可能x包含一些危险的东西,比如 的一些变体"rm(something_important)",所以eval在我确定x安全之前使用是一个坏主意。
有什么方法可以安全地检查是否x是 的子类型的字符串表示形式Number?
(除了构建所有可能子类型的字符串数组Number并进行比较......)
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 并且是 的子类型Number。Number除了内置子类型之外,这还允许自定义子类型,因为我们正在Main命名空间中对其进行评估。