我是Racket的新手,需要一些帮助来完成这个功能

时间:2017-07-08 18:23:05

标签: racket

我希望答案为#t

> (is-member? "foo" '(4 5 #f "foo" a))
#t

但我收到了错误:

> (is-member? "foo" '(4 5 #f "foo" a))
;string=?: contract violation
;  expected: string?
;  given: #f
;  argument position: 2nd
;  other arguments...:
;   "foo"

我对is-member?is-member-string?的定义是:

#lang racket

(define (is-member? num lst)
  (if (null? lst)
      #f
      (if (string? num)
          (is-member-string? num lst)
          (is-member-number? num lst))))

(define (is-member-string? num lst)
  (if (null? lst)
      #f
      (if (integer? (car lst))
          (is-member-string? num (rest lst))
          (if (string=? (car lst) num)
              #t
              (is-member-string? num (rest lst))))))

(define (is-member-number? num lst)
  ....)

1 个答案:

答案 0 :(得分:1)

  1. 查看错误消息并了解它对您有何帮助。它说错误来自string=?,如果您查看DrRacket,它甚至会突出显示出错的特定呼叫。它是(string=? (car lst) num)函数中的is-member-string?

  2. 弄清楚是什么论点以及为什么他们错了。错误消息表明错误的参数是#f,它期望一个字符串。

  3. 坏的争论来自哪里?是num还是(car lst)?查看num如何在整个计划中流动,num应始终为"foo",因此可能是另一个(car lst)

  4. 这段代码是如何用错误的参数执行的?为什么(car lst)在这里是假的?因为它在列表中向下走,列表中包含一个false。这应该没问题,只要你正确设计你的功能来处理所有的值。

  5. 为此,您应该在函数上放置一个类型签名,以显示允许哪些类型的参数。对于is-member-string?,我假设你的意思是:

    ;; is-member-string? : String [List-of Any] -> Boolean
    (define (is-member-string? str lst)
       ....)
    

    (我已将num重命名为str,因为它不是数字,而是字符串。)

    接下来,您需要确保代码与签名一起使用。您正在通过解构list参数来设计此函数,但您需要记住值的类型:

    ;; is-member-string? : String [List-of Any] -> Boolean
    (define (is-member-string? str lst)
      (if (null? lst)
          #f
          (.... (first lst) ; (first lst) is an Any
           .... (rest lst)))) ; (rest lst) is a [List-of Any]
    

    (我使用first代替car,因为first更有意义。)

    你能看到现在的错误吗?

    ;; is-member-string? : String [List-of Any] -> Boolean
    (define (is-member-string? str lst)
      (if (null? lst)
          #f
          (if (integer? (first lst))             ; (first lst) is an Any
              (is-member-string? str (rest lst))
              (if (string=? (first lst) str)     ; (first lst) is an Any, but not an integer
                  #t
                  (is-member-string? str (rest lst))))))
    

    (first lst)Any,但您使用的是(string=? (first lst) str)。除非您确定(first lst)是一个字符串,否则不应该允许这样做。

    有两种方法可以做到这一点。解决此问题的一种方法是使用(equal? (first lst) str)代替。

    ;; is-member-string? : String [List-of Any] -> Boolean
    (define (is-member-string? str lst)
      (if (null? lst)
          #f
          (if (equal? (first lst) str)
              #t
              (is-member-string? str (rest lst)))))
    

    第二种方法是在使用string=?之前检查它是否为字符串。我认为你正在尝试使用integer?检查,但它无法正常工作。相反,你想以某种方式使用(string? (first lst))。您只想在通过后检查string=?。一种方法是使用and

    ;; is-member-string? : String [List-of Any] -> Boolean
    (define (is-member-string? str lst)
      (if (null? lst)
          #f
          (if (and (string? (first lst)) (string=? (first lst) str))
              #t
              (is-member-string? str (rest lst)))))