应用半上下文传递附加参数 [英] Applying semicontext for passing additional arguments

查看:109
本文介绍了应用半上下文传递附加参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是来自Mat的问题的后续问题.com/a/42722823/1243762> answer

This is a follow-on question from an earlier question from Mat's answer

从此开始

e([number(0)]           , t1        , Uc0    , Uc0, Bc0    , Bc0) --> [].
e([number(1)]           , t2        , Uc0    , Uc0, Bc0    , Bc0) --> [].
e([number(2)]           , t3        , Uc0    , Uc0, Bc0    , Bc0) --> [].

e([op(neg),[Arg]]       , u1(E)     , [_|Uc0], Uc1, Bc0    , Bc1) --> 
    [_],   
    e(Arg , E , Uc0, Uc1, Bc0, Bc1).
e([op(ln),[Arg]]        , u2(E)     , [_|Uc0], Uc1, Bc0    , Bc1) --> 
    [_],   
    e(Arg , E , Uc0, Uc1, Bc0, Bc1).

e([op(add),[Left,Right]], b1(E0,E1) , Uc0    , Uc2, [_|Bc0], Bc2) --> 
    [_,_], 
    e(Left, E0, Uc0, Uc1, Bc0, Bc1), 
    e(Right, E1, Uc1, Uc2, Bc1, Bc2).
e([op(sub),[Left,Right]], b2(E0,E1) , Uc0    , Uc2, [_|Bc0], Bc2) --> 
    [_,_], 
    e(Left, E0, Uc0, Uc1, Bc0, Bc1), 
    e(Right, E1, Uc1, Uc2, Bc1, Bc2).

e(U,B,EL,Es) :-
    length(UL, U),
    length(BL, B),
    phrase(e(EL,Es,UL,[],BL,[]), _).

e(N,EL,Es) :-
    length([_|Ls], N),
    phrase(e(EL,Es,_,[],_,[]),Ls).

e_count(E, Count) :-
    length([_|Ls], E),
    findall(., phrase(e(_,_,_,[],_,[]), Ls), Sols),
    length(Sols, Count).

然后阅读

对于一个变量,请使用包含单个元素的列表,该元素仅包含 该变量.如果您要传递多个变量,请使用 包含形式为f(...)的单个术语的列表,捕获所有 您想要传递的变量.这也很值得 自己的问题.

For one variable, use a list with a single element that contains just that variable. If you want to pass around more than one variable, use a list that contains a single term of the form f(...), capturing all variables you want to pass around. This is also well worth its own question.

演变成这个

e( f([number(0)], t1, Uc0, Uc0, Bc0, Bc0) ) --> [].
e( f([number(1)], t2, Uc0, Uc0, Bc0, Bc0) ) --> [].
e( f([number(2)], t3, Uc0, Uc0, Bc0, Bc0) ) --> [].

e( f([op(neg), [Arg]], u1(E), [_|Uc0], Uc1, Bc0, Bc1) ) --> 
    [_], 
    e( f(Arg, E, Uc0, Uc1, Bc0, Bc1) ).
e( f([op(ln) , [Arg]], u2(E), [_|Uc0], Uc1, Bc0, Bc1) ) --> 
    [_], 
    e( f(Arg, E, Uc0, Uc1, Bc0, Bc1) ).

e( f([op(add), [Left,Right]], b1(E0,E1) ,Uc0, Uc2, [_|Bc0], Bc2) ) --> 
    [_,_], 
    e(f(Left, E0, Uc0, Uc1, Bc0, Bc1) ), 
    e(f(Right, E1, Uc1, Uc2, Bc1, Bc2) ).
e( f([op(sub), [Left,Right]], b2(E0,E1) ,Uc0, Uc2, [_|Bc0], Bc2) ) --> 
    [_,_],
    e(f(Left, E0, Uc0, Uc1, Bc0, Bc1) ),
    e(f(Right, E1, Uc1, Uc2, Bc1, Bc2) ).

