Схема списка из двух элементов

Мне нужно написать функцию, которая определяет, является ли данный список парой элементов. Программа просто ответит #t, если список содержит ровно два элемента, или #f, если нет, например:

(zipper? '((a 1)(b 2))) => #t

и

(zipper? '((foo 100)(bar 2 3))) => #f

Я все еще довольно новичок в Scheme, поэтому любая помощь будет очень признательна! Спасибо!


person Nelson.b.austin    schedule 28.01.2014    source источник
comment
Вы хотите проверить, содержит ли список ровно два элемента (как вы говорите) или список содержит только списки из двух элементов (что, по-видимому, подразумевает ваш второй пример?   -  person molbdnilo    schedule 30.01.2014
comment
Мой ответ учитывает оба случая, упомянутых @molbdnilo, какой из них был правильным? и не забудьте принять его ;)   -  person Óscar López    schedule 30.01.2014


Ответы (2)


Неясно, является ли "правильный" ввод для процедуры произвольным списком или списком из двух элементов. Если это строго двухэлементный список, это будет работать:

(define (is-two-element-list? lst)
  (and (list? lst)
       (= (length lst) 2)))

(define (zipper? lst)
  (and (is-two-element-list? lst)
       (is-two-element-list? (first lst))
       (is-two-element-list? (second lst))))

… И если это список произвольной длины, элементы которого мы хотим проверить, это будет работать в Racket, используя andmap:

(define (zipper? lst)
  (andmap is-two-element-list? lst))

Если вы не используете Racket, то это решение с использованием every будет работать в любом интерпретаторе с SRFI:

(require srfi/1)

(define (zipper? lst)
  (every is-two-element-list? lst))

В любом случае, обратите внимание, что трюк заключался в определении процедуры is-two-element-list?, которая проверяет свойство двухэлементного списка, после чего мы можем применить ее по мере необходимости.

person Óscar López    schedule 29.01.2014

Подумайте об этом так. Если список zipper равен '(), то ответ будет #t. Если список zipper не равен '(), то если первый элемент состоит из двух элементов, а остальные — из другого zipper?, то возвращается #t.

(define (zipper? list)
  (or (null? list)
      (and (= 2 (length (car list)))
           (zipper? (cdr list)))))

или, может быть, вы имели в виду:

(define (zipper? list)
  (or (not (pair? list))
      (and (= 2 (length list))
           (zipper? (list-ref list 0))
           (zipper? (list-ref list 1)))))

каждый элемент на любом уровне состоит из двух элементов.

> (zipper? '((a 1 2) '(b)))
#f
> (zipper? '(a b))
#t
> (zipper? '(((a (b b)) c) (1 2)))
#t
person GoZoner    schedule 29.01.2014