【问题标题】:Can we create a fact from inside the Prolog code?我们可以从 Prolog 代码中创建一个事实吗?
【发布时间】:2016-10-02 19:15:39
【问题描述】:

我的目标是打破给定的列表列表,以便我能够访问同名的各个列表。我有以下列表:-

mylist([[1,2],[2,3],[3,4],[4,6]]).

我想将列表分成 [1,2]、[2,3]、[3,4]、[4,6],以便我可以单独访问这些项目(如 [1,2])。

为此,我可以从分离的列表元素中创建一个新事实吗?我能够将元素分成单独的列表。但是,我想将这些单独的列表转换为事实。喜欢:-

mylist([[1,2],[2,3],[3,4],[4,6]]).

应该变成如下:-

node([1,2]).
node([2,3]).
node([3,4]).
node([4,6]).

然后我应该能够使用“节点”访问每个列表。

【问题讨论】:

  • 参见assertz/1 以及编译时术语扩展,使用term_expansion/2

标签: list prolog


【解决方案1】:

另一个答案很好(尤其是forall 解决方案),但是如果您在编译时知道您的列表,并且想在编译时将node/1 事实添加到数据库中,那么您可以这样做。

此代码是从this page 最底部的示例简化而来的:

在你的文件中(我称之为nodes.pl):

term_expansion(nodes_list(NL), Nodes) :-
        maplist(to_node, NL, Nodes).

to_node(X, node(X)).

nodes_list([[1,2],[2,3],[3,4],[4,6]]).

当我查阅文件时,我得到:

?- [nodes].
true.

?- listing(node).
node([1, 2]).
node([2, 3]).
node([3, 4]).
node([4, 6]).

true.

两个细节:

  1. 扩展谓词(此处为 nodes_list/1不会进入数据库。
  2. term_expansion/2 的子句必须在源文件中nodes_list/1 的定义之前。

【讨论】:

    【解决方案2】:

    CapelliC 推荐(在 cmets 中)的一个很好的答案(也许是最好的)是:

    ?-forall(member(X,[[1,2],[2,3],[3,4]]),assertz(node(X))).
    

    你也可以写:

    my_list(L):- member(X,L),assertz(node(X)).
    

    例子:

    ?- my_list([[1,2],[2,3],[3,4]]).
    true ;
    true ;
    true.
    ?- node([1,2]).
    true ;
    false.
    

    感谢 CapelliC 的建议的另一种方法是:

    ?- maplist(X>>assertz(node(X)), [[1,2],[2,3],[3,4]]).
    

    【讨论】:

    • 可能:'?- maplist(X>>assertz(node(X)), [[1,2],[2,3],[3,4]]).`跨度>
    • 是的,这是一个很好的实现,感谢您指出我将编辑答案。
    • ?-forall(member(X,[[1,2],[2,3],[3,4]]),assertz(node(X))). 会像 lambda+maplist 解决方案一样更便携,更高效
    • 再次感谢,我没想过使用 forall/2 谢谢!!
    • 您应该将forall 解决方案放在顶部,这是最惯用的实现方式。您还可以查看here 以获得更多解释,以及assertz 的示例。
    猜你喜欢
    • 2014-06-29
    • 2012-04-22
    • 1970-01-01
    • 2019-09-27
    • 2011-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多