如何在球拍中创建一个宏,其中一个列表成为所述lambda的args? [英] how to create a macro in racket where a list becomes the args of said lambda?

查看:61
本文介绍了如何在球拍中创建一个宏,其中一个列表成为所述lambda的args?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我该如何做一个define-syntax-rule接受一个列表作为参数,一个列表(或引号,如果是单个元素的话)作为lambda的主体? 我想做类似的事情:

    >(define a (lambdarize '(x y z) '(+ x y z)))
    #<procedure>
    >(a 1 2 3)
    6
    >(define b (lambdarize '(x) 'x))
    #<procedure>
    >(b 1)
    1

我曾经玩过define-syntax-ruleapply,但是由于lambda本身似乎是一个宏而不是一个过程,所以我很困惑地试图找到它...

哦...我想要一个不使用eval的解决方案,因为它很有害...

更新

感谢您的回答,瑞安...差不多做到了! =)eval的问题在于它不能很好地捕获当前范围...这样我就可以做

    (let ([a 1])
        (begin
            (defmethod add ((x integer?) (y integer?)) (+ x y a))
            (add 1 2)
    )

这将因评估而惨败...这只是一个学术例子,但我认为这是对正确性的良好测试.

解决方案

如果不使用eval,则无法创建将形式参数和主体作为运行时值(S-表达式)给出的函数. >

但是根据您对Greg评论的回答,您可以更改您的defmethod宏来避免此问题.您当前的方法采用变量和主体表达式(程序项),将它们转换为运行时值,然后希望将它们重新解释为程序项.相反,您应该将程序项组合到宏中的lambda表达式中,然后可以将其作为值传递给辅助函数:

(define-syntax-rule (defmethod name ((var predicate) ...) body)
  (add-to-generic name
                  (list predicate ...)
                  (lambda (var ...) body)))

如果您想保留变量名(例如,对于错误消息),也可以用引号将它们括起来,但要与lambda -expression分开:

(define-syntax-rule (defmethod name ((var predicate) ...) body)
  (add-to-generic name
                  (list predicate ...)
                  '(var ...)                 ;; for errors, debugging, etc
                  (lambda (var ...) body)))

How would I go about in doing a define-syntax-rule that accepts a list as arguments and a list (or a quote, in case it is a single element) as body of a lambda? i would like to do something like:

    >(define a (lambdarize '(x y z) '(+ x y z)))
    #<procedure>
    >(a 1 2 3)
    6
    >(define b (lambdarize '(x) 'x))
    #<procedure>
    >(b 1)
    1

I have played around with define-syntax-rule and apply, but since lambda itself seems to be a macro and not a procedure, i have been stumped at trying to find it...

oh... And I would like a solution that does not use eval, as it is pernicious...

UPDATE

thanks for the answer, Ryan... that pretty much did it! =) the problem with eval was that it is no good at catching the current scope... this way i can do stuff like

    (let ([a 1])
        (begin
            (defmethod add ((x integer?) (y integer?)) (+ x y a))
            (add 1 2)
    )

which would fail miserably with eval... this is just an academic example, but i think it is a good test for correctness.

解决方案

It's not possible to create a function where the formal parameters and body are given as run-time values (S-expressions) without using eval.

But based on your answer to Greg's comment, you can change your defmethod macro to avoid this issue. Your current approach takes the variables and body expression (program terms), converts them to run-time values, then wants to reinterpret them as program terms. Instead, you should just combine the program terms into a lambda-expression in the macro, which you can then pass as a value to the helper function:

(define-syntax-rule (defmethod name ((var predicate) ...) body)
  (add-to-generic name
                  (list predicate ...)
                  (lambda (var ...) body)))

If you wanted to keep the variable names around (eg for error messages), you can also quote them, but separate from the lambda-expression:

(define-syntax-rule (defmethod name ((var predicate) ...) body)
  (add-to-generic name
                  (list predicate ...)
                  '(var ...)                 ;; for errors, debugging, etc
                  (lambda (var ...) body)))

这篇关于如何在球拍中创建一个宏,其中一个列表成为所述lambda的args?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