package variant; import java.util.regex.Pattern; import java.util.Map; import java.util.HashMap; import java.util.Iterator; abstract class lambda { abstract var f(var v); public var apply(var v){ return f(v); } } public class var { public static void main(String[] args){ lambda square = new lambda(){var f(var v){ return new $(v.i() * v.i()); }}; lambda say = new lambda(){var f(var v){ System.out.println(v.display()); return var.NIL; }}; //文字列 var name = new $("James"); say.apply(name); //文字列と数値の混合リスト var ls = $.list(1, "2", 3, 4, 5); //リストの各要素を2乗したリストを返す(数値=>文字列は自動変換) say.apply($.map(square, ls)); //cdr(笑) say.apply(ls.cdr()); //入れ子のハッシュテーブル var hash = $.hash( "John", $.hash("sex", "male", "age", 20), "Eva", $.hash("sex", "female", "age", "unknown"), "Abe", $.hash("sex", "unknown", "age", "25") ); say.apply(hash.get("John").get("sex")); say.apply(hash.get("Nobita").get("sex")); say.apply(hash.keys()); say.apply(hash); } private var_impl impl; public static final var NIL = new var(var_nil.NIL_IMPL); protected var(var_impl i){ impl = i; } public var(){ impl = var_nil.NIL_IMPL; } public var(int val){ impl = new var_int(val); } public var(String val){ impl = new var_str(val); } public var(Map hash){ impl = new var_hash(hash); } public var(var car, var cdr){ impl = (cdr.is_nil()) ? new var_list(car) : (cdr.is_list()) ? new var_list(car, cdr) : new var_pair(car, cdr); } public var car(){ return impl.car(); } public var cdr(){ return impl.cdr(); } public var get(String key){ return impl.get(key); } public var get(var key){ return impl.get(key.s()); } public var keys(){ return impl.keys(); } public var put(var key, var val){ return impl.put(key, val); } public int type(){ return impl.type(); } public boolean eq(var other){ return impl.eq(other.impl); } public boolean is_nil(){ return impl.type() == var_impl.T_NIL; } public boolean is_atom(){ return impl.type() != var_impl.T_LIST && impl.type() != var_impl.T_PAIR; } public boolean is_pair(){ return !is_atom(); } public boolean is_str(){ return impl.type() == var_impl.T_STR; } public boolean is_int(){ return impl.type() == var_impl.T_INT; } public boolean is_symbol(){ return impl.type() == var_impl.T_SYMBOL; } public boolean is_list(){ return impl.type() == var_impl.T_LIST; } public boolean is_hash(){ return impl.type() == var_impl.T_HASH; } public boolean bool(){ return impl.bool(); } public int i(){ return impl.i(); } public String s(){ return impl.s(); } public String display(){ return impl.display(); } public String toString(){ return impl.display(); } //static public static var detect(Object o){ if(o instanceof var){ return (var)o; }else if(o instanceof String){ return new var((String)o); }else if(o instanceof Integer){ Integer i = (Integer)o; return new var(i.intValue()); }else{ return var.NIL; } } public static var v(String v){ return (v==null) ? var.NIL : new var(v); } public static var v(int v){ return new var(v); } public static var v(var v){ return (v==null) ? var.NIL : v; } } //本当はpublicにしたいけど1ファイルにまとめるためにプリフィックスなし。 class $ extends var { public $(int val){ super(val); } public $(String val){ super(val); } //両方プリミティブ public static var cons(String car, String cdr) { return new var(v(car), v(cdr)); } public static var cons(int car, String cdr) { return new var(v(car), v(cdr)); } public static var cons(String car, int cdr) { return new var(v(car), v(cdr)); } public static var cons(int car, int cdr) { return new var(v(car), v(cdr)); } //片方プリミティブ public static var cons(int car, var cdr) { return new var(v(car), v(cdr)); } public static var cons(String car, var cdr) { return new var(v(car), v(cdr)); } public static var cons(var car, int cdr) { return new var(v(car), v(cdr)); } public static var cons(var car, String cdr) { return new var(v(car), v(cdr)); } //両方var public static var cons(var car, var cdr){ return new var(car, cdr); } public static var q(String exp){ return new var(new var_symbol(exp)); } public static var hash(Map hash){ return new var(hash); } public static var hash(var list){ Map map = new HashMap(); return hash(append_hash(map, list)); } public static var hash(Object... args){ return hash(list(args)); } public static Map append_hash(Map hash, var list){ if( !list.cdr().is_nil() ){ hash.put(list.car().s(), list.cdr().car()); return append_hash(hash, list.cdr().cdr()); }else{ return hash; } } public static var list(Object... args){ //再帰で書きたいけどきっと非効率だからやめとく。 var ret = var.NIL; for(int i=args.length-1; i>-1; i--){ Object o = args[i]; var v = detect(o); ret = new var(v, ret); } return ret; } public static var map(lambda l, var list){ if(list.is_nil()){ return var.NIL; }else{ return $.cons(l.apply(list.car()), map(l, list.cdr())); } } } abstract class var_impl { public var car(){ return var.NIL; } public var cdr(){ return var.NIL; } public var get(String key){ return var.NIL; } public var keys(){ return var.NIL; } public var put(var key, var val){ return var.NIL; } public abstract int type(); public abstract String display(); //nil 0 ""だけがfalse public boolean bool(){ return true; } public boolean eq(var_impl v){ return false; } public int i(){ return 0; } public String s(){ return ""; } public static final int T_NIL = 0; public static final int T_INT = 1; public static final int T_STR = 2; public static final int T_PAIR = 3; public static final int T_LIST = 4; public static final int T_QUOTE = 5; public static final int T_SYMBOL= 6; public static final int T_HASH = 7; } class var_nil extends var_impl { private var_nil(){}; public static final var_nil NIL_IMPL = new var_nil(); public int type(){ return T_NIL; } public String display(){ return "nil"; } //nil 0 ""だけがfalse public boolean bool(){ return false; } public boolean eq(var_impl v){ return v.type() == T_NIL; } } class var_int extends var_impl { private int val; public var_int(int v){ val = v; } public int type(){ return T_INT; } public var car(){ return new var(val); } public int i(){ return val; } public String s(){ return String.valueOf(val); } public String display(){ return s(); } //nil 0 ""だけがfalse public boolean bool(){ return val != 0; } public boolean is_integer(String s){ return Pattern.matches("^-?[0-9]+$", s); } public boolean eq(var_impl rhs){ switch(rhs.type()){ case T_STR : return (is_integer(rhs.s())) ? val == rhs.i() : false; case T_INT: return val == rhs.i(); default: return false; } } } class var_str extends var_impl { private String val; public var_str(String v){ val = (v!=null) ? v : ""; } public int type(){ return T_STR; } public var car(){ return new var(val); } public int i(){ return Integer.parseInt(val); } public String s(){ return val; } public String display(){ return "\"" + val.replace("\"", "\\\"") + "\""; } //nil 0 ""だけがfalse public boolean bool(){ return !"".equals(val); } public boolean eq(var_impl rhs){ switch(rhs.type()){ case T_STR : return val.equals(rhs.s()); case T_INT: return rhs.eq(this); default: return false; } } } class var_pair extends var_impl { private var car; private var cdr; public var_pair(var car, var cdr){ this.car = car; this.cdr = cdr; } public var car(){ return car; } public var cdr(){ return cdr; } public int type(){ return T_PAIR; } public String s(){ return ("(" + car.display() + " . " + cdr.display() + ")"); } public String display(){ return s(); } public boolean eq(var_impl rhs){ switch(rhs.type()){ case T_PAIR : var_pair p = (var_pair)rhs; return car.eq(p.car) && cdr.eq(p.cdr); default: return false; } } } class var_list extends var_impl { private var car; private var cdr; public var_list(var car){ this.car = car; this.cdr = var.NIL; } public var_list(var car, var cdr){ this.car = car; this.cdr = cdr; } public var car(){ return car; } public var cdr(){ return cdr; } public int type(){ return T_LIST; } public String s(){ return (cdr.is_nil()) ? car.display() : car.display() + " " + cdr.s(); } public String display(){ return "(" + s() + ")"; } public boolean eq(var_impl rhs){ switch(rhs.type()){ case T_LIST : var_list p = (var_list)rhs; return car.eq(p.car) && cdr.eq(p.cdr); default: return false; } } } class var_symbol extends var_impl { private String val; public var_symbol(String v){ val = (v!=null) ? v : ""; } public int type(){ return T_SYMBOL; } public var car(){ return new var(val); } public int i(){ return Integer.parseInt(val); } public String s(){ return val; } public String display(){ return val; } //nil 0 ""だけがfalse public boolean bool(){ return !"".equals(val); } public boolean eq(var_impl rhs){ switch(rhs.type()){ case T_SYMBOL : return val.equals(rhs.s()); default: return false; } } } class var_hash extends var_impl { private Map hash; public var_hash(Map hash){ this.hash = hash; } public int type(){ return T_HASH; } public var put(var key, var val){ hash.put(key.s(), val); return new var(this); } public var get(var key) { return var.v(hash.get(key.car().s())); } public var get(String key) { return var.v(hash.get(key)); } public var keys(){ var ret = var.NIL; Iterator i = hash.keySet().iterator(); while(i.hasNext()){ ret = $.cons(i.next(), ret); } return ret; } public String s(){ Iterator i = hash.keySet().iterator(); String ret = ""; while(i.hasNext()){ var key = new $(i.next()); var val = hash.get(key.s()); ret = "("+key.display()+" => "+val.display()+")" + ret; } return ret; } public String display(){ return "(" + s() + ")"; } public boolean eq(var_impl rhs){ return false; } }