简体   繁体   English

什么是 Prolog 运算符 `^`(“插入符号”)?

[英]What is the Prolog operator `^` ("caret")?

What is the Prolog operator ^ ?什么是 Prolog 运算符^

Looking at The Prolog Built-in Directive op gives a list of the built-in operators.查看Prolog 内置指令 op给出了内置运算符的列表。

I see我懂了

  • ** is exponentiation **求幂
  • /\\ is or /\\

but what is ^ ?但什么是^

Each of the three current answers are of value and I learned something:当前三个答案中的每一个都很有价值,我学到了一些东西:

  • Roy for the book罗伊为书
  • false for the examples示例为假
  • I accepted the answer by CapelliC because it made clear that ^/2 has multiple meanings我接受了 CapelliC 的回答,因为它明确表示 ^/2 有多重含义
    depending on context which instantly cleared up my confusion.取决于上下文,这立即消除了我的困惑。

The operator (^)/2 serves several purposes:运算符(^)/2多种用途:

setof/3 , bagof/3 setof/3 , bagof/3

Here it is used to denote the existential variables (set) of a term .这里它用来表示一个术语存在变量(集合) Like in setof(Ch, P^child_of(Ch,P), Chs) where P is declared as an existential variable.就像在setof(Ch, P^child_of(Ch,P), Chs) ,其中P被声明为存在变量。

As a non-standard side effect to this, many systems have defined it as predicate with the following definition:作为对此的非标准副作用,许多系统将其定义为具有以下定义的谓词:

_^Goal :- Goal

But then, others do not have such a definition.但是,其他人没有这样的定义。 It is in any case a good idea to avoid to define a predicate (^)/2 .在任何情况下,避免定义谓词(^)/2都是一个好主意。

(^)/2 - power (^)/2 - 功率

This is an evaluable functor accessible via (is)/2 and arithmetic comparison like (=:=)/2 and (>)/2 .这是一个可评估的函子,可通过(is)/2和算术比较(=:=)/2(=:=)/2(>)/2 Also library(clpfd) uses it with this meaning. library(clpfd)也用这个意思来使用它。 In contrast to (**)/2 which always results in a float, 2^2 is an integer - thereby permitting arithmetics with bigints.与总是产生浮点数的(**)/2相比, 2^2是一个整数 - 从而允许使用 bigint 进行算术运算。 Just try ?- X is 7^7^7.试试?- X is 7^7^7. to see if your system supports them.看看你的系统是否支持它们。

Finally, there are user defined uses for (^)/2 that do not collide with above uses like lambda expressions via library(lambda) (source ).最后,用户定义的(^)/2使用不会与上述使用相冲突,例如通过library(lambda) (source ) 使用 lambda 表达式。


There are a few general remarks about its use.关于它的使用有一些一般性的说明。 (^)/2 associates to the right which means that: (7^7^7) = (7^(7^7)) . (^)/2与右侧相关联,这意味着: (7^7^7) = (7^(7^7)) It has a very low priority which means that you have to use brackets for arguments with standard operators.它的优先级非常低,这意味着您必须使用方括号作为标准运算符的参数。

In math expressions, ^ is exponentiation, it's just different notation for **.在数学表达式中,^ 是取幂,它只是 ** 的不同表示法。

In lambda expressions, it is a parameter-passing operator.在 lambda 表达式中,它是一个参数传递运算符。

As in Pereira and Shieber's book:正如 Pereira 和 Shieber 的书中所说:

Thus the lambda expression λ x.因此 lambda 表达式 λ x。 x + 1 would be encoded in Prolog as X^(X+1). x + 1 将在 Prolog 中编码为 X^(X+1)。 Similarly, the lambda expression λ x.类似地,lambda 表达式 λ x。 λ y.wrote(y, x) would be encoded as the Prolog term X^Y^wrote(Y,X), assuming right associativity of "^" λ y.wrote(y, x) 将被编码为 Prolog 项 X^Y^wrote(Y,X),假设“^”的右结合

In Prolog, most symbols can be used 'uninterpreted', at syntactic level, in particular after an op/3 declaration, any atom can be used as operator .在 Prolog 中,大多数符号都可以“未解释”地使用,在语法级别,特别是在op/3声明之后,任何原子都可以用作operator Then you can use, for instance, ^/2 as a function constructor for a domain specific language (a DSL), with a semantic specified from your rules.然后,例如,您可以使用^/2作为域特定语言(DSL)的函数构造函数,并根据您的规则指定语义。

Is SWI-Prolog (or more generally in ISO Prolog), current_op/3 gives you information about declared operators:是 SWI-Prolog(或更一般地在 ISO Prolog 中), current_op/3为您提供有关声明运算符的信息:

