演算子を使って WHERE 節を書いた方がいいと思いませんか
かなりどうでもいいネタを思いついたので。
SQL の WHERE 節を string で書くのが一般的なバインディングですが、それはどうも正しい文法を書いているのか、正しい型を書いているのかどうか怪しい。そんなあなたに・・・。
type exp = | BinOp of bin_op * exp * exp | Var of string | Bool of bool | Int of int | Float of float | Str of string and bin_op = | And | Or | Eq let make_bin op e1 e2 = BinOp(op, e1, e2) let ( |=| ) = make_bin Eq let ( |&| ) = make_bin And let ( ||| ) = make_bin Or let bin_op_to_str = function | And -> "AND" | Or -> "OR" | Eq -> "=" let rec to_str = function | BinOp(op, e1, e2) -> (to_str e1) ^ " " ^ (bin_op_to_str op) ^ " " ^ (to_str e2) | Var var -> var | Bool true -> "TRUE" | Bool false -> "FALSE" | Int n -> string_of_int n | Float f -> string_of_float f | Str s -> "\""^s^"\""
中置演算子にしているのがポイントだ。
let e = ((Var "name") |=| (Str "taro")) |&| ((Var "id") |=| (Int 3)) in print_string(to_str e);; name = "taro" AND id = 3
もちろんこのあと型チェックをしましょうねという寸法。それから、C++ みたいにオーバーロードできる言語なら、もっとすっきり書けるはず。書いてないけど。たぶんこんなん。
Exp e = Var("name") == "taro" && Var("id") == 3; cout << e.to_str() << endl;
お、これスゴイじゃん。
そういえば、またどうでもいいことを思いついたんだが、ここで bool と int の exp を(というか、non-terminal)を bool_exp と int_exp に分けたいよね。でも、分けると a' -> a' -> bool な演算子とかが面倒だよね。だから、あとで型チェックプログラムに通すのが筋だよね。でも、そこで項間の関係(同じ型であるとか)いれればいいだけだよね。まるで I と am の人称をあわせるみたいに!