0

任意の式がエラーをスローしたかどうかをテストする関数を Guile で作成しようとしていますが、壁にぶつかっています。

(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関数内で評価されerror-or-not、エラーが発生するかどうかをテストする準引用符付きの式です。

Guile のマニュアルでは、評価qqxでエラーが発生した場合、catch関数は 3 番目の引数 (引数を取るラムダ) を呼び出して取得した値を返すと述べています。実際にエラーが発生した場合、これは正常qqxに機能します (上記の #1 を参照)。

しかし、マニュアルには、エラーがなければ、catch関数は を評価して値を返すとも書かれていますqqx。2 つのケースを区別できないため、これはうまくいきません (上記 #2 を参照)。

エラーが発生しなかったことを明確に伝える方法を誰かが指摘できますか?


アップデート

Chris Jester-Young が私の間違いを指摘しました。以下の受け入れられた回答を参照してください。完全を期すために、私が使用している彼のコードのバージョンを投稿しています (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)
4

1 に答える 1

2

quasiquoting を誤用しています。それはあなたが期待することをしません。特に、 の代わりにはなりませんeval。あなたが持っている は、フォームの外では使用できないため、呼び出されたときに常に失敗(lambda () ,qqx)する関数を作成します。unquotequasiquote

必要な機能を実装する最良の方法は、マクロを使用することです。

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

例:

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

Guile 1.8 互換バージョン:

(use-syntax (ice-9 syncase))
(define-syntax error-or-not
  (syntax-rules ()
    ((_ expr ...)
     (catch #t (lambda () expr ... #f)
               (lambda _ #t)))))
于 2014-02-03T02:36:49.300 に答える