简体   繁体   English

使用没有变量绑定的变量复制术语

[英]Copy term with variables without variables being bound

With SWI-Prolog. 使用SWI-Prolog。

How can a term with variables be copied without the variables being bound? 如何在没有绑定变量的情况下复制带变量的术语?

What I have tried 我试过了什么

I tried copy_term/2 and duplicate_term/2 我尝试了copy_term / 2duplicate_term / 2

For example: 例如:

foo(c).

foo(E) :-
    E = bar(a,b,X),
    copy_term(E,Ec),
    duplicate_term(E,Ed),
    write("E:  "),write(E),nl,
    write("Ec: "),write(Ec),nl,
    write("Ed: "),write(Ed),nl.

results in 结果是

?- foo(bar(a,b,bar(a,b,bar(a,b,c)))).
E:  bar(a,b,bar(a,b,bar(a,b,c)))
Ec: bar(a,b,bar(a,b,bar(a,b,c)))    <-- Copy
Ed: bar(a,b,bar(a,b,bar(a,b,c)))    <-- Duplicate
true.

?- foo(bar(a,b,bar(a,b,c))).
E:  bar(a,b,bar(a,b,c))
Ec: bar(a,b,bar(a,b,c))    <-- Copy
Ed: bar(a,b,bar(a,b,c))    <-- Duplicate
true.

?- foo(bar(a,b,c)).
E:  bar(a,b,c)
Ec: bar(a,b,c)    <-- Copy
Ed: bar(a,b,c)    <-- Duplicate
true.

and checked the section Analyzing and Constructing Terms 并查看了分析和构建术语部分

What I need 我需要的

Here En is the result of predicate returning what I need 这里En是谓词返回我需要的结果

?- foo(bar(a,b,bar(a,b,bar(a,b,c)))).
E:  bar(a,b,bar(a,b,bar(a,b,c)))
En: bar(a,b,X),                      <-- Need this
true.

?- foo(bar(a,b,bar(a,b,c))).
E:  bar(a,b,bar(a,b,c))
En: bar(a,b,X),                      <-- Need this
true.

?- foo(bar(a,b,c)).
E:  bar(a,b,c)
En: bar(a,b,X),                      <-- Need this
true.

I was hoping for a built-in predicate. 我希望有一个内置的谓词。

TL;DR TL; DR

The need for this is in solving binary expressions. 对此的需求是解决二进制表达式。 The original is used to select the predicate and to solve the expression. 原始用于选择谓词并解决表达式。 A copy I refer to as local is used to show the rewrite for the subexpression and a copy I refer to as global is used to show the rewrite applied to the entire expression. 我称为local的副本用于显示子表达式的重写,而我称为global的副本用于显示应用于整个表达式的重写。 If there is only one term, eg no copies, once the variable is bound for one use, it causes the other uses to fail. 如果只有一个术语,例如没有副本,一旦变量被绑定一次使用,就会导致其他用途失败。

The current solution is to type in the multiple terms with different variables for each use into the predicate. 当前的解决方案是使用不同的变量键入多个术语,以便每次使用到谓词中。 Multiply this by hundreds to possibly thousands of predicates with possible typing or copy/paste mistakes and you can see the need. 将此数量乘以数百甚至数千个谓词,可能会输入或复制/粘贴错误,您可以看到需要。

Other considerations 其他考虑

I have also considered having a master copy of the term in the predicate and then using that to make the three copies. 我还考虑在谓词中使用该术语的主副本,然后使用它来制作三个副本。 The problem with that is one of the copies is used in selecting the predicate, so before a predicate can be selected the copy would have to take place. 问题是其中一个副本用于选择谓词,因此在选择谓词之前,必须进行复制。 So even if a predicate is not selected for evaluation a copy has to take place in the predicate. 因此,即使未选择谓词进行评估,也必须在谓词中进行复制。

foo(c).

foo(Ec) :-
    M = bar(a,b,X),
    copy_term(M,Ec),
    duplicate_term(M,Ed),
    write("M:  "),write(M),nl,
    write("Ec: "),write(Ec),nl,
    write("Ed: "),write(Ed),nl.

?- foo(bar(a,b,bar(a,b,bar(a,b,c)))).
M:  bar(a,b,_9364)
Ec: bar(a,b,bar(a,b,bar(a,b,c)))
Ed: bar(a,b,_9384)
true.

?- foo(bar(a,b,bar(a,b,c))).
M:  bar(a,b,_9240)
Ec: bar(a,b,bar(a,b,c))
Ed: bar(a,b,_9260)
true.

?- foo(bar(a,b,c)).
M:  bar(a,b,_9116)
Ec: bar(a,b,c)
Ed: bar(a,b,_9136)
true.

