Macros 术语列表的术语扩展

Macros 术语列表的术语扩展,macros,prolog,prolog-defaulty,Macros,Prolog,Prolog Defaulty,假设我想有一些规则都遵循相同的模式。当我想通过显式列出所有可能的第一个参数来避免非确定性行为时,我遇到了这种情况。然而,我知道,对于某些可能性,我需要做完全相同的事情。解决这一问题的一种方法是在结尾处加上一个全面的条款: foo(a) :- /* do something */. foo(b) :- /* do something else*/. foo(_). /* ignore the rest */ 但这不是很好,因为我不知道是否得到了意外的输入,或者我的程序是否出错。为了避免这种情况,

假设我想有一些规则都遵循相同的模式。当我想通过显式列出所有可能的第一个参数来避免非确定性行为时,我遇到了这种情况。然而,我知道,对于某些可能性,我需要做完全相同的事情。解决这一问题的一种方法是在结尾处加上一个全面的条款:

foo(a) :- /* do something */.
foo(b) :- /* do something else*/.
foo(_). /* ignore the rest */
但这不是很好,因为我不知道是否得到了意外的输入,或者我的程序是否出错。为了避免这种情况,我还可以说

foo(X) :- memberchk(X, [ /* list of possible values of X */ ]).
但是,我现在再次反对Prolog的确定性行为,并在论证成立时建立索引

因此,相反,我做了这样的事情:

term_expansion(foos(Foos), Foo_rules) :-
    maplist(expand_foo, Foos, Foo_rules).

expand_foo(Foo, foo(Foo)).
other_foos([x,y,z]).
问题是,我试图找到像这样的现有代码,但我找不到。是因为我做错了什么吗?有没有更好的方法来解决这个问题?还是完全绕过它

我不介意回答说“你在解决错误的问题”

编辑:一些谷歌搜索实际上让我从SWI Prolog文档中看到了这个非常类似的示例:


(在最下面)

首先对您已经建议的变体发表一些评论:

foo(a) :- /* do something */.
foo(b) :- /* do something else */.
foo(_).   /* ignore the rest */
这方面的主要问题是,最后一个子句(
foo()
)适用于其他可能更专业的子句。因此查询
?-foo(a)。
现在无意中是不确定的

你说这个版本“不是很好,因为我实际上不知道是否有意外的输入,或者我的程序是否出错”。我们可以通过在check all子句中确保给定的术语不是意外的来防止意外输入:

foo(a) :- /* do something */.
foo(b) :- /* do something else */.
foo(X) :- must_be(oneof([a,b,x,y], X).
当术语的形式意外时,这会引发错误。我用
x
y
作为例子,来说明没有特别处理的术语。请注意,当然必须包括
a
b
,因为该条款(再次)也适用于这两个条款。谓词即使在其参数被实例化时仍然是不确定的,因为第一个参数索引不能区分这些情况。你写了“我现在反对Prolog的确定性行为和索引,当论点成立时”,这可能(正确地)意味着当你使用这种表示法时,你不能从这些特性中获益

现在是一个很好的声明性解决方案:每当您试图引入“catch all”或“default”子句时,请重新考虑您的数据表示,并针对可能应用的不同情况引入不同的函子。在您的示例中,这两种情况是:

  • 这个术语需要以特殊的方式处理
  • 这个术语不需要做任何特殊的处理
  • 我将使用
    特殊()
    普通()
    来区分这些情况。因此:

    foo(special(S)) :- foo_special(S).
    foo(ordinary(_)). % do nothing
    
    foo_special(a) :- /* do something      */
    foo_special(b) :- /* do something else */
    

    这些谓词可以在所有方向上使用,并且在参数已知时具有确定性。类型检查可以很容易地添加。

    我喜欢这个建议(+1),但这是否意味着我需要在上一步中明确地处理我的
    a
    b
    x
    y
    ?在我的特殊情况下,我解析文本;然后,在这一点上,我将不得不有每一个默认和特殊情况明确处理以及。。。。实际上,我正在标记标签!此外,请参见编辑后的问题以了解先例。是的,在程序中通常会有一个小的早期步骤,您可以将默认结构转换为非默认结构,通常是在收到用户输入(来自文件或终端)后直接转换。这一部分通常会使用非单调的控制结构,如if-then-else、cuts等,但好的一面是:一旦数据被清晰地表示出来,它就可以通过模式匹配在整个(大的)程序的其余部分进行专门处理!您正在标记数据,而不是标记。SWI Prolog文档中的示例并不完全适用:它详尽地列举了所有案例,不需要默认案例。@mat是的,但我想的是列举默认案例的可能参数……如果可能的话,我也会这么做。