Errors in Racket
In Racket, error handling is typically done using exceptions, which is different from Go’s approach of returning explicit error values. However, we can simulate a similar pattern using option types and custom structs. Here’s how we might implement the example:
#lang racket
(require racket/format)
;; Define a custom struct for errors
(struct custom-error (message) #:transparent)
;; Function that might produce an error
(define (f arg)
(if (= arg 42)
(values #f (custom-error "can't work with 42"))
(values (+ arg 3) #f)))
;; Define sentinel errors
(define ErrOutOfTea (custom-error "no more tea available"))
(define ErrPower (custom-error "can't boil water"))
;; Function that uses sentinel errors
(define (make-tea arg)
(cond
[(= arg 2) ErrOutOfTea]
[(= arg 4) (custom-error (~a "making tea: " (custom-error-message ErrPower)))]
[else #f]))
;; Main function
(define (main)
;; Test f function
(for ([i (in-list '(7 42))])
(define-values (result error) (f i))
(if error
(printf "f failed: ~a\n" (custom-error-message error))
(printf "f worked: ~a\n" result)))
;; Test make-tea function
(for ([i (in-range 5)])
(define error (make-tea i))
(cond
[(not error) (printf "Tea is ready!\n")]
[(equal? error ErrOutOfTea) (printf "We should buy new tea!\n")]
[(string-contains? (custom-error-message error) (custom-error-message ErrPower))
(printf "Now it is dark.\n")]
[else (printf "unknown error: ~a\n" (custom-error-message error))])))
;; Run the main function
(main)
This Racket code simulates Go’s error handling pattern:
We define a
custom-error
struct to represent errors.The
f
function returns multiple values: the result and an error (if any).We define sentinel errors using our
custom-error
struct.The
make-tea
function demonstrates the use of sentinel errors and error wrapping.In the
main
function, we check for errors using conditional statements, similar to Go’sif err != nil
pattern.We use
equal?
andstring-contains?
to check for specific errors, simulating Go’serrors.Is
functionality.
To run this program, save it to a file (e.g., errors.rkt
) and execute it using the Racket interpreter:
$ racket errors.rkt
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 Racket implementation provides a similar structure and behavior to the original Go code, while adapting to Racket’s language features and idioms.