So 所以
copy_term/2 gives me the copy with the variables bound which is needed for the predicate selection and evaluation part duplicate_term/2 gives me the term with the free variables for use with other predicates. copy_term/2给我用绑定的变量,需要作谓语的选择和评估的一部分复制duplicate_term/2给了我与其他谓词使用自由变量术语。

Example output from actual application 实际应用的示例输出

                    Global                           Local
                    ------------------               -----------------------------
Input               (1 + ((0 + 0) + 0)) 
0 + X -> X                                           (0 + 0)                -> 0
=                   (1 + (0 + 0))       
X + 0 -> X                                           (0 + 0)                -> 0
=                   (1 + 0)             
X + 0 -> X                                           (1 + 0)                -> 1
=                   1                   

(A very tiny remark in the beginning: Rather use single quotes, not double quotes for simple atoms.) (开头的一个非常小的评论:使用单引号,而不是简单原子的双引号。)

In the first case, the relevant part is: 在第一种情况下,相关部分是:

foo(E) :-
    E = bar(a,b,X),
    copy_term(E,Ec),
    write('X' = X).

?- foo(bar(a,b,bar(a,b,bar(a,b,c)))).

Here, E = bar(a,b,X) already unifies X , which cannot be undone later on. 这里, E = bar(a,b,X)已经统一了X ,后来无法撤消。 With the $ -debugger (see below) I get: 使用$ -debugger(见下文),我得到:

call:copy_term(bar(a,b,bar(a,b,bar(a,b,c))),A).
exit:copy_term(bar(a,b,bar(a,b,bar(a,b,c))),bar(a,b,bar(a,b,bar(a,b,c))))

So the ground term is simply copied. 因此简单地复制了基础术语。

In the second case, the relevant part is: 在第二种情况下,相关部分是:

foo(Ec) :-
    M = bar(a,b,X),
    copy_term(M,Ec),
    write('Ec: '),write(Ec),nl.

?- foo(bar(a,b,bar(a,b,bar(a,b,c)))).

First note the variables! 首先注意变量! Ec is in the beginning a ground term. Ec在一开始就是一个基础术语。 And that will not change! 这不会改变! No matter what you do. 无论你做什么。

What you actually do is to copy a non-ground term onto a ground term. 你实际做的是将非基础术语复制到基础术语上。 Now, literally that means, you are copying the term, and the copy gets unified with the ground terms. 现在,字面意思是,您正在复制该术语,并且副本与基础术语统一。 Unification cannot undo the groundness. 统一无法消除基础。

In this fragment you are unhappy that the copied term is ground. 在这个片段中,你不满意复制的术语是基础的。 In fact, prior to copy_term(M, Ec) , the term Ec is already ground. 实际上,在copy_term(M, Ec) ,术语Ec已经基础了。 If you have used a d-bugger and have not found the error, consider a simpler version and simply add a $ in front of copy_term/2 . 如果您使用过d-bugger并且没有找到错误,请考虑更简单的版本 ,只需在copy_term/2前添加$ That is: 那是:

foo(Ec) :-
        M = bar(a,b,X),
        $copy_term(M,Ec),
        write('Ec: '),write(Ec),nl.

which produces: 产生:

call:copy_term(bar(a,b,A),bar(a,b,bar(a,b,bar(a,b,c)))).
exit:copy_term(bar(a,b,A),bar(a,b,bar(a,b,bar(a,b,c)))).
Ec: bar(a,b,bar(a,b,bar(a,b,c)))

So, the copy_term/2 is entirely redundant in this case. 因此,在这种情况下, copy_term/2完全是多余的。


Some minor remarks: In SWI, the difference between copy_term/2 and duplicate_term/2 is only of relevance when you do destructive update on terms (don't!). 一些小的评论:在SWI中, copy_term/2duplicate_term/2之间的区别仅在您对术语进行破坏性更新时才有意义(不要!)。 Particularly problematic is that both copy constraints somehow: 特别有问题的是,两种复制约束都是以某种方式:

?- X #> Y, copy_term(X,C).
Y#=<X+ -1,
_3398#=<C+ -1,
_3398#=<C+ -1.

?- X #> Y, duplicate_term(X,C).
Y#=<X+ -1,
_3780#=<C+ -1.

?- X #> Y, copy_term_nat(X,C). % syntactic version
Y#=<X+ -1.

In general, maintaining copies of constraints is quite complex, better avoid it or treat it more generally. 一般而言,维护约束的副本非常复杂,更好地避免或更普遍地对待它。 SICStus offers only a purely syntactic copy_term/2 . SICStus只提供纯语法copy_term/2 If you want more, you need to use copy_term/3 . 如果你想要更多,你需要使用copy_term/3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM