Ассоциированная эквивалентная процедура не функционирует должным образом

Я пытаюсь написать процедуру, аналогичную схеме Sche. Единственное различие между ними заключается в том, что я хочу, чтобы моя процедура возвращала только значение, относящееся к данному ключу, где в качестве assoc выдает всю пару (key. Value). Вот моя процедура:

(define alist '((a . 1) (b . 2) (c . 3)))

(define (search-list key list)
  (cond ((null? key) #f)
        ((eq? (caar list) key) (cdar list))
        ((null? (cdr list)) #f)
        (else search-list key (cdr list))))

Кажется, я на правильном пути - (search-list 'aist) возвращает 1. Однако, при тестировании с (search-list 'b alist), это мой вывод: ((b . 2) (c . 3))

Я не могу понять, почему моя процедура не работает так, как я намереваюсь. Я был бы очень рад, если бы вы могли указать на ошибку в моей процедуре. Заранее спасибо.

3 ответа

Решение

Проблема заключалась в вызове (или, скорее, пропущенном вызове) в список поиска в последней строке. Поскольку это не было заключено в круглые скобки, процедура никогда не вызывалась рекурсивно, и процедура возвращала (список cdr) вместо (ключ списка поиска (список cdr)). Этот код работает как задумано:

(define alist '((a . 1) (b . 2) (c . 3)))

(define (search-list key list)
  (cond ((null? key) #f)
        ((eq? (caar list) key) (cdar list))
        ((null? (cdr list)) #f)
        (else (search-list key (cdr list)))))

Вы нашли свою ошибку, но я бы предложил другие изменения:

1) перед использованием следует проверить, пуст ли список caar и тому подобное, потому что ваша процедура потерпит неудачу при вызове с пустым списком.

2) OTOH, нет необходимости проверять, является ли ключ нулевым.

3) В схеме не следует использовать list в качестве имени параметра, чтобы не затенять процедуру list,

Так что я бы пошел на

(define (search-list key lst)
  (cond
    ((null? lst) #f)
    ((eq? key (caar lst)) (cdar lst))
    (else (search-list key (cdr lst)))))

Обратите внимание, что вы не хотите точно поведение assq (который assoc с помощью eq? не equal?) но вы все еще можете использовать assq в реализации:

(define (search-list key lst)
  (cond ((assq key lst) => cdr)
        (else #f)))

> (search-list 'b '((a . 1) (b . 2) (c . 3)))
2

Кроме того, ваш существующий код будет иметь проблемы со списком '() так как caar не удастся. Обычно в рекурсивных алгоритмах базовый случай, который (null? lst) в вашем случае проверяется первым.

Другие вопросы по тегам