macros - (Chez) 用于隐藏 lambda 的方案宏

标签 macros scheme associative-array chez-scheme

我想编写一个宏来创建速记语法来隐藏更详细的 lambda 表达式,但我很难理解如何编写宏(我意识到这是反对使用它们的一个论点)。

给出这个例子:

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

(define ($ alist name)
  (cdr (assoc name alist)))

((lambda (a) (map (lambda (x y z) (+ x y z)) ($ a 'x) ($ a 'y) ($ a 'z))) alist-example)
((lambda (a) (map (lambda (y) (/ y (apply max ($ a 'y)))) ($ a 'y))) alist-example)

我想编写一个宏,with-alist,它允许我编写与此类似的最后两个表达式:

(with-alist alist-example (+ x y z))
(with-alist alist-example (/ y (apply max y)))

有什么意见或建议吗?

最佳答案

这是一个基于我在其他答案和评论中收到的反馈的syntax-rules解决方案:

(define ($ alist name)
  (cdr (assoc name alist)))

(define-syntax with-alist
  (syntax-rules ()
    [(_ alist names expr)
     (let ([alist-local alist])
       (apply map (lambda names expr)
              (map (lambda (name) ($ alist-local name)) (quote names))))]))

以下是一些示例用法:

> (define alist-example
  '((x 1 2 3) (y 4 5 6) (z 7 8 9)))
> (with-alist alist-example (x) (+ x 2))
(3 4 5)
> (with-alist alist-example (x y) (+ x y))
(5 7 9)
> (with-alist alist-example (x y z) (+ x y z))          
(12 15 18)

这个答案未能解决我的问题中更复杂的示例,(with-alist alist-example (/y (apply max y))),但我认为这是合理的达到我的目的的方法:

> (with-alist alist-example (y) (/ y (apply max ($ alist-example 'y))))
(2/3 5/6 1)

编辑:经过一些额外的修改,我得出了一个略有不同的解决方案,我认为它将提供更大的灵活性。

我的新宏 npl 将速记表达式扩展为名称和过程列表。

(define-syntax npl
  (syntax-rules ()
    [(_ (names expr) ...)
     (list 
      (list (quote names) ...)
      (list (lambda names expr) ...))]))

该宏的输出将传递给常规过程 with-list-map,该过程包含上面 with-alist 宏中的大部分核心功能。

(define (with-alist-map alist names-proc-list)
  (let ([names-list (car names-proc-list)]
        [proc-list (cadr names-proc-list)])
    (map (lambda (names proc)
           (apply map proc
                  (map (lambda (name) ($ alist name)) names)))
         names-list proc-list)))

上述 with-alist 用法的 3 个示例可以通过对 with-alist-map 的单次调用来捕获。

> (with-alist-map alist-example
                (npl ((x) (+ x 2))
                     ((x y) (+ x y))
                     ((x y z) (+ x y z))))
((3 4 5) (5 7 9) (12 15 18))

关于macros - (Chez) 用于隐藏 lambda 的方案宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60625913/

相关文章:

C++ constexpr 与字符串文字中的宏与整数

c++ - Boost.Log 宏扩展和条件三元运算符

architecture - 学习如何使用类似 Lisp 的语言设计和实现大型复杂的应用程序

scheme - 你如何找到MIT方案中发生错误的地方?

list - 在方案中将包含二进制数的列表转换为十进制和十六进制

c - 只计算一次宏参数

c - 宏作为 switch-case 中的一个案例在 c 中不起作用

javascript - 使用 d3.js 在表中显示关联数组的数据

php - 格式化关联数组声明

javascript - 将对象添加到数组中的特定索引处