Click to change color scheme

Notes on codes, projects and everything

Evaluating logical statements

Often times one would have to write code to evaluate logical statements. For example, given statement p and q, what is p implies q? As there’s no operator for implication in PHP, one would have to rewrite the statement that consists only in NOT (!), AND (&&) and OR (||) operators. When there are a huge load of these statements, code can be difficult to read.

I was having this problem just now while working on my project, and after much tinkering I produce a quick set of functions for this purpose. Unfortunately using this library doesn’t seem to reduce the number of code to be written, and probably made code involving logical statements much more unreadable. Therefore, I am still looking for a better solution as of now.

As mentioned, the library was written to improve readability, and makes it easier to write complex logical statements. For example to write the statement p implies q, which is logical equivalent to NOT(p AND NOT(q)),


!($p AND !$q)

This looks alright, but when we have a real life code, then it may look something like this


!(array_key_exists('bar', $foo) AND !array_key_exists('baz', $foo['bar']));

or even in some other form that may or may not be more complex. Ideally I hope for something like this:


gate_implication(array_key_exists('bar', $foo), array_key_exists('baz', $foo['bar']));
function gate_implication($p, $q) {
return !($p AND !$q);
}

However, considering PHP does lazy evaluation when normal logical operators are used, this advantage is gone after it is rewritten. The problem with the above statement is that the array $foo is dynamically generated, if the key 'bar' does not exist, then PHP will throw a notice. However, if the statement is written using purely logical operators, then evaluation will stop after the first array_key_exists function returns FALSE.

In order to have this lazy evaluation, while maintaining more or less the same syntax, I thought why not use closure. Start with just AND operator,


gate_and(
call_user_func(function($array) {
return function() use($array) {
return array_key_exists('bar', $array);
};
}, $foo),
call_user_func(function($array) {
return function() use($array) {
return array_key_exists('baz', $array['bar']);
};
}, $foo));
function gate_and(Closure $p, Closure $q) {
return call_user_func($p) AND call_user_func($q);
}

Similarly, the function gate_and can be changed to gate_implication with the same function arguments, as follows,


gate_implication(
call_user_func(function($array) {
return function() use($array) {
return array_key_exists('bar', $array);
};
}, $foo),
call_user_func(function($array) {
return function() use($array) {
return array_key_exists('baz', $array['bar']);
};
}, $foo));
function gate_implication($p, $q) {
return gate_negation(gate_and($p, gate_negation($q)));
}

Just so one is curious about negation, here it is


function gate_negation($p) {
return function() use($p) {
return !call_user_func($p);
};
}

However, calling gate_* functions do not directly return the value. After rewriting simple logical statements to this ridiculously more troublesome form, call the result again to get the answer. For example, to negate a TRUE, and get the value, one would need to write


call_user_func(gate_negation(function() { return TRUE; })); // returns FALSE

I really hope I can stop writing call_user_func() statements, and rewrite it as follows,


$foo = function() { return function() {}; };
($foo)(); // invalid
($foo)()(); // invalid
(function() {})(); // invalid

While I know it is perfectly OK to write $foo(), but I don’t really like it, probably because of the dollar sign (and yes, I know I am being ridiculous here). Anyway, if anyone is interested in seeing this simple hack, it is a small part of my library (which also contains the form and database libraries).

leave your comment

name is required

email is required

have a blog?

This blog uses scripts to assist and automate comment moderation, and the author of this blog post does not hold responsibility in the content of posted comments. Please note that activities such as flaming, ungrounded accusations as well as spamming will not be entertained.