Julia-lang表达与可交换性的比较

时间:2018-10-21 17:10:07

标签: operators expression julia commutativity

好的,我的标题不好,但可以通过示例轻松解释。

invalid operands to binary expression ('const std::optional<n1::tag>' and 'const std::optional<n2::tag>')

我有两个表达式a和b。我想知道他们是否会给我未经评估的结果

尽管我可以像+或*这样的可交换运算符推断出结果将是相同的。

编辑: 理解它的另一种方式是比较一个非常具体的表达式子集,这些子集可以推断函数的可交换性: Expr(:call,+,a,b)<=> Expr(:call,+,b,a)

2 个答案:

答案 0 :(得分:2)

这是不可能的。找出两个程序是否具有相同结果而不进行评估的结果称为 Function Problem (函数问题),并且可以证明等同于解决停止问题。

不可能计算出代码段是否具有相同的结果。

答案 1 :(得分:2)

我们可以编写一个相当简单的函数,以模序的形式检查两个数组是否具有相同的元素:

function eq_modulo_ordering!(xs, ys)  # note !, mutates xs and ys
    while !isempty(xs)
        i = findfirst(isequal(pop!(xs)), ys)
        i === nothing && return false
        deleteat!(ys, i)
    end
    isempty(ys)
end
eq_modulo_ordering(xs, ys) = eq_modulo_ordering!(copy(xs), copy(ys))

我们可以使用然后使用此功能来检查两个顶级表达式是否等效。

function expr_equiv(a::Expr, b::Expr, comm)
    a.head === b.head || return false
    a.head === :call || return a == b
    a.args[1] ∈ comm || return a == b

    eq_modulo_ordering(a.args, b.args)

end
expr_equiv(a, b, comm) = a == b
expr_equiv(a, b) = expr_equiv(a, b, [:+])

在我们要检查两个表达式在顶级以外完全相等的情况下,我们可以修改函数以使用相互递归来检查子表达式是否为expr_equiv而不是{{1} }。

isequal

我们现在可以按预期使用function eq_modulo_ordering!(xs, ys, comm) # note !, mutates xs and ys while !isempty(xs) x = pop!(xs) i = findfirst(b -> expr_equiv(x, b, comm), ys) i === nothing && return false deleteat!(ys, i) end isempty(ys) end eq_modulo_ordering(xs, ys, comm) = eq_modulo_ordering!(copy(xs), copy(ys), comm) function expr_equiv(a::Expr, b::Expr, comm) a.head === b.head || return false a.head === :call || return a == b a.args[1] ∈ comm || return all(expr_equiv.(a.args, b.args, Ref(comm))) eq_modulo_ordering(a.args, b.args, comm) end expr_equiv(a, b, comm) = a == b expr_equiv(a, b) = expr_equiv(a, b, [:+]) ,可以选择提供可交换的函数列表。

expr_equiv