将元素添加到方案中的关联列表中

问题描述 投票:0回答:1

我正在学习计划,并达到了我目前所学知识的极限。我怀疑宏可能是完成这项工作的正确工具,但是...

我想编写一个过程,其中基于用户提供的表达式来操作关联列表的内容。如果我们有此关联列表,

(define a '((x (1 2 3)) (y (4 5 6)) (z (7 8 9))))

然后,我希望有一个基于关联列表的当前元素将新元素添加到关联列表的过程。

(define (add-element alist proc)
  ;; this is part that I'm struggling with
  )

这里有几个用法示例:

(add-element a '(w (* x y z)))
(add-element a '(w (- (+ y z) (/ y 2)))

我想将这些输入转换为以下内容(对于第二个示例):

(cons
 (list 'w
       (map (lambda (y z)
              (- (+ y z) (/ y 2)))
            (cadr (assoc 'y a))
            (cadr (assoc 'z a))))
  a)

此问题的某些部分似乎可以解决。例如,用户定义的proc的结构使得(car proc)提供新关​​联列表元素的键,而(cadr proc)提供lambda主体。我编写了一个过程(此处未显示)以展平(car proc),提取在关联列表的键中找到的符号并删除重复项。然后,我可以使用该符号列表映射到关联列表,并从关联列表中获取相关元素的列表,以便可以将apply map模式与lambda函数一起使用。但是我不知道如何将lambda函数与符号列表组合在一起。或如何在(cadr proc)主体中使用lambda

编辑:添加代码以显示我使用eval的失败尝试。

  ;; https://stackoverflow.com/questions/8382296/scheme-remove-duplicated-numbers-from-list
  (define (remove-duplicates ls)
    (cond [(null? ls)
       '()]
      [(member (car ls) (cdr ls))
       (remove-duplicates (cdr ls))]
      [else
       (cons (car ls) (remove-duplicates (cdr ls)))]))

 ;; https://stackoverflow.com/questions/28753729/how-to-manually-flatten-a-list-in-racket-scheme
 (define (flatten obj)
  (cond [(null? obj) '()]
        [(list? obj)
         (append (flatten (car obj))
         (flatten (cdr obj)))]
        [else (list obj)]))

 (define (alist-contains? alist symbol)
   (if (member symbol (map car alist)) #t #f))

 (define (extract-alist-keys alist expr)
   (remove-duplicates
    (filter
     (lambda (x)
       (and (symbol? x) (alist-contains? alist x)))
     (flatten expr))))

 (define (add-element alist proc)
   (define new-key (car proc))
   (define body (cadr proc))
   (define key-list (extract-alist-keys alist body))
   (define values-list (map (lambda (x) (cadr (assoc x alist))) key-list))
   (define new-values (eval '(apply map (lambda ,key-list body) ,values-list)))
   (cons (list new-key new-values) alist))

 (add-element a '(w (- (+ y z) (/ y 2))))
lambda macros scheme eval
1个回答
0
投票

我使用eval拼凑了一个解决方案。这是带有add-elementquasiquote的有效应用程序的unquote-splicing过程(我还将所有define语句都更改为let*块):

 (define (add-element alist proc)
   (let* ([new-key (car proc)]
          [body (cadr proc)]
          [key-list (extract-alist-keys alist body)]
          [values-list (map (lambda (x) (cadr (assoc x alist))) key-list)]
          [new-values (eval `(apply map (lambda (,@key-list) (,@body)) values-list))])
     (cons (list new-key new-values) alist)))

[如果有更多经验的人有更好的答案,我将等待几天,然后接受此答案。

© www.soinside.com 2019 - 2024. All rights reserved.