あー、失敗。「プログラマのための述語論理」は、説明にJavaScriptを使うべきだった(「みにくいアヒルの子 -- コンピューティング・サイエンスとJavaScript」も参照)。技巧的なJavaコードじゃ、分かるものも分からなくなる。
手遅れだろうけど、JavaScriptで書き直し。
述語の例
function positive(n) { return n > 0; } function zero(n) { return n === 0; } function empty(s) { return s === ""; }
述語論理の演算
function and(p, q) { return function(x) { return p.call(null, x) && q.call(null, x); }; } function or(p, q) { return function(x) { return p.call(null, x) || q.call(null, x); }; } function not(p) { return function(x) { return ! p.call(null, x); }; }
述語の演算デモ
var positiveOrZero = or(positive, zero); var notEmpty = not(empty); var intData = [1, 0, -2, 3, -1]; var strData = ["Hello", "", "World"]; for(var i in intData) { var n = intData[i]; print("positiveOrZero " + n + " = " + positiveOrZero(n)); } for(var i in strData) { var s = strData[i]; print("notEmpty " + s + " = " + notEmpty(s)); }
positiveOrZero 1 = true
positiveOrZero 0 = true
positiveOrZero -2 = false
positiveOrZero 3 = true
positiveOrZero -1 = false
notEmpty Hello = true
notEmpty = false
notEmpty World = true
限量子の実現
function forAll(domain, pred) { for(var i in domain) { var x = domain[i]; if (! pred.call(null, x)) { return false; } } return true; } function forSome(domain, pred) { for(var i in domain) { var x = domain[i]; if (pred.call(null, x)) { return true; } } return false; }
限量子のデモ
var formula; var truth; formula ="ForAll s in {\"Hello\", \"\", \"World\"}.(Not empty(s))"; truth = forAll(["Hello", "", "World"], notEmpty); print(formula + " ==> " + truth); formula = "ForAll s in {\"Hello\", \"Hello\", \"World\"}.(Not empty(s))"; truth = forAll(["Hello", "Hello", "World"], notEmpty); print(formula + " ==> " + truth); formula = "ForSome x in {-1, -2, 0, 3}.(positive(x) Or zero(x))"; truth = forSome([-1, -2, 0, 3], positiveOrZero); print(formula + " ==> " + truth); formula = "ForSome x in {-1, -2, -3}.(positive(x) Or zero(x))"; truth = forSome([-1, -2, -3], positiveOrZero); print(formula + " ==> " + truth);
ForAll s in {"Hello", "", "World"}.(Not empty(s)) ==> false
ForAll s in {"Hello", "Hello", "World"}.(Not empty(s)) ==> true
ForSome x in {-1, -2, 0, 3}.(positive(x) Or zero(x)) ==> true
ForSome x in {-1, -2, -3}.(positive(x) Or zero(x)) ==> false
それで、さらに
あー、やっぱり、JavaScriptのほうがはるかに簡単で素直。“述語”の型を“X→Boolean”のように特定(強く型付け)できない点がJavaScriptの問題といえば問題。JavaScript2.0には、高階型や型総称は入る予定ないよなぁ(見た記憶がない)、もし次のように書けたらサイコーなんだけど。
function<X> forAll(domain:Collection<X>, pred:X->Boolean):Boolean { for(var i in domain) { var x:X = domain[i]; if (! pred.call(null, x)) { return false; } } return true; }