e(U,B,EL,Es) :-
    length(UL, U),
    length(BL, B),
    phrase(e(f(EL,Es,UL,[],BL,[])), _).

e_N(N,EL,Es) :-
    length([_|Ls], N),
    phrase(e(f(EL,Es,_,[],_,[])),Ls).

e_count(E, Count) :-
    length([_|Ls], E),
    findall(., phrase(e(f(_,_,_,[],_,[])), Ls), Sols),
    length(Sols, Count).

哪个有效,但记为use a list that contains a single term of the form f(...),此处f(...)不在列表中.

which works but it is noted use a list that contains a single term of the form f(...), and here f(...) is not in a list.

我在某个地方出错了吗?

Did I go wrong somewhere?

  • Thinking in States by Markus Triska
  • Prolog DCG Primer by Markus Triska
  • Extra Arguments with Learn Prolog Now!

通常在使用

ISO/IEC DTR 13211–3:2006限定子句语法规则

6.1.3终端序列的变量名约定

6.1.3 Variable names convention for terminal-sequences

此TR使用名为S0,S1,...,S的变量表示末端序列 在处理语法规则或扩展时用作参数 语法规则分为子句.在此符号中,变量S0,S1, ...,S可以视为状态序列,其中S0表示 初始状态和代表最终状态的变量S. 因此,如果变量Si表示给定条件下的末端序列 状态,变量Si + 1将代表剩余的 用语法规则解析Si后的末端序列.

This TR uses variables named S0, S1, ..., S to represent the terminal-sequences used as arguments when processing grammar rules or when expanding grammar rules into clauses. In this notation, the variables S0, S1, ..., S can be regarded as a sequence of states, with S0 representing the initial state and the variable S representing the final state. Thus, if the variable Si represents the terminal-sequence in a given state, the variable Si+1 will represent the remaining terminal-sequence after parsing Si with a grammar rule.

推荐答案

DCG 总是描述一个列表.

但是哪个列出? 您必须决定如何使用专用机制

在上述情况下,似乎您已经专门使用 DCG来描述列表,该列表的长度用作衡量搜索深度的方式.

In the above cases, it seems you have already dedicated DCGs to describe a list whose length you use as a measure for the depth of the search.

这完全可以,并且非常自然地使用了DCG.

That's completely OK, and a very natural use of DCGs.

但是,您只能描述一个列表,而不是两个列表,至少不能以主要"方式描述.当然,您可以通过DCG 参数同时描述任意多个术语.但是,DCG的 body 仅限于通过调用非终端并使用终端来描述一个列表.

However, you can only describe one list, not two at the same time, at least not in the "primary" way. You can of course describe arbitrarily many terms at the same time via DCG arguments. However, the DCG body is limited to describing just one list, by invoking nonterminals, and using terminals.

有一种直接的方法可以将DCG转换为常规的Prolog代码,而无需 DCG,或通过常规的Prolog解释DCG规则.有关更多信息,请参见例如ISO草案.

There is a straight-forward way to convert DCGs to regular Prolog code without DCGs, or to interpret DCG rules via regular Prolog. See for example the ISO draft for more information.

例如,让我们来看看以下片段:

For example, let us take just this snippet:


e( f([op(neg), [Arg]], u1(E), [_|Uc0], Uc1, Bc0, Bc1) ) --> 
    [_], 
    e( f(Arg, E, Uc0, Uc1, Bc0, Bc1) ).
e( f([op(ln) , [Arg]], u2(E), [_|Uc0], Uc1, Bc0, Bc1) ) --> 
    [_], 
    e( f(Arg, E, Uc0, Uc1, Bc0, Bc1) ).

让我们摆脱DCG语法,并将其写为 例如:

Let's get rid of the DCG syntax, and write it for example as:


e( f([op(neg), [Arg]], u1(E), [_|Uc0], Uc1, Bc0, Bc1, [_|Rest0], Rest) ) :- 
    e( f(Arg, E, Uc0, Uc1, Bc0, Bc1, Rest0, Rest) ).
