Support lazy candidates in `switch`-expression
Summary
With the v1.5.0 API of switch
-expressions all candidates have to be evaluated before the expression starts to be evaluated. In some scenarios this can be inefficient, e.g. if the n
-th candidates is expensive to compute but unlikely because some candidates i
, i<n
, commonly holds. Thus, like in switch
-statements, it should be possible to evaluate candidates lazily.
This issue is closely related to #8 (closed)
Proposals
Proposal 1
Provide alternatives to hctiws
and .case
that must be provided with a function which will be evaluated lazily to obtain the condition value.
This syntax is not final but it illustrates how this could be supported:
const value = lazySwitch(() => "foobar")
.case("foo").then(optionA)
.lazyCase(() => "foobar").then(optionB)
.default(optionC);
assert.equal(value, optionB);
It should not be required to start with lazySwitch
to use lazyCase
, i.e. the following should be possible as well:
const value = hctiws("foobar")
.case("foo").then(optionA)
.lazyCase(() => "foobar").then(optionB)
.default(optionC);
assert.equal(value, optionB);
Proposal 2
If the value provided to hctiws
or .case
is a function, evaluate the function lazily and use the return value as the candidate value:
const value = hctiws(() => "foobar")
.case("foo").then(optionA)
.case(() => "foobar").then(optionB)
.default(optionC);
assert.equal(value, optionB);
While this is arguably more convenient, it eliminates the possibility of using a value that could be a function from being a condition. This would make it impossible to emulate certain valid switch
-statements as switch
-expression. For example (albeit contrived):
const maybeFn = /* ??? */;
// Works
let value;
switch (maybeFn) {
case null:
case undefined:
console.log("Not a function so we can't run it!");
value = 42;
break;
default:
value = maybeFn();
}
// Doesn't work
const value = hctiws(maybeFn)
.case(null, undefined).thenDo(() => {
console.log("Not a function so we can't run it!");
return 42;
})
.defaultDo(() => maybeFn());