2017-04-06 87 views
1

看來,方案考慮了一些整數和浮點版本採用相同的時候是不同的?,但同樣使用=時,對它們進行比較:不過,如果我遞歸數值等於

(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))))) 

但似乎這將是一個非常普通的任務計劃可能有一個內置的方法來做到這一點。

回答

3

在拍你可以通過內置程序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過程處理,通過對,結構等

2

方案是一種簡約的語言,並有很少的原語。 22.0不是相同的數字,因爲2.0可以低於和高於2,這是確切數量2

如果你有一個數字的列表,並希望檢查所有都是一樣的用=,您可以在使用everySRFI-1 List Library做:

;; 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 

在R6RS它變得更簡單:

#!r6rs 

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

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

既然你已經標記了球拍,你有可能不會寫Scheme,但也許有#lang racket,它既支持SRFI-1,也支持它自己的版本every,它被稱爲andmap

#lang racket 

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

(require srfi/1) 
(every = '(2 3) '(2.0 3.0)) ; ==> #t 

編輯

對於使用本身樹狀結構和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

啊復發,這對號碼清單一個很好的解決方案。這聽起來像是對於更復雜的結構,比如'(a 2(b 3))與'(a 2.0(b 3.0)),你可能需要編寫一個自定義函數。 –

+0

@JeffAmes我編輯了一個製作通用平等製造商的例子,您可以指定如何比較某些類型。 – Sylwester