e( f([op(ln) , [Arg]], u2(E), [_|Uc0], Uc1, Bc0, Bc1, [_|Rest0], Rest) ) :- 
    e( f(Arg, E, Uc0, Uc1, Bc0, Bc1, Rest0, Rest) ).

(当然,请注意,您不应依赖任何特定的扩展方法,但始终使用phrase/2接口来调用DCG.不过,以上是一个执行这种扩展的方式,获得常规的Prolog代码.)

(Note of course that you should not rely on any particular expansion method, but always use the phrase/2 interface to invoke a DCG. Still, the above is one way to perform such an expansion, obtaining regular Prolog code.)

假设我们想再次 使用DCG表示法,因为它是如此方便.例如,当使用DCG表示法时,我们显然需要考虑更少的变量,而这本身已经是一个巨大的优势.

Suppose we want to go back to using DCG notation again, because it is so convenient. For example, we obviously need to think about fewer variables when using DCG notation, and that can in itself already be a huge advantage.

因此,我们当然可以返回到初始DCG,使用终端而不是我们引入的用于描述列表差异的最后两个新参数.

So, we can of course go back to our initial DCG, using terminals instead of our last two new arguments that we introduced to describe a list difference.

但是我们也可以做其他事情

例如,在上面的代码片段中,我们注意到Bc0Bc1穿过:没有一个子句真正关心这些参数.因此,假设我们专用于DCG的机制来描述这两个论点.

For example, in the snippet above, we note that Bc0 and Bc1 are only threaded through: None of the clauses really cares about these arguments. So, suppose we dedicate the DCG mechanism to describe these two arguments.

例如,它可能如下所示:

This could for example look as follows:


e( f([op(neg), [Arg]], u1(E), [_|Uc0], Uc1, [_|Rest0], Rest) ) -->
    e( f(Arg, E, Uc0, Uc1, Rest0, Rest) ).
e( f([op(ln) , [Arg]], u2(E), [_|Uc0], Uc1, [_|Rest0], Rest) ) -->
    e( f(Arg, E, Uc0, Uc1, Rest0, Rest) ).

在这里,我从常规的Prolog版本开始,引入了DCG表示法,只是将Bc0Bc1转换为隐式参数!它们不再在此处全部出现.仅当我们再次将其扩展回Prolog时,它们才可见,或者至少这是一种的实现方式.

Here, I have started from the regular Prolog version, introduced DCG notation, and simply turned Bc0 and Bc1 into the implicit arguments! They no longer appear at all here. Only if we again expand this back into Prolog do they become visible, or at least that's one way to do it.

但是,仍然存在两个问题:

But, there are two problems that remain:

首先,如果我们实际上想要访问这些参数怎么办?当然不是 all 子句只能像这样通过它们.我们还需要在某个地方访问.其次,还有一个更根本的问题:我们想谈一个单一的论点,可以是 any  term ,但是DCG总是描述一个 list

First, what if we actually want to access these arguments? Certainly not all clauses only thread them through like this. We also need to access them somewhere. And second, there's an even more fundamental problem: We want to talk about a single argument, which can be any term, but DCGs always describe a list!

那么,我们如何调和所有这一切?

So, how do we reconcile all this?

最重要的是,我们需要讨论列表,因此解决方案很简单:让我们讨论一个具有单个元素的列表,即列表[Bc0][Bc1] .在这种情况下,这使得DCG标记在所有情况下都适用.

Most importantly, we need to talk about lists, so the solution is simple: Let us talk about a list with a single element, i.e., the list [Bc0] and [Bc1]. This makes DCG notation applicable at all in this case.

接下来,我们如何表达DCG中Bc0Bc1之间的关系?为此,我们使用 semicontext表示法:它是在谈论先前不在我们描述的列表中的元素.

Next, how do we express the relation between Bc0 and Bc1 within the DCG? For this, we use semicontext notation: It lets as talk about elements that previously were not in the list we are describing.

