Ассоциированная эквивалентная процедура не функционирует должным образом
Я пытаюсь написать процедуру, аналогичную схеме 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)
в вашем случае проверяется первым.