【问题标题】:Making Prolog code that works in GNU and SWI制作适用于 GNU 和 SWI 的 Prolog 代码
【发布时间】:2013-06-10 23:57:39
【问题描述】:

我知道这会有限制,但是有没有一种合理的方法可以在 Prolog 代码中放入条件指令,以便在 GNU 或 SWI 中合理地工作?我在考虑至少最简单的情况,其中内置谓词(例如 SWI 中的 sumlist 和 GNU 中的 sum_list )在拼写上不匹配。或者 SWI 有 assert 但 GNU 没有。所以最好有类似的东西:

:- if($SWI).
SWI version of stuff
:- else.
GNU version of stuff
:- endif.

或者简单地说:

:- if(not_a_builtin(sumlist))
sumlist(L, S) :- sum_list(L, S).
:- endif.

或者什么不是。两种语言中都存在条件指令,但似乎没有提供执行此类操作所需的条件。我可能遗漏了一些手动搜索没有出现的东西。

【问题讨论】:

    标签: prolog swi-prolog portability gnu-prolog iso-prolog


    【解决方案1】:

    GNU Prolog 和 SWI-Prolog 的最新版本都定义了一个名为 dialect 的标志(顺便说一句,这是一个事实上的标准,因为它已被大多数 Prolog 系统实现),您可以在条件编译指令中使用它:

    $ gprolog
    GNU Prolog 1.4.4 (64 bits)
    Compiled Apr 23 2013, 17:24:33 with /opt/local/bin/gcc-apple-4.2
    By Daniel Diaz
    Copyright (C) 1999-2013 Daniel Diaz
    | ?- current_prolog_flag(dialect, Dialect).
    
    Dialect = gprolog
    
    yes
    
    $ swipl
    Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.3.16-6-g9c0199c-DIRTY)
    Copyright (c) 1990-2013 University of Amsterdam, VU Amsterdam
    SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
    and you are welcome to redistribute it under certain conditions.
    Please visit http://www.swi-prolog.org for details.
    
    For help, use ?- help(Topic). or ?- apropos(Word).
    
    ?- current_prolog_flag(dialect, Dialect).
    Dialect = swi.
    

    因此,简单的写如下:

    :- if(current_prolog_flag(dialect, swi)).
    
        % SWI-Prolog specific code
    
    :- elif(current_prolog_flag(dialect, gprolog)).
    
        % GNU Prolog specific code
    
    :- else.
    
        % catchall code
    
    :- endif.
    

    【讨论】:

    • 正是我想要的。谢谢。
    • 我在回答同样的问题,然后决定进行测试,我的 gprolog(不是由源代码安装的)引发了异常。 dialect 这是要走的路。
    • 即使这样,也有限制。 Prolog 版本中让我有点抓狂的区别是format 谓词,或一般的输出格式。 ISO prolog 的输出能力很差,而且从我在 SWI 和 GNU 之间看到的情况来看,Prolog 的每个版本似乎都朝着自己的方向发展。
    • 与提供这些谓词的其他 Prolog 系统相比,GNU Prolog 中的 format/2-3 谓词确实存在一些不幸且不兼容的差异。但是 B-Prolog、CxProlog、ECLiPSe、SICStus Prolog、SWI-Prolog、XSB 和 YAP(可能还有其他一些)提供了这两个谓词的合理兼容实现。
    • @mbratch:你在 GNU 的 format/2,3 中缺少什么?我假设像~20| 这样的格式化指令。这确实是 GNU 中的一个错误,您应该报告。
    【解决方案2】:

    可移植性是 Prolog 的最大弱点之一 - ISO 标准定义了 current_prolog_flag/2,但没有在标志中列出实现的“名称”。

    我使用以下代码在 SWI 和 YAP 之间切换

    swi :- prolog_impl(swi).
    yap :- prolog_impl(yap).
    
    prolog_impl(K) :-
        F =.. [K,_,_,_,_],
        current_prolog_flag(version_data, F).
    

    然后像这样使用它

    :- if(swi).
    
     gen_hash_lin_probe(Key, HashTable, Value) :-
        arg(_, HashTable, E),
        nonvar(E),
        E = Key-Value.
    
    :- elif(yap).
    
     gen_hash_lin_probe(Key, HashTable, Value) :-
        HashTable =.. [htlp|Args],
        nth1(_, Args, E),
        nonvar(E),
        E = Key-Value.
    
    :- endif.
    

    但 GNU 没有定义 version_data。那么该代码应该或多或少地扩展为

    ...
       catch(current_prolog_flag(version_data,F),_,K = gnu).
    

    (注:未测试)

    要测试内置函数的存在,有 predicate_property/2(AFAIK 不是 ISO),您需要像往常一样进行试验以确定实际行为。

    OT:sumlist/2 已弃用,有 sum_list/2

    【讨论】:

    • sum_list/2 在 SWI-Prolog 6.0.2 中对我不起作用。我明白了,ERROR: toplevel: Undefined procedure: sum_list/2 (DWIM could not correct goal)sumlist/2 工作。
    • 因为我优先使用 Linux,所以我会从源代码更新构建 SWI-Prolog。可能 sumlist/2 最近在 backcomp 库中消失了。我刚刚报告了文档页面中的注释。抱歉打扰了。
    • CapelliC,我一直很感激你的回答。感谢sumlist 的提醒。没必要道歉。我也在使用 Linux,但我只是使用最新的可用 yum 安装。
    【解决方案3】:

    dialect 标志最适合测试底层系统。然而,GNU Prolog 也提供了version_data。顺便说一句:使用version_dataprolog_impl 的更好定义是:

    prolog_impl(K) :-
        current_prolog_flag(version_data, F),
        functor(F, K, _).
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-02
      • 2012-04-06
      • 1970-01-01
      相关资源
      最近更新 更多