创建修改后的“equal?”函数以与 RackUnit 一起使用
Create a modified `equal?` function for use with RackUnit
我正在使用 check-equal?
编写一堆测试,其中的对象包含不是 eq?
的语法对象。出于这些测试的目的,如果两个语法对象在给定 syntax->datum
时相等,我可以说它们是相等的。 (是的,我知道这会丢失很多绑定信息,但是目前,确保它们的数据相等就足够了。稍后我会测试绑定信息是否良好。)
如果这两个对象不是语法对象,但是,如果它们彼此 equal?
,我希望它们相等。
但是,如果这些对象在某个递归点包含语法对象,我想在它们的数据上测试它们的相等性,所以我不能这样做:
(define (my-equal? a b)
(if (and (syntax? a) (syntax? b)
(equal? (syntax->datum a) (syntax->datum b))
(equal? a b)))
(define-binary-check (check-my-equal? my-equal? actual expected))
因为这不会进行递归检查。
我可以自己处理递归,并且只在基元上使用 equal?
,但这对于实现我自己的相等性测试至关重要。
您可以使用 equal?/recur
获得此行为。此函数的行为类似于 equal?
,但在递归调用的情况下采用不同的函数。所以你可以像这样实现 my-equal?
:
(define (my-equal? actual expected)
(if (and (syntax? actual) (syntax? expected))
(equal? (syntax->datum actual) (syntax->datum expected))
(equal?/recur actual expected my-equal?)))
但是请注意,由于您提供的是递归函数,equal?/recur
不会为您进行任何循环检测。因此,您需要自己做。一种简单的方法是使用参数:
(define current-equal-visited (make-parameter set))
(define (my-equal? actual expected)
(cond [(set-member? (current-equal-visited) (cons actual expected))
#t]
[(and (syntax? actual) (syntax? expected))
(equal? (syntax->datum actual) (syntax->datum expected))]
[else
(parameterize ([current-equal-visited
(set-add (current-equal-visited) (cons actual expected))])
(equal?/recur actual expected my-equal?))]))
然后,当然,正如您在问题中注意到的那样,您可以使用 define-binary-check
将此过程变成 RackUnit 的东西。
(define-binary-check (check-my-equal? my-equal? actual expected))
我正在使用 check-equal?
编写一堆测试,其中的对象包含不是 eq?
的语法对象。出于这些测试的目的,如果两个语法对象在给定 syntax->datum
时相等,我可以说它们是相等的。 (是的,我知道这会丢失很多绑定信息,但是目前,确保它们的数据相等就足够了。稍后我会测试绑定信息是否良好。)
如果这两个对象不是语法对象,但是,如果它们彼此 equal?
,我希望它们相等。
但是,如果这些对象在某个递归点包含语法对象,我想在它们的数据上测试它们的相等性,所以我不能这样做:
(define (my-equal? a b)
(if (and (syntax? a) (syntax? b)
(equal? (syntax->datum a) (syntax->datum b))
(equal? a b)))
(define-binary-check (check-my-equal? my-equal? actual expected))
因为这不会进行递归检查。
我可以自己处理递归,并且只在基元上使用 equal?
,但这对于实现我自己的相等性测试至关重要。
您可以使用 equal?/recur
获得此行为。此函数的行为类似于 equal?
,但在递归调用的情况下采用不同的函数。所以你可以像这样实现 my-equal?
:
(define (my-equal? actual expected)
(if (and (syntax? actual) (syntax? expected))
(equal? (syntax->datum actual) (syntax->datum expected))
(equal?/recur actual expected my-equal?)))
但是请注意,由于您提供的是递归函数,equal?/recur
不会为您进行任何循环检测。因此,您需要自己做。一种简单的方法是使用参数:
(define current-equal-visited (make-parameter set))
(define (my-equal? actual expected)
(cond [(set-member? (current-equal-visited) (cons actual expected))
#t]
[(and (syntax? actual) (syntax? expected))
(equal? (syntax->datum actual) (syntax->datum expected))]
[else
(parameterize ([current-equal-visited
(set-add (current-equal-visited) (cons actual expected))])
(equal?/recur actual expected my-equal?))]))
然后,当然,正如您在问题中注意到的那样,您可以使用 define-binary-check
将此过程变成 RackUnit 的东西。
(define-binary-check (check-my-equal? my-equal? actual expected))