如DCG入门中所述,以下形式的非末端将是有用的:

As noted in the DCG primer, a nonterminal of the following form will be useful:


state(S0, S), [S] --> [S0].

您可以将非终结符state(S0, S)读为:当前状态为S0此后为,其为S.

You can read the nonterminal state(S0, S) as: The current state is S0, and henceforth it is S.

因此,如果您要实际访问Bc0并将其与您的子句中的Bc1相关联,则可以这样操作:

Thus, if you want to actually access Bc0 and relate it to Bc1 in one of your clauses, you could do it like this:


e( f([op(neg), [Arg]], u1(E), [_|Uc0], Uc1, [_|Rest0], Rest) ) -->
    state(Bc0, Bc1),
    ... (something involving Bc0 and Bc1) ...
    e( f(Arg, E, Uc0, Uc1, Rest0, Rest) ).

主要优点是:此符号使您可以隐藏其他参数,而 still 则允许您在需要时显式访问它们 ,使用state//2(或直接使用半文本表示法).

The major advantage is this: This notation lets you hide the additional arguments, and still lets you access them explicitly if you need it, using state//2 (or semicontext notation directly).

在代码中实际使用的参数越来越少,这显然变得越来越有吸引力.如果几乎所有子句都访问参数,则隐藏它们是没有意义的.但是,您经常会描述贯穿其中的术语,而只有很少的DCG子句实际访问它们.在这种情况下,请考虑使用DCG表示法隐式传递它们.

This obviously becomes more and more attractive the less the arguments are actually used in your code. If almost all of your clauses access the arguments, there is no sense in hiding them. However, quite frequently, you will describe terms that are threaded through while only very few of your DCG clauses actually access them. In such cases, consider using DCG notation to pass them around implicitly.

但是仍然存在一个问题:如果我们不仅要传递一个术语,还要传递两个或更多术语,该怎么办?有一个非常简单的解决方案:让我们仍然在列表中传递一个元素,但是让该元素只是形式为f(Arg1,Arg2,...,Arg_n) compound  term .因此,您对非终结符e//N的调用可能看起来像这样:

But there's still one problem: What to do if we want to pass around not only one term, but two or more? There's a very easy solution for this: Let us still pass around a list with a single element, but let that element simply be a compound term of the form f(Arg1,Arg2,...,Arg_n). Thus, your invocation of your nonterminal e//N might look like this:


?- phrase(e(Arg1,Arg2,...,Arg_N), [f(B1,B2,...,B_M)], [Result]).

在这里,B1B2等是您想隐式传递的参数,它们是列表形式,带有一个包含所有这些参数的单个元素.

Here, B1, B2 etc. are the arguments that you would like to pass around implicitly, in the form of a list with a single element that combines all these arguments.

假设这回答了您的问题,一个合适的标题可能是:应用半上下文符号来传递附加参数".实际问题很明确,在这种情况下,我认为至关重要的是,即使您已经专用于DCG表示法来描述其他内容,您仍希望应用半上下文表示法来传递其他参数.总而言之,一种解决方案是首先释放DCG表示法,以便您可以使用所描述的列表来传递其他参数.

Assuming this answers your question, a suitable title could be: "Applying semicontext notation for passing additional arguments". The actual question makes clear, and I think that is critical in this case, that you want to apply semicontext notation for passing additional arguments even though you have already dedicated the DCG notation to describe something else. To summarize, a solution for this is to first free the DCG notation so that you can use the described list for passing around additional arguments.

请注意,还有其他解决方案:例如,您可以设计自己的 own 自定义表示法,它完全类似于DCG表示法,但是扩展方式允许您描述两个独立列表.我将其保留为练习.

Note that there are also other solutions: For example, you can devise your own custom notation, completely analogous to DCG notation, but expanded in such a way that it lets you describe two independent lists at the same time. I leave this as an exercise.

这篇关于应用半上下文传递附加参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