Simple scheme-y implementations of option and either datatypes. See the docs for details.
raco pkg install https://github.com/LLazarek/simple-option
raco docs simple-option
(require simple-option)
;; Without any absences, option-let* is just like match-let*
(option-let* ([x 1]
[(list y) '(2)])
(+ x y))
; => 3
;; Absences short-circuit the whole expression to absent
(option-let* ([x absent]
; the rest is skipped
[(list y) '(2)])
(+ x y))
; => absent
(define (fails-on-odd-numbers n)
(if (even? n)
(/ n 2)
absent))
(option-let* ([x 1]
[y (fails-on-odd-numbers 8)]
[z (fails-on-odd-numbers y)])
(+ x y z))
; => 7
(option-let* ([x 1]
[y (fails-on-odd-numbers 7)]
; the rest is skipped
[z (fails-on-odd-numbers y)])
(+ x y z))
; => absent
;; fail-if is mostly useful in option-let*, to explicitly short-circuit under a condition
;; the remaining examples presented as tests...
(test-equal? (option-let* ([x 5]
[y (fail-if (odd? x))]
[z (/ x 2)])
(add1 z))
absent)
(test-equal? (option-let* ([x 8]
[y (fail-if (odd? x))]
[z (/ x 2)])
(add1 z))
5)
(test-equal? (for/list ([x (in-option 5)]) x)
'(5))
(test-equal? (for/list ([x (in-option absent)]) x)
'())
(test-equal? (for/first/option ([i '(3 5 7)]
#:when (even? i))
i)
absent)
(test-equal? (for/first/option ([i '(3 5 2 7)]
#:when (even? i))
i)
2)
(require simple-option/either)
(test-equal? (either-let* () 5) 5)
(test-equal? (either-let* ([x 5])
x)
5)
(test-equal? (either-let* ([x (failure "bad")])
x)
(failure "bad"))
(test-equal? (either-let* ([x 5]
[y (failure "bad")])
(+ x y))
(failure "bad"))
(test-equal? (either-let* ([x 5]
[y (+ x 5)])
(+ x y))
15)
(test-equal? (either-let* ([x 5]
[y (fail-if (odd? x) "bad x")])
(/ x 2))
(failure "bad x"))
(test-equal? (either-let* ([x 10]
[y (fail-if (odd? x) "bad x")])
(/ x 2))
5)
(test-equal? (for/list ([x (in-success 5)])
x)
'(5))
(test-equal? (for/list ([x (in-success (failure "bad"))])
x)
'())
(test-equal? (for/list ([x (in-failure 5)])
x)
'())
(test-equal? (for/list ([m (in-failure (failure "bad"))])
m)
'("bad"))
(test-equal? (for/first/either ([i '(3 5 7)]
#:when (even? i))
#:failure-message "no evens!"
i)
(failure "no evens!"))
(test-equal? (for/first/either ([i '(3 5 2 7)]
#:when (even? i))
#:failure-message "no evens!"
i)
2)
(test-equal? (hash-ref/either (hash) 'a)
(failure "hash-ref/either: key 'a not found"))
(test-equal? (hash-ref/either (hash) 'a "bad")
(failure "bad"))
(test-equal? (hash-ref/either (hash 'a 5) 'a)
5)
(test-equal? (first/either empty)
(failure "first/either: empty list"))
(test-equal? (first/either empty "bad")
(failure "bad"))
(test-equal? (first/either '(5))
5)