If this is a really big tree, and especially if it is generated from data, you can consider decision functions as data using a functional approach. For example:
var decisionTree = new Case( true, Array( new Case ( function(n){ return n < 0; }, Math.sin ), new Case ( function(n){ return n < 2; }, "0<= n < 2" ), new Case ( true, "Greater than two " ))); decisionTree.evaluate(1);
Using this implementation, you can arbitrarily nest your tree:
// Represents a predicate and corresponding action to take if predicate is a // match. // // predicate : true or Function( object ) returning a boolean. // // action : One of Function, Case, Array of Cases or other value (see // Case.evaluate as to how each is applied) // // Case = function (predicate, action) { this.predicate = predicate; this.action = action; }; Case.prototype = { nomatch : { match : false }, match : function (v) { return { match : true, result :v }; }, // Recursively test Cases and applies corresponding action on // `object`. // // The action applied depends on the datatype of `action`: // // - Function : evaluates to `action( object )` // // - Case : A subsequent test is performed. Evaluates to whatever // the Cases action evaluates to. // // - Array of Cases : Subsequent tests are performed. Evaluates to whatever // the action of the first matching Case evaluates to. // // - Any other Value : Evaluates to itself // // returns object containing fields: // // match: boolean, indicates if Case was a match // // result: result of action applied // evaluate : function( object ) { var match = this.predicate; if ( match instanceof Function ) match = match( object ); if ( match ) { if (this.action instanceof Function ) return this.match( this.action(object) ); if ( this.action instanceof Case ) return this.action.evaluate( object ); if ( this.action instanceof Array ) { var decision; var result; for (var c = 0; c < this.action.length; c++ ) { decision = this.action[c]; if ( decision instanceof Case ) { result = decision.evaluate( object ); if (result.match) return result; } else throw("Array of Case expected"); } return this.nomatch; } return this.match(this.action); } return this.nomatch; } };
artistoex
source share