?- current_op(X,Y,^).
X = 200,
Y = xfy. 

That said, any Prolog implementing setof/3 is expected to interpret ^/2 as a quantification specifier, when put to decorate the 2 nd argument.也就是说,当用于装饰第二个参数时,任何实现setof/3 Prolog 都应该将^/2解释为量化说明符。 As well, any Prolog implementing is/2 is expected to interpret ^/2 as exponentiation, when occurring on the right side of the is/2 expression.同样,当出现在is/2表达式的右侧时,任何实现is/2 Prolog 都应将^/2解释为幂运算。

Here's my addition to the use of ^ in setof/3 and bagof/3 .这是我在setof/3bagof/3使用^ bagof/3

Upfront note :前期注意

Personally, I consider the semantics of ^ to be a failure, because it looks as if this were an "existential quantification" and is even described as such sometimes (for example: GNU Prolog , SWI-Prolog library(yall) ) but it actually is NOT .就个人而言,我认为^的语义是失败的,因为它看起来好像是“存在量化”,有时甚至被描述为这样(例如: GNU PrologSWI-Prolog library(yall) )但实际上不是 Avoid this misfeature , write a separate predicate to be called by setof/3 and bagof/3 instead.避免这种错误功能,编写一个单独的谓词由setof/3bagof/3调用。 An ISO Prolog-2, if it ever happens, should really clean this up. ISO Prolog-2,如果发生的话,应该真正清理它。

We start with an overview ASCII Image:我们从概览 ASCII 图像开始:

                                 Clause-wide variable
                                         |
                                         |
                +------------------------+------------------------+
                |                                                 |
                |          Clause-wide variables                  |
                |          that are collected via the             |
                |          template at arg-position 1 by          |
                |          setof/3 (NOT local to setof/3)         |
                |          thus can be constrained elsewhere      |
                |          in the clause (possibly accidentally)  |
                |                           |                     |
                |                           |                     |                
                |                +-+--------+----------+-+        |
                |                | |                   | |        |
                |                | |                   | |        |            
get_closed_set(Set,K) :- setof( [X,Y] , P^R^search(P,R,X,Y,K) , Set).
                   |                    | |        | |     |
                   |                    <-------------------> Goal expression 
                   |                    | |        | |     |
                   |                    | |        | |     |                   
                   +---------------------------------------+-----+                    
                                        | |        | |           |
                                        | |        | |           |
                                        +-+----+---+-+          Clause-wide variable.
                                               |                Backtracking over this
                                               |                is done by the caller
                                               |                of get_closed_set/2.
                                               |
                                       Variables marked as "free for
                                       backtracking if fresh".
                                       This is NEARLY the same as "being
                                       local to the goal expression" or
                                       "being existentially quantified."
                                       Backtracking over these is done by setof/3.
                                       If these appear elsewhere in the clause,
                                       they be constrained (possibly accidentally)!

Test Cases for Expected Behaviour预期行为的测试用例

search(1,n,a,g).
search(2,m,a,g).

search(2,m,a,j).
search(1,m,a,j).
search(3,w,a,j).
search(3,v,a,j).

search(2,v,b,g).
search(3,m,b,g).
search(5,m,b,g).

search(2,w,b,h).


% ===
% HATTY EXPRESSIONS ("CLOSED EXPRESSIONS")
% ===

% If P and R do not appear anywhere else than in the goal expression.
% "P^R^" (not quite) closes off variables P,R: they are not (not quite) 
% invisible outside of the goal expression "P^R^search(P,R,X,Y)"

get_closed_set(Set) :- setof( [X,Y] , P^R^search(P,R,X,Y) , Set).
get_closed_bag(Bag) :- bagof( [X,Y] , P^R^search(P,R,X,Y) , Bag).

% The above is the same as this (which I recommend for clarity and
% to avoid annoying bug searches):

indirect_search(X,Y) :- search(_P,_R,X,Y).

get_closed_set_indirect(Set) :- setof( [X,Y] , indirect_search(X,Y) , Set).
get_closed_bag_indirect(Bag) :- bagof( [X,Y] , indirect_search(X,Y) , Bag).

% ===
% NONHATTY EXPRESSIONS ("OPEN EXPRESSIONS")
% ===

get_open_set(Set,P,R) :- setof( [X,Y] , search(P,R,X,Y) , Set).
get_open_bag(Bag,P,R) :- bagof( [X,Y] , search(P,R,X,Y) , Bag).

% ===
% TESTING
% ===

:- begin_tests(hat_operator).

test(clo_set)     :- get_closed_set(Set),
                     format("Closed Set:\n  ~q\n",[Set]),
                     Set = [[a,g],[a,j],[b,g],[b,h]].

