首页 > 解决方案 > 从 for 循环生成代码的宏

问题描述

这个例子有点做作。目标是创建一个循环遍历某些值并以编程方式生成一些代码的宏。

Python 中的一个常见模式是在调用时初始化对象的属性,如下所示:

(defclass hair [foo bar]
  (defn __init__ [self]
    (setv self.foo foo)
    (setv self.bar bar)))

这正确地转换hy2py

class hair(foo, bar):

    def __init__(self):
        self.foo = foo
        self.bar = bar
        return None

我知道有解决这个问题的 Python 方法,包括 attr.ib 和数据类。但作为一个简化的学习练习,我想用一个宏来解决这个问题。

这是我的非工作示例:

(defmacro self-set [&rest args]
  (for [[name val] args]
    `(setv (. self (read-str ~name)) ~val)))

(defn fur [foo bar]
  (defn __init__ [self]
    (self-set [["foo" foo] ["bar" bar]])))

但这并没有扩展到原始模式。hy2py显示:

from hy.core.language import name
from hy import HyExpression, HySymbol
import hy


def _hy_anon_var_1(hyx_XampersandXname, *args):
    for [name, val] in args:
        HyExpression([] + [HySymbol('setv')] + [HyExpression([] + [HySymbol
            ('.')] + [HySymbol('self')] + [HyExpression([] + [HySymbol(
            'read-str')] + [name])])] + [val])


hy.macros.macro('self-set')(_hy_anon_var_1)


def fur(foo, bar):

    def __init__(self, foo, bar):
        return None

我做错了吗?

标签: hy

解决方案


for表格总是返回None。因此,您的循环正在构建(setv ...)您请求的表单,然后将它们丢弃。取而代之的是 try lfor,它返回一个结果列表,或者gfor,它返回一个生成器。另请注意,在下面的示例中,我使用do将生成的表单分组在一起,并且我已经移动了 a~以便read-str在编译时发生,因为它必须为了.工作。

(defmacro self-set [&rest args]
  `(do ~@(gfor
    [name val] args
    `(setv (. self ~(read-str name)) ~val))))

(defclass hair []
  (defn __init__ [self]
    (self-set ["foo" 1] ["bar" 2])))

(setv h (hair))
(print h.bar)   ; 2

推荐阅读