Scheme中的递归数字相等

时间:2017-04-06 16:01:04

标签: recursion scheme racket equality r5rs

似乎Scheme在使用等于?时考虑数字的整数和浮点版本,但在使用=来比较它们时相同:

(equal? 2 2.0)  ; => #f
(= 2 2.0)       ; => #t

但是,如果我有一个带有一些数字部分的递归结构(甚至是一个简单的数字列表),是否有一种比较它们的方法,使用=进行数值比较?

(equal? '(2 3) '(2.0 3.0))  ; => #f
(= '(2 3) '(2.0 3.0))       ; error: contract violation

我可以编写自己的相等检查器,如下所示:

(define myequal?
  (lambda (x y)
    (cond ((and (null? x) (null? y)) #t)
          ((or (null? x) (null? y)) #f)
          ((and (pair? x) (pair? y))
           (and (myequal? (car x) (car y))
                (myequal? (cdr x) (cdr y))))
          ((or (pair? x) (pair? y)) #f)
          ((and (number? x) (number? y)) (= x y))
          ((or (number? x) (number? y)) #f)
          (else (equal? x y)))))

但似乎这是一个足够普遍的任务,Scheme可能有一个内置方法来执行此操作。

2 个答案:

答案 0 :(得分:3)

在Racket中,您可以借助equal?/recur内置程序构建所需的平等概念:

;; equalish? : Any Any -> Boolean
;; Like equal?, but use = for numbers (including within compound data)
(define (equalish? a b)
  (if (and (number? a) (number? b))
      (= a b)
      (equal?/recur a b equalish?)))

(equalish? '(2 3) '(2.0 3.0))
;; => #t

equal?/recur过程处理通过对,结构等重复出现。

答案 1 :(得分:2)

Scheme是一种简约语言,只有很少的原语。 22.0不是同一个数字,因为2.0可以低于2,而2就是确切的数量=

如果您有一个包含数字的列表,并希望检查所有内容是否与;; include the library. In R5RS this is impleentation specific ;; and worst case you need to load of external file to be portable. (load "srfi1.scm") (every = '(2 3) '(2.0 3.0)) ; ==> #t 相同,则可以使用every中的SRFI-1 List Library来执行此操作:

#!r6rs

(import (rnrs base)
        (only (srfi :1) every))

(every = '(2 3) '(2.0 3.0)) ; ==> #t

在R6RS中它变得更简单:

#lang racket

由于你已经标记了Racket,你可能不会编写Scheme,但也许every同时支持SRFI-1和它自己的#lang racket (andmap = '(2 3) '(2.0 3.0)) ; ==> #t (require srfi/1) (every = '(2 3) '(2.0 3.0)) ; ==> #t 版本,称为{{3} }}:

equal?

修改

当没有更多特定于类型的选项时,所有用于树结构的树结构和(define (make-equal . predicates-and-equal-procedures) (when (odd? (length predicates-and-equal-procedures)) (error "make-equal needs an even number of predicate and equal function arguments")) (define (mequal? a b) (if (pair? a) (and (pair? b) (mequal? (car a) (car b)) (mequal? (cdr a) (cdr b))) (let loop ((pe predicates-and-equal-procedures)) (if (null? pe) (equal? a b) (let ((p? (car pe))) (if (p? a) (and (p? b) ((cadr pe) a b)) (loop (cddr pe)))))))) mequal?) (define list=? (make-equal number? =)) (list=? '(1 2 a b "test") '(1.0 2 a b "test")) ; ==> #t (define equal-ci? (make-equal string? string-ci=? char? char-ci=?)) (equal-ci? '(1 2 a b "Test") '(1 2 a b "test")) ; ==> #t (define inexact-eq-ci? (make-equal number? = string? string-ci=? char? char-ci=?)) (inexact-eq-ci? '(1 2 a b "test") '(1.0 2 a b "TEST")) ; ==> #t 的通用解决方案:

{{1}}