如何添加一个函数(例如,hammingweight)并在右侧出现的表达式中使用它是一些(is)/2
目标?
像goal_expansion 或term_expansion 这样的东西在这里有帮助吗?
我承认这不是一个大特性,但它可以增加我的一些 Prolog 程序的可读性。
编写自定义(is)/2
谓词(实现自定义表达式求值器)是可行的,但我希望将运行时开销保持在较低水平,因为在这种情况下我不想牺牲运行时开销的可读性。
如何添加一个函数(例如,hammingweight)并在右侧出现的表达式中使用它是一些(is)/2
目标?
像goal_expansion 或term_expansion 这样的东西在这里有帮助吗?
我承认这不是一个大特性,但它可以增加我的一些 Prolog 程序的可读性。
编写自定义(is)/2
谓词(实现自定义表达式求值器)是可行的,但我希望将运行时开销保持在较低水平,因为在这种情况下我不想牺牲运行时开销的可读性。
ISO Prolog 中没有这样的规定,既不扩展(is)/2
也不依赖目标扩展。并且,查看某些实现为此提供的各种实现特定功能,没有普遍同意的方法来做到这一点。所以实施你自己的(my_is)/2
似乎是最好的方法。
另请注意,这不仅会影响(is)/2
所有其他使用可评估函子的内置函数。特别是,所有算术比较内置函数(8.7 算术比较)(请参阅此概述)都会受到影响。
我头脑简单(~20 LOC)的语法糖,lifter,它基于goal_expansion。
带升降机,从句
longer(A,B) :-
length(A,º) > length(B,º).
扩展为
longer(A, B) :-
length(A, C),
length(B, D),
C > D.
您可以使用 Logtalk 的术语扩展机制,该机制是可移植的,可与十二个受支持的 Prolog 编译器 (*) 一起使用。Logtalk 编译加载和加载谓词接受 Prolog 文件,并会输出对应的 Prolog 扩展文件。例如,假设您要扩展的文件已命名source.pl
,并且您的term_expansion/2
和goal_expansion/2
谓词定义位于名为 的文件中expansions.pl
,您可以执行以下操作:
% first, load the expansion hooks:
| ?- [expansions].
...
% second, expand a file using those hooks:
| ?- logtalk_compile(source, [hook(user)]).
...
您将获得扩展文件,该文件将(默认情况下)命名source_pl.pl
(在取决于scratch_directory
Logtalk 标志值的目录中)。如果扩展包含在 Prolog 模块中,请在模块名称上方使用,而不是user
. 如果source.pl
文件包含模块而不是普通的 Prolog 代码,则需要为term_expansion/2
谓词定义一些子句以避免 Logtalk 将模块编译为对象。但是在不使用模块的更简单的情况下,上面的两个查询就足够了。
Logtalk 的术语扩展机制的一个可能有用的特性是,您可以通过将术语或目标与{}/1
控制结构包装起来,将其标记为不扩展或进一步扩展。
(*) 请注意,术语扩展机制不是标准的,并非所有 Prolog 实现都提供,并且实现之间存在显着差异。
许多 Prolog 系统不允许用户定义的可评估谓词。有时问题是可评估谓词存在于另一个命名空间中。有时,Prolog 系统在使用宿主语言进行算术评估时会回避跳回 Prolog 执行。
然而,一些 Prolog 系统具有用户定义的可评估谓词,例如 ECLiPSe Prolog 和 Jekejeke Prolog。在 Jekejeke Prolog 中,开销是两倍。令我惊讶的是,在新的 Dogelog 运行时用户可定义的可评估谓词显示了一个优势:
/* Dogelog Runtime 0.9.5 */
fact(0, 1) :- !.
fact(N, X) :- M is N-1, fact(M, Y), X is Y*N.
fact2(0, 1) :- !.
fact2(N, X) :- X is fact2(N-1)*N.
for(_).
for(N) :- N > 1, M is N - 1, for(M).
% ?- time((for(1000), fact(1000, _), fail; true)).
% % Wall 1595 ms, trim 0 ms
% ?- time((for(1000), _ is fact2(1000), fail; true)).
% % Wall 1394 ms, trim 0 ms
我将轻微的速度优势归因于事实上更简洁的公式 2/2。该公式使用较少的 Prolog 逻辑变量。并且用户定义的可评估谓词在(is)/2
内部也没有 Prolog 逻辑变量,发生的宿主语言分配不分配
一个 Prolog 逻辑变量或 trail 相同,这样最后就有了加速。