test(clo_bag)     :- get_closed_bag(Bag),
                     format("Closed Bag:\n  ~q\n",[Bag]),
                     Bag = [[a,g],[a,g],[a,j],[a,j],[a,j],[a,j],[b,g],[b,g],[b,g],[b,h]].

test(clo_set_ind) :- get_closed_set_indirect(Set),
                     format("Closed Set, indirect:\n  ~q\n",[Set]),
                     Set = [[a,g],[a,j],[b,g],[b,h]].

test(clo_bag_ind) :- get_closed_bag_indirect(Bag),
                     format("Closed Bag, indirect:\n  ~q\n",[Bag]),
                     Bag = [[a,g],[a,g],[a,j],[a,j],[a,j],[a,j],[b,g],[b,g],[b,g],[b,h]].

test(opn_set)     :- bagof(solution(Set,P,R), get_open_set(Set,P,R), OuterBag),
                     format("Bag for get_open_set/3:\n  ~q\n",[OuterBag]).

test(opn_bag)     :- bagof(solution(Bag,P,R), get_open_bag(Bag,P,R), OuterBag),
                     format("Bag for get_open_bag/3:\n  ~q\n",[OuterBag]).

:- end_tests(hat_operator).

rt :- run_tests(hat_operator).

When we run rt , nothing unexpected occurs, we are like Fonzi with existential quantifiers:当我们运行rt ,没有任何意外发生,我们就像带有存在量词的 Fonzi:

Closed Set:            [[a,g],[a,j],[b,g],[b,h]]

Closed Bag:            [[a,g],[a,g],[a,j],[a,j],[a,j],[a,j], 
                        [b,g],[b,g],[b,g],[b,h]]

Closed Set, indirect:  [[a,g],[a,j],[b,g],[b,h]]

Closed Bag, indirect:  [[a,g],[a,g],[a,j],[a,j],[a,j],[a,j],
                        [b,g],[b,g],[b,g],[b,h]]

Bag for get_open_set/3:  [solution([[a,j]],1,m),solution([[a,g]],1,n),
                          solution([[a,g],[a,j]],2,m),solution([[b,g]],2,v),
                          solution([[b,h]],2,w),solution([[b,g]],3,m),
                          solution([[a,j]],3,v),solution([[a,j]],3,w),
                          solution([[b,g]],5,m)]

Bag for get_open_bag/3:  [solution([[a,j]],1,m),solution([[a,g]],1,n),
                          solution([[a,g],[a,j]],2,m),solution([[b,g]],2,v),
                          solution([[b,h]],2,w),solution([[b,g]],3,m),
                          solution([[a,j]],3,v),solution([[a,j]],3,w),
                          solution([[b,g]],5,m)]

Trying out behaviour for less obvious expressions尝试不太明显的表达的行为

You may have to run this to see more list output (case of SWI-Prolog):您可能必须运行它才能看到更多列表输出(SWI-Prolog 的情况):

set_prolog_flag(answer_write_options,[max_depth(100)]).
set_prolog_flag(debugger_write_options,[max_depth(100)]).

Singletons in goal expression目标表达中的单例

If you enter the following, Prolog correctly warns about "singleton variables P,R".如果输入以下内容,Prolog 会正确警告“单个变量 P,R”。 Good.好的。

get_open_set(Set) :- setof([X,Y],search(P,R,X,Y),Set).

Hats outside of setof/3 or bagof/3 setof/3 或 bagof/3 之外的帽子

This is accepted and could be given a meaning, but Prolog will be looking for procedure ^/2 on call and say that "^/2 can only appear as the 2nd argument of setof/3 and bagof/3" .这是可以接受的并且可以赋予含义,但是 Prolog 将在调用时查找过程^/2并说"^/2 只能作为 setof/3 和 bagof/3 的第二个参数出现" Okay.好的。

get_outerly_closed_set(Set) :- P^R^setof([X,Y],search(P,R,X,Y),Set).

A possible meaning for the above might be the utterly mundane:上述可能的含义可能是完全平凡的:

get_outerly_closed_set(Set) :- close_it_off(Set).
close_it_off(Set) :- setof([X,Y],search(_P,X,_R,Y),Set).

Closed-off variable used elsewhere in clause: Problematic!子句中其他地方使用的封闭变量:有问题!

Now we are getting into "failure of semantics" territory: Prolog does not consider the outside P as a variable different from the P in P^ .现在,我们正在进入领土“的语义失败”:序言不考虑外部P从一个变量不同的PP^ This is why P^ does NOT mean "∃P such that" :这就是为什么P^不意味着“∃P 使得”

get_closed_set_weird_1(Set,P) :- 
   setof( [X,Y] , P^R^search(P,R,X,Y) , Set),
   format("P=~q\n",[P]).
