Skip/pass 非标准序言代码

Skip/pass non-standard prolog code

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

这是一个例子,它看起来像什么:

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.

语法错误:应为运算符

我使用这个习惯用法来保持代码 运行 在不同的实现中

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

此答案部分基于 以及您对他的候选解决方案的评论。

我们提出了一种不同的方式。 循序渐进...

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

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

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

    恩!在(重新)加载时,我们得到:⚠ 语法错误:预期运算符

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

  • 让我们尝试一些不同的东西,它受到您使用的短语的启发,特别是:“[...] 使用非标准的 Prolog 语法 [...] 将被忽略的代码 [。 ..] 使其不可见 [...]"

    对我来说,短语 "non-standard syntax" 表示可能会引入新的运算符(或重新定义旧运算符):

    :- 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 文本 reader 忽略 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

希望对您有所帮助!如果我的回答符合您的问题,我很好奇/感兴趣:)

"else" 分支中缺少一个右括号。

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!

简单数一下左括号的个数。当达到 .(周期,整步)时,打开与关闭的差异计数必须正好为零。

希望对您有所帮助!