【问题标题】:Implementing user-defined arithmetic functions实现用户定义的算术函数
【发布时间】:2015-03-04 12:42:14
【问题描述】:

如何添加一个函数(例如,hammingweight)并在右侧出现的表达式中使用它是一些(is)/2 目标?

goal_expansion 或 term_expansion 之类的内容在这里有帮助吗?

我承认这不是一个大功能,但它可以提高我的一些 Prolog 程序的可读性。

编写自定义 (is)/2 谓词(实现自定义表达式求值器)是可行的,但我希望将运行时开销保持在较低水平,因为在这种情况下我不想牺牲可读性来牺牲运行时开销。

【问题讨论】:

    标签: prolog expression iso-prolog


    【解决方案1】:

    ISO Prolog 中没有这样的规定,既不扩展(is)/2,也不依赖目标扩展。并且,查看一些实现为此提供的各种实现特定的功能,没有普遍同意的方法来做到这一点。所以实现你自己的(my_is)/2 似乎是最好的方法。

    还要注意,这不仅会影响(is)/2,还会影响所有其他使用可评估函子的内置函数。特别是,所有算术比较内置(8.7 算术比较)(请参阅this overview)都会受到影响。

    【讨论】:

      【解决方案2】:

      我头脑简单(~20 LOC)的语法糖,lifter,它基于goal_expansion。

      带升降机,从句

      longer(A,B) :-
          length(A,º) > length(B,º).
      

      扩展为

      longer(A, B) :-
          length(A, C),
          length(B, D),
          C > D.
      

      【讨论】:

      • 解决方案是一个简洁的解决方案,但考虑到问题被标记为 Prolog 通用和iso-prolog,最好在答案中指出,所提供的解决方案针对特定的 Prolog 实现(SWI-Prolog ,显然,在这种情况下)。否则,在其他 Prolog 实现中尝试解决方案的用户最终可能会错误地认为该实现已被破坏,而不是简单地提供不同的功能集。
      • @PauloMoura:你是对的。我发布我的解决方案只是为了提供一个有效的目标扩展示例
      • 发帖人可能会根据自己的目的使用或改编哪些内容 :-)
      • SICStus 肯定会支持goal_expansion,不是吗?
      【解决方案3】:

      您可以使用 Logtalk 的术语扩展机制,该机制是可移植的,可与十二个受支持的 Prolog 编译器 (*) 一起使用。 Logtalk 编译加载和加载谓词接受 Prolog 文件,并会输出对应的 Prolog 扩展文件。例如,假设您要扩展的文件名为 source.pl,并且您的 term_expansion/2goal_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 实现都提供,并且实现之间存在显着差异。

      【讨论】:

        【解决方案4】:

        许多 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同理,这样最后有一个加速。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-08-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-11
          • 2016-11-29
          • 2015-10-05
          • 2013-04-09
          相关资源
          最近更新 更多