?- get_closed_set_weird_1(Set,P).
P=_14996
Set = [[a, g], [a, j], [b, g], [b, h]].

?- get_closed_set_weird_1(Set,1).
P=1
Set = [[a, g], [a, j]].

Variation of closed-off variable used elsewhere in clause: Problematic!子句中其他地方使用的封闭变量的变化:有问题!

No warnings occur if you write such a thing:如果你写这样的东西,不会出现警告:

get_closed_set_weird_2(Set) :-
   setof( [X,Y,P], P^R^search(P,R,X,Y), Set).
?- get_closed_set_weird_2(Set).
Set = [[a, g, 1], [a, g, 2], [a, j, 1], [a, j, 2], [a, j, 3], ...

In fact, P^ ends up being ignored.事实上, P^最终被忽略。 The above is the same as:上面是一样的:

get_closed_set_weird_2e(Set) :-
   setof( [X,Y,P], R^search(P,R,X,Y), Set).

Free variable over which to range used elsewhere in clause: Problematic!子句中其他地方使用的自由变量:有问题!

This is entirely expected behaviour, but a casual reading of setof([X,Y], ... would lead one to think that [X,Y] are free variables over which setof/3 ranges. This is not the case: [X,Y] is just a template and X and Y are actually clause-wide variables, which can be constrained elsewhere:这完全是预期的行为,但是对setof([X,Y], ...的随意阅读会让人认为[X,Y]setof/3范围内的自由变量。事实并非如此: [X,Y]只是一个模板, XY实际上是子句范围的变量,可以在其他地方进行约束:

get_closed_set_weird_2(Set,X) :- 
   setof( [X,Y], P^R^search(P,R,X,Y) , Set),
   format("X=~q\n",[X]).
?- get_closed_set_weird_2(Set,X).
X=_20346
Set = [[a, g], [a, j], [b, g], [b, h]].

?- get_closed_set_weird_2(Set,b).
X=b
Set = [[b, g], [b, h]].

The above would have been more clear as上面的会更清楚,因为

get_closed_set_weird_2c(Set,V) :- 
   setof( [V,Y], close_it_off(V,Y), Set),
   format("V=~q\n",[V]).
close_it_off(X,Y) :- search(_P,_R,X,Y).
?- get_closed_set_weird_2c(Set,V).
V=_21682
Set = [[a, g], [a, j], [b, g], [b, h]].

but note that this is absolutely not the same as this, where we backtrack over V outside of setof/3 :但请注意,这绝对与此不同,我们在setof/3之外回溯V

get_closed_set_weird_2x(Set,V) :- 
   setof( [X,Y], close_it_off(V,X,Y), Set),
   format("V=~q\n",[V]).
close_it_off(V,X,Y) :- V=X,search(_P,_R,X,Y).
?- get_closed_set_weird_2x(Set,V).
V=a
Set = [[a, g], [a, j]], V = a ;
V=b
Set = [[b, g], [b, h]], V = b.

There should be acceptable notation应该有可接受的符号

One would like to have a clean way of indicating which variables of the goal expression are visible outside of the goal expression, which ones are not, and which ones to range over.人们希望有一种干净的方式来指示目标表达式的哪些变量在目标表达式之外可见,哪些不可见,以及哪些变量可以覆盖。

How about this:这个怎么样:

  • If there is a λX.如果存在λX. at the head of the goal expression, the X is visible outside the goal expression.在目标表达式的头部, X在目标表达式之外可见。 Any X elsewhere in the clause is the same X .子句中其他地方的任何X都是相同的X
  • If there is a ∃X.如果存在∃X. at the head of the goal expression, the X is invisible outside the goal expression.在目标表达式的头部, X在目标表达式之外是不可见的。 Any X elsewhere in the clause is a different X (you are then invited to proceed to rename by the editor).子句中其他地方的任何X都是不同的X (然后编辑邀请您继续重命名)。
  • Any X that appears in the goal expression without a preceding λX.出现在目标表达式中的任何X前面没有λX. or a ∃X.∃X. is a compiler error .编译器错误
  • You can put anything you want into the template, lambda-ed, or existentialized, or clause-global.你可以把任何你想要的东西放到模板中,lambda 化的,存在的,或者子句全局的。
  • The called goal ranges over any variables that it sees as fresh: either fresh ones appearing as λX.被调用的目标范围涵盖它认为是新鲜的任何变量:要么是新鲜的,表现为λX. and any variables appearing as ∃X.以及任何出现为∃X.变量∃X.

(Don't complain about the lowercase x above; it just looks that way. λX. ∃X. Xx ) (不要抱怨上面的小写x ;它看起来就是这样λX. ∃X. Xx

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

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