Перебирая список строк, вы найдете строку с нужным префиксом - PullRequest
0 голосов
/ 23 марта 2019

Мне нужно определить функцию plPrefixContained - которая потребляет 5 строк и возвращает первый, который содержит строку "pl" в качестве префикса - если один такой существует и возвращает #f в противном случае.

То, что я пытаюсь сделать, - это использовать функцию префиксов, чтобы просмотреть все строки в списке и проверить их префиксы, поместить их в новый список и вывести первую строку в качестве результата. (Я рассмотрю случай #f позже), мой код внизу, но он продолжает давать мне ошибку-

first: contract violation
  expected: (and/c list? (not/c empty?))
  given: '()

любая помощь будет оценена

(: plPrefixContained : String String String String String -> String)
(define (plPrefixContained x y z w v) 
  (list-ref (prefixes (list x y z w v) '()) 0))


(: prefixes : (Listof String) (Listof String) -> (Listof String))
(define (prefixes lis em)
  (cond
    [(and (eq? (string-ref (first lis) 0) "p") (eq? (string-ref (first lis) 1) "l"))
     (cons (first lis) em)]
    [else
     (prefixes (rest lis) em)]))

так я хочу, чтобы мой вывод был похож, например

(test (plPrefixContained "yypl" "opl" "lpTT" "plpl" "lol")
      =>
      "plpl")

1 Ответ

1 голос
/ 24 марта 2019

Есть две проблемы:

  • интенсиональное равенство eq? вместо экстенсионального равенства, такого как equal? или string=?
  • сравнение строки / символа вместо сравнения символа / символа или строки / строки

Вы используете eq?, что всегда вызывает у меня подозрения. eq? использует "интенсиональное" равенство, которое в основном является равенством указателя, означая, что строка, которая расположена где-то в памяти, не обязательно будет eq?, даже если она имеет те же символы. Вы можете увидеть это с (eq? "abc123" (string-append "abc" "123")).

Если вы имеете дело со строками, списками или любыми другими данными, которые «содержат» вещи, вам следует избегать eq?. Вместо этого вы должны использовать «экстенсиональный» предикат равенства, такой как equal?, или, что еще лучше, предикат, специфичный для ожидаемых вами типов значений, например, string=?. Вот как они ведут себя лучше, чем eq?:

> (eq? "abc123" (string-append "abc" "123"))
#f
> (equal? "abc123" (string-append "abc" "123"))
#t
> (string=? "abc123" (string-append "abc" "123"))
#t

Поскольку вы сравниваете, используя строки "p" и "l", я смогу заменить eq? на string=? в вашем коде:

(: prefixes : (Listof String) (Listof String) -> (Listof String))
(define (prefixes lis em)
  (cond
    [(and (string=? (string-ref (first lis) 0) "p") (string=? (string-ref (first lis) 1) "l"))
     (cons (first lis) em)]
    [else
     (prefixes (rest lis) em)]))

Однако это выявляет вторую проблему, которую я заметил только после появления сообщения об ошибке:

string=?: contract violation
  expected: string?
  given: #\y
  argument position: 1st
  other arguments...:
   "p"

string=? не работает, потому что его первый аргумент, результат string-ref, является символом (например, #\y), а не строкой. Чтобы это исправить, используйте char=? вместо string=? и сравните с символами #\p и #\l вместо строк "p" и "l".

(: prefixes : (Listof String) (Listof String) -> (Listof String))
(define (prefixes lis em)
  (cond
    [(and (char=? (string-ref (first lis) 0) #\p) (char=? (string-ref (first lis) 1) #\l))
     (cons (first lis) em)]
    [else
     (prefixes (rest lis) em)]))
...