Monday, December 7, 2015

Re-imagining If

In Lisp, Scheme, and Smalltalk conditional expressions are functions. The idea is that you have a homogenous syntax. Everything is just a method invocation. Other languages have special syntax for if. This is because it is viewed as simpler to understand and it is a kind of tradition. So I was thinking about if as a method and if(condition,expression) seemed kind of ugly to me. Since I do a lot with promises and quickly shifted to if(condition).then(expression). It seems like you could also do some fluent style tricks to make your conditional logic very flexible. It would also precisely mirror Promise based asynchronous coding. This post will be my musing on the idea.

In the code below I will start by ignoring 'this' complications assuming they can be hashed out. I will start aiming for a fluent style interface.

function If(condition) {
    return new Condition(condition)
}
function Condition(condition) {   
    this.conditionOutcome = isFunction(condition)
        ? condition()
        : condition;
    // icky bool conversion
    this.conditionOutcome = !!this.conditionOutcome
}
Condition.prototype.then = function(expression) {
    if (this.conditionOutcome) {
        expression()
    }
    return this;
}
Condition.prototype.else = function(expression) {
    if (!this.conditionOutcome) {
        expression()
    }
    return this;
}
Condition.prototype.andIf = function(condition) {
    // This short circuits execution if condition is function
    if (this.conditionOutcome) {
        return new Condition(condition);
    }
    return this;
}
Condition.prototype.orIf = function(condition) {
    if (!this.conditionOutcome) {
        return new Condition(condition);
    }
    return this;
}

Now you can write code that looks like this:

If(someProp === someValue)
    .then(() => {
     }
    .else(() => {
     }
If(someProp === someValue)
    .andIf(otherProp === someValue)
    .then(() => {
     }
    .orIf(() => {
     })
    .then(() => {
     }
    .then(() => {
     }

You could write code where all your conditional behavior occurs at the top. (You could do that before I guess, but here is the idea.)

var inFirstCase = If(someProp === someValue);
var inFirstSubOne = inFirstCase.andIf(subCondition === value);
var inSecondCase = If(someProp === someOtherValue);
...
inFirstCase.then(() => {
})
inSecondCase.then(() => {
})

Does this have any value? Probably not. It was just something I was thinking about so I figured I would write some code to see what it looked like.

No comments:

Post a Comment