Tuesday, March 2, 2021

Roll your own conditional

Sometimes you'd like to write your own conditionals. Perhaps you'd like to wrap something around one or both arms of the branch. Perhaps the predicate is tristate and you need three branches. Perhaps the predicate wants to share information with one or both arms. You want to abstract away how the predicate makes it decision from how the caller wants to handle the possible outcomes. The trick is to use continuation passing style:

sign = lambda n, if_positive, if_zero, if_negative: \
           if_positive() if n > 0 else \
           if_negative() if n < 0 else \
           if_zero()

# use it like this:
for i in range (-1, 1):
    print (i)
    print (sign (i,
            lambda: \
              "positive",
            lambda: (lambda first, second: second)(
              print ("Hooray!"),
              "zero"),
            lambda: \
              "negative"))
By making the branches be thunks, we delay evaluation. Once the conditional decides which branch to take, it forces the thunk and returns its value.

2 comments:

Francesco said...

I think there is a missing ‘)’ at the end!

Joe Marshall said...

Thanks, Francesco. Fixed.