Projects

3 posts

dbj.cond shapes catalogue

dbj.cond is one very flexible thing. But here in lies its hidden complexity: the flexibility sometimes brings benefits hard to understand. And what is hard to understand one tends to avoid.

So, I have decided to catalog what I am calling “shapes” of dbj.cond.  They are not “use cases” (UC).  UC’s are showing concrete real life examples of dbj.cond usage. While Shapes are generic description of an finite number of  coding idioms, shaping dbj.cond  usage.

In this dbj.cond shapes catalogue each shape has a name, javascript pseudo code and a diagram.

dbj.cond shapes catalogue

[nextpage title=”The COND”]

Standard LISP COND — multiple outcome conditional statement

Lisp syntax of the COND statement is this:

(COND 
   ((condition_1) (outcome_1)) ;; any number
   ((condition_2) (outcome_2)) ;; of cond/outcome  
   ((condition_3) (outcome_3)) ;; pairs
   (T             (outcome_4)) ;; otherwise
)

Result of condition is true or false. If true it’s pair value is returned and COND stops. If none is true the value of the last pair  (T (value_4)) is returned. ‘T’ is true in LISP.

In JS syntax the equivalent is this.

if ( condition_1 ) {
   outcome_1;
} else if ( condition_2 ) {
   outcome_2;
} else if ( condition_3 ) {
   outcome_3;
} else {
   outcome_4;
}

dbj.cond has as a first argument the input value.  so that each “condition” from above is actually a comparison of that  input value to whatever we need to compare.  To shape it up to behave like a basic LISP cond we simply give ‘true’ as the input value.

dbj.cond ( true, /* the input */
           condition_1, outcome_1,
           condition_2, outcome_2,
           condition_3, outcome_3,
                        outcome_4) ;

Were conditions are any JS expressions resulting in true or false.

Basic LISP cond reversed

Since JS can be obligatory mind-bending  we will introduce an sub shape to this which does exactly the opposite. It stops the conditional multi selection if the condition met is false.

dbj.cond ( false, /* the input */
           condition_1, outcome_1,
           condition_2, outcome_2,
           condition_3, outcome_3,
                        outcome_4) ;

If any of the expressions representing the conditions above yields false, dbj.cond stops and returns its value sibling. Lisp COND can not do that.

[nextpage title=”Standard”]

Standard dbj .cond() logic flow

Each and every dbj.cond shape conforms to the above diagrammatic representation of its internal processing.

It is important to note the “comparisons”. The dbj.cond comparisons are performed by  primary and secondary comparator functions.  If secondary is set that is.

//
// set optional primary and 
// optionally secondary 
// comparator functions
// if neither is given the current is unchanged 
// return array of the current comparators 
// [ primary, secondary ]
// 
dbj.cond.setcmp( primary_cmp, secondary_cmp );
//

[nextpage title=”The Functional”]JavaScript (JS) has a function as the “first class” object.  Nothing is stopping us  to use functions in place of any argument to the dbj.cond() , some arguments or in place of all arguments that is.

Canonical Functional shape of dbj.cond

// dbj.cond Functional shape
dbj.cond ( input_provider_function, /* the input */
           condition_function_1 , outcome_function_1,
           condition_function_2 , outcome_function_2,
           condition_function_3 , outcome_function_3,
/* there can be any number of condition/outcome pairs */
                        outcome__function_4) ;

Any shape of mixing functional and non functional arguments is of course possible. As long as the underlying comparator can handle them.

Please keep in mind the underlying comparators. In the case of using any variant of this dbj.cond shape comparator must be able to compare functions.

And this is where one meets head on, so called JS minefields, like this one:

var A = function () { return 2 };
var B = function () { return 2 };

function C () { return 2 };
function D () { return 2 };
// two function variables are strictly equal
A+"" === B+""
/* true */
// while two same functions are not
C+"" === D+""
/* false */

Moral of the snippet for comparator writers: It is hard to  decide how to compare two functions in an browser agnostic way and in the EcmaScript  standard version, agnostic way too.