跳过/传递非标准的prolog代码

时间:2015-10-10 20:22:25

标签: prolog swi-prolog erlog

我在SWI-Prolog下开发,但我的目标是Erlog​​(https://github.com/rvirding/erlog)。我需要一种方法来使用非标准的Prolog语法。 有没有办法编写SWI编译器忽略的prolog代码,即使其不可见。

以下示例如何:

do_stuff(G,Amt) :- ecall(erlog_demo:efunc('Elixir.Blah':stuff({G,Amt})).

我在想是否有一种方法可让SWI跳过这一点,而我还有另一项声明无效。

do_stuff(_,_).

一个选项可能是对它进行注释,然后在Erlog​​中运行之前使用解析器删除注释,但这看起来很麻烦。

任何其他想法。

==

is_dialect(swi) :- catch(current_prolog_flag(dialect, swi), _, fail).
:- if(is_dialect(swi)).
    do_stuff(_,_).
:- else.
   do_stuff(G,Amt) :- ecall(erlog_demo:efunc('Elixir.Blah':stuff({G,Amt})).
:- endif.

语法错误:操作员期望

3 个答案:

答案 0 :(得分:3)

我使用这个成语来保持代码在不同的实现中运行

:- 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.

其中从该模块导入谓词swi / 0或yap / 0(prolog_impl)

:- module(prolog_impl, [swi/0, yap/0, prolog_impl/1]).

swi :- prolog_impl(swi).
yap :- prolog_impl(yap).

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

答案 1 :(得分:3)

这个答案部分基于 @Capelli's answer以及您对候选人解决​​方案的评论。

我们提出了一种不同的方式。 按照点一步一步......

  • 首先,我们采用以下简化和缩短的代码段。

    :- if(true).       p(3).
    :- elif(false).    p(4+3).
    :- endif. 
    
  • 在上面的示例中,我们可以看到永远不会采用“else”分支 那么......我们原则上可以将任意文本和二进制数据放在那里吗?

    :- if(true).       p(3).
    :- elif(false).    p (4);;[ p())
    :- endif.
    

    нет!在(重新)加载时,我们得到:⚠语法错误:操作员期望

    TIL,elifendif之间的所有部分都必须是有效的Prolog文本。

  • 让我们尝试一些不同的东西,这些东西受到你使用的短语的启发,特别是:“[...]使用非标准的Prolog语法代码,这些代码将被忽视[...] make它看不见[...]“

    对我来说,短语“非标准语法”表示可能会引入新的运算符(或旧的运算符重新定义):

    :- op(500,xfx,=>).
    
    :- if(true).       p(2).
    :- elif(false).    p(3 => 3).
    :- endif.
    

    考虑以下变化:

    :- if(true).       p(2).
    :- elif(false).    :- op(500,xfx,=>).   % is moving the `op/3` here ok?
                       p(3 => 3).
    :- endif.
    

    нет!在(重新)加载后,我们得到:⚠来自[...]的未终止条件编译

还有另一种方式!我们可以通过插入一个特殊用途的end_of_file事实来告诉Prolog文本读者忽略end_of_file.之后的所有内容

我们这样使用它:

% snip_at_end.pl
xxx1.

xxx2.

end_of_file.

xxx3.

:- op (500, xfx,eat).       % broken syntax (pt.1)
1 ]][[ v                    % broken syntax (pt.2)

使用SICStus Prolog进行简单测试:

$ sicstus
SICStus 4.3.2 (x86_64-linux-glibc2.12): Fri May  8 01:05:09 PDT 2015
[... License information ...]
| ?- compile(snip_at_end).
% compiling /home/stefan/prolog/snip_at_end.pl...
% compiled /home/stefan/prolog/snip_at_end.pl in module user, 40 msec 400672 bytes
yes
| ?- xxx1.
yes
| ?- xxx2.
yes
| ?- xxx3.
! Existence error in user:xxx3/0
! procedure user:xxx3/0 does not exist
! goal:  user:xxx3

希望这有帮助!如果我的答案适合你的问题,我很好奇/感兴趣:)

答案 2 :(得分:3)

"其他&#34>缺少一个右括号。分支。

do_stuff(G,Amt) :- ecall(erlog_demo:efunc('Elixir.Blah':stuff({G,Amt})).  % BAD
do_stuff(G,Amt) :- ecall(erlog_demo:efunc('Elixir.Blah':stuff({G,Amt}))). % OK!

只需计算左括号的数量即可。当达到.(期间,全步)时,期初与期末的差额必须精确为零。

希望有所帮助!