summary refs log tree commit diff
path: root/err.scm
diff options
context:
space:
mode:
Diffstat (limited to 'err.scm')
-rw-r--r--err.scm94
1 files changed, 94 insertions, 0 deletions
diff --git a/err.scm b/err.scm
new file mode 100644
index 0000000..0dad12b
--- /dev/null
+++ b/err.scm
@@ -0,0 +1,94 @@
+; Influenced by Rust, Haskell, Racket rebellion/results, JS promises
+
+(module err (err unerr err? ok? ok=> err=> ok/if ok ok/or ok/and guard-err)
+
+(import
+  (scheme)
+  (chicken base)
+  (chicken format)
+  (chicken condition))
+
+(define-record-type <err>
+  (%make-err data)
+  err?
+  (data %err-data))
+
+(set-record-printer! <err>
+  (lambda (x out)
+    (fprintf out "#<err ~s>" (%err-data x))))
+
+(define (err x)
+  (if (err? x)
+    x
+    (%make-err x)))
+
+(define (ok? e)
+  (not (err? e)))
+
+(define (unerr e)
+  (if (err? e)
+    (%err-data e)
+    (if #f #f)))
+
+(define ok/if
+  (case-lambda
+    ((x when-ok)
+     (if (err? x)
+       x
+       (when-ok x)))
+    ((x when-ok when-err)
+     (if (err? x)
+       (when-err (unerr x))
+       (when-ok x)))))
+
+(define (ok=> x . fs)
+  (if (null? fs)
+    x
+    (if (ok? x)
+      (apply ok=> ((car fs) x) (cdr fs))
+      x)))
+
+(define (err=> x . fs)
+  (if (ok? x)
+    x
+    (let loop ((x (unerr x))
+               (fs fs))
+      (if (null? fs)
+        x
+        (loop ((car fs) x) (cdr fs))))))
+
+(define (ok x)
+  (err=> x (lambda (e)
+             (if (condition? e)
+               (abort e)
+               (error e)))))
+
+(define-syntax ok/or
+  (syntax-rules ()
+    ((_)            (err (if #f #f)))
+    ((_ a)          a)
+    ((_ a b)        (let ((va a))
+                      (if (err? va)
+                        b
+                        va)))
+    ((_ a b c ...)  (ok/or (ok/or a b) c ...))))
+
+(define-syntax ok/and
+  (syntax-rules ()
+    ((_)            #t)
+    ((_ a)          a)
+    ((_ a b)        (let ((va a))
+                      (if (err? va)
+                        va
+                        b)))
+    ((_ a b c ...)  (ok/and (ok/and a b) c ...))))
+
+(define-syntax guard-err
+  (syntax-rules ()
+    ((_ expr)
+     (guard-err expr ()))
+    ((_ expr conditions ...)
+     (condition-case expr
+       (exn conditions (err exn)) ...))))
+
+)