LoginSignup
5
0

More than 5 years have passed since last update.

PrologでLisp遊び

Last updated at Posted at 2018-07-28

はじめに

Prologで書いたLispモドキです。O-Prologのテストを兼ねて書きました。S式の代わりにPrologのリストを使います。Prologで遊びつつLispの内部構造をお楽しみください。実用性はまったくありません。遊びです。

使い方

起動はreplです。終了は[quit]です。



| ?- repl.
> [defun,foo,[a,b],[*,a,b]].
t
> [foo,10,2].
20
> [setq,x,2].
t
> x.
2
> [quit].
t
yes
| 


拡張

四則演算しか実装していません。いろいろ追加して遊んでください。

コード


%Lisp in Prolog


repl :-
    repeat,
    write('> '),
    read(X),
    eval(X,Y,[]),
    write(Y),nl,
    (X=[quit]->true;fail).

eval(X,X,E) :-
    integer(X).
eval(X,X,E) :-
    float(X).
eval(X,Y,E) :-
    atom(X),
    assoc(X,E,Y).
eval(X,Y,E) :-
    atom(X),
    global(X,Y).
eval([quit],t,E).
eval([defun,F,A,B],t,E) :-
    assert(fun(F,A,B)).
eval([setq,X,Y],t,E) :-
    eval(Y,Z,E),
    assert(global(X,Z)).
eval(X,Y,E) :-
    funcall(X,Y,E).

funcall([F|A1],Z,E) :-
    fun(F,A,B),
    argument(A,A1,Y),
    append(Y,E,E1),
    eval(B,Z,E1).
funcall([+,X,Y],Z,E) :-
    eval(X,X1,E),
    eval(Y,Y1,E),
    Z is X1+Y1.
funcall([-,X,Y],Z,E) :-
    eval(X,X1,E),
    eval(Y,Y1,E),
    Z is X1-Y1.
funcall([*,X,Y],Z,E) :-
    eval(X,X1,E),
    eval(Y,Y1,E),
    Z is X1*Y1.
funcall([/,X,Y],Z,E) :-
    eval(X,X1,E),
    eval(Y,Y1,E),
    Z is X1/Y1.

assoc(X,[],Z) :- fail.
assoc(X,[[X|Y]|Ys],Y).
assoc(X,[_|Ys],Z) :-
    assoc(X,Ys,Z).



argument([X],[Y],[X|Y]).
argument([X|Xs],[Y|Ys],[[X|Y],Z]) :-
    argument(Xs,Ys,Z).


global(t,t).
global(nil,nil).

:- dynamic(fun/3).
fun(dummy,a,b).

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0