Errors in Scheme

In Scheme, error handling is typically done using condition systems or custom error handling mechanisms. We’ll use a simple approach with error messages as strings for this example.

;; By convention, we'll return a pair where the first element is the result
;; and the second element is an error message (or #f for no error).
(define (f arg)
  (if (= arg 42)
      (cons -1 "can't work with 42")
      (cons (+ arg 3) #f)))

;; Define sentinel errors
(define err-out-of-tea "no more tea available")
(define err-power "can't boil water")

(define (make-tea arg)
  (cond ((= arg 2) err-out-of-tea)
        ((= arg 4) (string-append "making tea: " err-power))
        (else #f)))

(define (main)
  ;; Test f function
  (for-each
   (lambda (i)
     (let ((result (f i)))
       (if (cdr result)
           (display (string-append "f failed: " (cdr result) "\n"))
           (display (string-append "f worked: " (number->string (car result)) "\n")))))
   '(7 42))

  ;; Test make-tea function
  (for-each
   (lambda (i)
     (let ((err (make-tea i)))
       (cond (err
              (cond ((string=? err err-out-of-tea)
                     (display "We should buy new tea!\n"))
                    ((string-contains err err-power)
                     (display "Now it is dark.\n"))
                    (else
                     (display (string-append "unknown error: " err "\n")))))
             (else
              (display "Tea is ready!\n")))))
   (iota 5)))

(main)

In Scheme, we use a different approach to handle errors:

  1. The f function returns a pair (cons cell) where the first element is the result and the second is an error message (or #f for no error).

  2. Sentinel errors are defined as simple strings.

  3. The make-tea function returns an error string or #f for success.

  4. We use for-each with lambda functions to iterate over lists, similar to the loops in the original code.

  5. Error checking is done using cond statements, which are similar to if-else chains in other languages.

  6. String comparison is done using string=? and string-contains for partial matches.

  7. We use display for output instead of println.

When you run this program, it will produce output similar to the original Go program:

f worked: 10
f failed: can't work with 42
Tea is ready!
Tea is ready!
We should buy new tea!
Tea is ready!
Now it is dark.

This Scheme version demonstrates error handling using return values and conditional statements, which is a common approach in functional programming languages. While it doesn’t have the same built-in error handling mechanisms as some other languages, it allows for flexible error management through careful function design and condition handling.