Issues with conditionals in Scheme

大兔子大兔子 提交于 2019-12-13 05:05:51

问题


I'm using Scheme with the full Swindle package, and I'm trying to use conditionals to recursively determine evenness/oddity of integers. My code is as follows:

(define (odd? x)(
            (cond 
              ((= x 0) '#f)
              ((= x 1) '#t)
              ((= (even? (- x 1)) #t) '#f)
              (else '#t))))

(define (even? x)(
              (cond
                ((= x 0) '#f)
                ((= x 2) '#t)
                ((= (odd? (- x 1)) #t) '#f)
                (else '#t))))

However, when I run (even? x) or (odd? x) [x is some number, doesn't matter what, as I get the same error] I get: application: not a procedure; expected a procedure that can be applied to arguments given: #t arguments...: [none]

Can anyone help? Thanks. I'm not 100% familiar with ideal Scheme syntax, so it might be that.


回答1:


You have an erroneous pair of parentheses surrounding the cond expression (that's causing the error reported). But also, there are way too many conditions in each procedure, and because you're using = to compare numbers with boolean values, there will be a point where a contract violation will occur. For fixing that you can replace = with equal? in here:

((equal? (even? (- x 1)) #t) '#f)

And in here:

((equal? (odd? (- x 1)) #t) '#f)

But then, the procedures will still give an incorrect result:

(even? 5)
=> #t
(odd? 7)
=> #f

Honestly, I think it'd better to simplify the implementation, that will solve all the problems. Try this instead:

(define (odd? x)
  (cond ((= x 0) #f)
        (else (even? (- x 1)))))

(define (even? x)
  (cond ((= x 0) #t)
        (else (odd? (- x 1)))))

Now we'll get correct answers:

(even? 4)
=> #t
(even? 5)
=> #f
(odd? 6)
=> #f
(odd? 7)
=> #t



回答2:


Any Scheme form in parentheses is an application, like (sin 42) or (42 sin). The first calls sin as a function with argument 42 and produces a value; the second tries to call 42 with an argument sin, but 42 is no procedure, so this causes an error. Similarly (42) is an application with no arguments; still it must have a procedure to be applied as its first part, to be called with no arguments, right? In Scheme, parentheses matter, they are not just for grouping stuff (as they may be in some other languages). So the extra parentheses cause an extra attempt to evaluate the result, which is a Boolean, i.e. not a procedure, so this is an error.

Then, '#f is just #f; similarly for #t (they both evaluate to themselves); and a condition (= test #t)1(equal? test #t) is the same as just test (produces the same set of Boolean results) ((1 we can't use = to compare Booleans, it is supposed to be used with numbers only)):

(define (odd? x)
        (cond 
          ((= x 0) #f)
          ((= x 1) #t)
          ((even? (- x 1)) #f)
          (else #t)))

Also, (if test #f else...) is the same as (if (not test) else... #f):

(define (odd? x)
        (cond 
          ((= x 0) #f)
          ((= x 1) #t)
          ((not (even? (- x 1))) #t)
          (else #f)))                 ; (else ...) is like (#t ...)

using logical connectives, the clauses with the same outcome can be merged, and mutually exclusive clauses can be rearranged (mutual exclusivity can be achieved with explicit guards):

(define (odd? x)
        (cond 
          ((and (/= x 0)              ; a guard
                (or (= x 1) 
                    (not (even? (- x 1))))) #t)
          ((or (= x 0) #t) #f)))

but (cond (test #t) (else #f) is (if test #t #f) which is just test:

(define (odd? x) (and (> x 0)         ; `>` is better
                      (or (= x 1) 
                          (not (even? (- x 1))))))

The guard (> x 0) prevents the fall-through for negative xes.

But then, this is completely wrong. For n to be odd, n-1 must be even, not the opposite!

(define (odd? x) (and (> x 0)         ; work only for positive integers
                      (or (= x 1) 
                          (even? (- x 1)))))

We could write (not (odd? (- x 1))), but then it wouldn't be tail recursive. It would be tail recursive modulo cons (not serving as a "constructor"), but for some historic fluke of a reason2, TRMC optimization isn't required of a Scheme implementation. The last expression in and and or forms is, in fact, in tail position. But not in not. ((2 despite being described as early as 1974.))

Repeat the same for your definition of even?.



来源:https://stackoverflow.com/questions/19886294/issues-with-conditionals-in-scheme

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!