C++テンプレートとマクロでLisp
C++テンプレートでLispに触発されて作成。
lisp.h
#pragma once // nil ====================================== struct nil { typedef nil eval; }; #define nil nil::eval // t ======================================== struct T { typedef T eval; }; #define T T::eval // cons ====================================== template < class A, class B> class cons { typedef typename A::eval left; typedef typename B::eval right; public: typedef cons<A, B> eval; // friend: template <class> friend struct car; template <class> friend struct cdr; }; #define cons(A, B) cons<A, B>::eval // car ====================================== template <class A> struct car { typedef typename A::left eval; }; #define car(A) car<A>::eval // cdr ====================================== template <class A> struct cdr { typedef typename A::right eval; }; #define cdr(A) cdr<A>::eval // atom ===================================== template <class> struct atom { typedef T eval; }; template <class A, class B> struct atom< cons<A, B> > { typedef nil eval; }; #define atom(A) atom<A>::eval // eq ======================================= template <class, class> struct eq { typedef nil eval; }; template <class A> struct eq<A, A> { typedef T eval; }; #define eq(A, B) eq<A, B>::eval // lisp ===================================== #define lisp(expr) expr()
main.cpp
#include <iostream> #include "lisp.h" // valueとか作ってみる template <int val> struct value { typedef typename value<val> eval; }; #define value(val) value<val>::eval template <class Type> void disp_typeinfo(Type t) { std::cout << typeid(t).name() << std::endl; } int main() { disp_typeinfo(lisp(atom(value(10)))); disp_typeinfo(lisp(atom(cons(value(10), value(20))))); disp_typeinfo(lisp(atom(cdr(cons(nil, cons(T, T)))))); disp_typeinfo(lisp(eq(T, T))); disp_typeinfo(lisp(eq(nil, nil))); disp_typeinfo(lisp(eq(T, nil))); disp_typeinfo(lisp(eq(nil, T))); disp_typeinfo(lisp(eq(cons(T, nil), cons(T, nil)))); disp_typeinfo(lisp(eq(T, car(cons(T, T))))); disp_typeinfo(lisp(cons(T, cdr(cons(T, nil))))); disp_typeinfo(lisp(cons(T, cdr(cons(T, value(10)))))); }
Visual C++ 2005での実行結果はこんな感じ。
struct T struct nil struct nil struct T struct T struct nil struct nil struct T struct T class consclass cons >
そしたら当然というかなんというか、次の日のよりLispっぽく見せるにほとんど同じものが・・・
まぁ、改良点(改悪点???)はそれだけじゃないですけどね。おびなたさんのプログラムとの違いは大体以下のとおりです。
変更点は改良になってるのかどうか、Lispをほとんど知らない(おぃ)からよくわかんない。