如何在 scheme 中编写一个函数,用 car & cdr 在列表中找到一个元素?

How to write a function in scheme that finds an element in a list with car & cdr?

我是 scheme 的新手,我不知道该怎么做。我有这个列表:

 (define-struct store(id desc price))
 (define master (list
   (make-store 1 'milk 2.50)
   (make-store 2 'meat 3.29)
   (make-store 3 'eggs 1.99)
   (make-store 4 'cereal 2.99)
   (make-store 5 'bread 2.79)
   (make-store 6 'soda 1.29)
   (make-store 7 'water 4.99)))

并且我想创建一个函数,它将接受一个 id 和 return desc 和价格。但我不确定我应该从哪里开始。有人可以帮忙吗?

编辑:有没有办法用 car 和 cdr 做到这一点?我知道我可以根据需要使用 car 和 cdr 使用 (store-id)、(store-desc) 和 (store-price) 检索 id desc 和价格,但我如何将其合并到一个函数中。

你必须使用 struct accessors and some function for list searching or filtering。结构访问器的命名方式如下:如果您有结构 store 并想获取插槽 id 的值,则该访问器将被命名为 store-id:

(store-id (make-store 1 'milk 2.50)) => 1

然后使用 filter or findf 获取结果并使用来自其他两个插槽的值创建新列表。

(define (find-by-id obj id)
  (let ((found (findf (lambda (e)
                        (= (store-id e) id))
                      obj)))
    (if found (list (store-desc found)
                    (store-price found))
        #false)))

(find-by-id master 2)
(find-by-id master 5)
(find-by-id master 8)

编辑: 带有 carcdr 的版本。如果结构列表为空,#false 为 returned。 Else 函数检查列表中的第一个结构。如果 struct-id = id,它将 return 列出值。否则,再次调用此函数,仅使用 cdr of list.

(define (find-by-id lst id)
  (cond ((null? lst) #false)
        ((= (store-id (car lst)) id)
         (list (store-desc (car lst))
               (store-price (car lst))))
        (else (find-by-id (cdr lst) id))))