Skip to main content

if then else

As a solution to condtitional code execution plu-ts exposes an if then else construct.

However, since everything in plu-ts is an expression, the if then else construct does not allow stuff that in typescript would have been written as

if( my_condition )

because we don't really know what to do if the condtion is false.

So the if then else we have in plu-ts is more similar to the typescript ? : ternary operator, so at the end of the day, if then else is just a function.

Let's look at a simple if then else construct:

pif( int ).$( true )
.then( 42 )
.else( 69 )

This plu-ts expression checks the condition (in our case pBool(true); remeber that plu-ts is converting the typescript value for us)

and if it is a Term<PBool> equivalent to true it returns pInt(42) otherwhise it returns pInt(69).

Why pif is a typescript function and not a constant like other plu-ts funcitons?

Since the type of if then else is something like bool -> a -> a -> a, we need to specify the type of a prior to the actual expression.

This ensures type safety so that Typescript can warn you if one of the results is not of the type you expect it to be.

Doing so Typescript can catch stuff like:

pif( int ).$( true )
.then( 42 )
// "muahahah" is converted to `pStr("muahahah")`
// which is obviously not of type `int`
.else( "muahahah" )

What happens if one of the two branches raises an error?

plu-ts is a strict language as we saw while having a look at papp; that means that arguments are evaluated prior being passed to a function.

what happens if one of the argument returns an error?

The answer is what you expect to happen. Or, to be more precise, if the error rose in the branch selected by the boolean, the computation results in an error; if not it returns the result.

This is because even if by default functions are strict, pif is lazy; meaning that it evaluates only the argument it needs and not the others.

This is done using pforce and pdelay so the compiled funcion is a bit larger than the one you'd expect.

if you don't need lazyness you can use the pstrictIf function that emits slightly less code but evaluates both the arguments.

so something like

pstrictIf( int ).$( pBool( true ) )
.$( pInt(42) )
.$( pInt(69) )

is just fine but something like

// this results in an error, even if the conditional is true
pstrictIf( int ).$( pBool( true ) )
.then( pInt(42) )
.else( perror( int ) ) // KABOOM

generally speaking you should always prefer the plain pif