Question

I'm trying to create a function in Guile which tests if an arbitrary expression threw an error or not, but have hit a wall.

(define (error-or-not qqx)
  (if
    (catch
      #t
      (lambda () ,qqx)
      (lambda (k . args) #t))
    #t
    #f))

(display (error-or-not `(/ 1 0))) ; => #t (1)
(newline)
(display (error-or-not `(/ 1 1))) ; => #t (2)
(newline)

qqx is a quasiquoted expression that is evaluated inside the error-or-not function and tested to see if it causes an error.

The Guile manual in effect says that, if evaluating qqx throws an error, the catch function returns the value it gets from calling its third argument (the lambda which takes the arguments). This works fine if qqx actually does cause an error (see above #1).

But the manual also says that if there is no error, the catch function returns the value from evaluating qqx. This is not working out so well for me because I can't distinguish between the two cases (see above #2).

Can someone point out how to definitively tell when an error did not occur?


Update

Chris Jester-Young has pointed out my mistake--see the accepted answer below. For completeness, I'm posting the version of his code I'm using (backported to Guile 1.8.8):

(use-syntax (ice-9 syncase))

(define (stub retval) (lambda args retval))

(define-syntax error-or-not
  (syntax-rules ()
    ((_ expr ...)
      (catch #t (lambda () expr ... #f) (stub #t)))))

(display (error-or-not (/ 1 0))) ; => #t
(newline)
(display (error-or-not (/ 1 1))) ; => #f
(newline)
Was it helpful?

Solution

You are misusing quasiquoting; it doesn't do what you expect. In particular, it isn't a substitute for eval. The (lambda () ,qqx) you have creates a function that always fails when called, because unquote cannot be used outside of a quasiquote form.

The best way to implement the functionality you want is as a macro:

(define-syntax-rule (error-or-not expr ...)
  (catch #t
         (lambda () expr ... #f)
         (const #t)))

Example:

(error-or-not (/ 1 0))   ; => #t
(error-or-not (/ 1 1))   ; => #f

Guile 1.8-compatible version:

(use-syntax (ice-9 syncase))
(define-syntax error-or-not
  (syntax-rules ()
    ((_ expr ...)
     (catch #t (lambda () expr ... #f)
               (lambda _ #t)))))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top