如何将这个Prolog程序转换成Lisp?

时间:2017-01-09 13:16:43

标签: prolog lisp common-lisp

我正在尝试学习Common Lisp,我想知道如何使用类似于Prolog的解析器作为单项式,并且不知道从哪里开始。

as_monomial(X, m(X, 0, [])) :- number(X), !.  
as_monomial(^(Y, Z), m(1, Z, [v(Z, Y)])) :- !.  
as_monomial(^(X, 0), m(1, 0, [])) :-  !.  
as_monomial(*(X, ^(Y, Z)), m(G, K, Q)) :- 
  as_monomial(X, m(G, TD, Vars)), 
  K   is (TD + Z), 
  ordinamonomio([v(Z, Y)| Vars], Q),
  !.
as_monomial(*(X, Y), m(G, K, Q)) :- 
  as_monomial(X, m(G, TD, Vars)), 
  K is (TD + 1), 
  ordinamonomio([v(1, Y)| Vars], Q),
  !.
as_monomial(-(X), m(Q, Y, L)) :- 
  as_monomial(X, m(A, Y, L)), 
  Q is A *(-1), 
  !.
as_monomial(X, m(1, 1, [v(1, X)])).

2 个答案:

答案 0 :(得分:3)

在Prolog代码中,您主要依赖于模式匹配和递归,但不是回溯,因此您可以轻松地将其转换为Common Lisp而无需进行重大修改。我可以根据generic functions向您展示一个骨架。如果您不熟悉Common Lisp,我强烈建议您阅读Practical Common Lisp书。

DEFGENERIC声明一个泛型函数,即根据一个或多个参数的类型或值动态调度的函数。

(defgeneric as-monomial (term)
  (:documentation "Express a term as a monomial."))

DEFMETHOD 根据其参数的类型或值来专门化泛型函数。例如,您可以具有数字的特定实现:

(defmethod as-monomial ((term number))
  `(m ,term 0 ()))

...和另一个cons单元格,即复合词:

(defmethod as-monomial ((term cons))
  (destructuring-bind (operator left &optional right) term
    (case operator
      (^ ...)
      (* ...)
      (- ...))

DESTRUCTURING-BIND。 您还可以使用默认行为:

;; fallback case
(defmethod as-monomial (term)
  `(m 1 1 ((v 1 ,term))))

当然,您可以定义仅使用casedestructure-bind的单个函数,但通用方法可以更好地扩展。对于复杂的模式匹配需求(这里不是这种情况,IMO),您可以使用模式匹配库,如trivia

答案 1 :(得分:1)

参考:Lisprolog - Interpreter for a simple Lisp, written in Prolog

这使用Prolog DCG,我发现Ivan Bratko的书籍“Prolog Programming for Artificial Intelligence”可以更好地学习DCG。

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Lisprolog -- Interpreter for a simple Lisp. Written in Prolog.
    Written Nov. 26th, 2006 by Markus Triska (triska@metalevel.at).
    Public domain code.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

:- set_prolog_flag(double_quotes, chars).

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   Parsing
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

parsing(String, Exprs) :- phrase(expressions(Exprs), String).

expressions([E|Es]) -->
    ws, expression(E), ws,
    !, % single solution: longest input match
    expressions(Es).
expressions([]) --> [].

ws --> [W], { char_type(W, space) }, ws.
ws --> [].

% A number N is represented as n(N), a symbol S as s(S).

expression(s(A))         --> symbol(Cs), { atom_chars(A, Cs) }.
expression(n(N))         --> number(Cs), { number_chars(N, Cs) }.
expression(List)         --> "(", expressions(List), ")".
expression([s(quote),Q]) --> "'", expression(Q).

number([D|Ds]) --> digit(D), number(Ds).
number([D])    --> digit(D).

digit(D) --> [D], { char_type(D, digit) }.

symbol([A|As]) -->
    [A],
    { memberchk(A, "+/-*><=") ; char_type(A, alpha) },
    symbolr(As).

symbolr([A|As]) -->
    [A],
    { memberchk(A, "+/-*><=") ; char_type(A, alnum) },
    symbolr(As).
symbolr([]) --> [].

TL; DR

引用是Markus Triska's website的一部分,其中包含许多其他有用的Prolog资源。他也积极参与GitHub