用Hy宏生成Python代码
我正在尝试从Hy生成一些python代码。如何做得更好 我试过几种方法。一个是宏:用Hy宏生成Python代码,python,macros,lisp,hy,Python,Macros,Lisp,Hy,我正在尝试从Hy生成一些python代码。如何做得更好 我试过几种方法。一个是宏: (defmacro生成变量[数据] (setv res'()) (对于[元素数据] (setv变量名(HySymbol(+“var”(str元素))) (setv res(cons`(setv~varname 0)res))) `(do~@res)) 然后在捕获宏扩展后,我打印代码的python反汇编 但是,对于宏,我似乎无法传递变量,因此: (setv vnames[1 2 3]) (制作变量vnames)
(defmacro生成变量[数据]
(setv res'())
(对于[元素数据]
(setv变量名(HySymbol(+“var”(str元素)))
(setv res(cons`(setv~varname 0)res)))
`(do~@res))
然后在捕获宏扩展后,我打印代码的python反汇编
但是,对于宏,我似乎无法传递变量,因此:
(setv vnames[1 2 3])
(制作变量vnames)
定义varv
、varn
、vara
等,而不是var1
、var2
、var3
。似乎可以通过以下方式进行正确调用:
(宏扩展`(生成变量~vnames))
但这似乎过于复杂
我遇到的另一个问题是HySymbol
的必要性,这让我大吃一惊。但当我尝试第二种方法时,我真的受到了伤害,在第二种方法中,我创建了一个返回带引号的表单的函数:
(defn使派系分离[派系元数据单元类型]
(让[metabase(获取元数据“base”)
元模式(获取元数据“节”)
类别cand[]
类定义'()
班级分组(dict)]
(对于[(,sec name sec flag)(.iteritems元模式)]
;如果设置了节标志,但找不到包含该节的单元类型,则中断并不返回任何内容
(打印“检查”sec名称)
(如果不是(或(非sec标志)(任何(genexpr(sec名称(.ut角色))[ut单元类型])
(休息)
;保存节的单位类型
(做
(打印“与章节匹配”章节名称)
(setv sec分组(列出组件ut[ut单元类型]
(在sec名称(.ut角色)中)
(打印(len-sec分组)为“section name”找到的类型
(当sec分组时)
(assoc类别分组sec名称sec分组)))
万一我们完成了循环
(其他
(做
(定义
类名(.format“{}}{}”(.metabase\uuuuuuu name\uuuuuuuu)(固定阵营字符串阵营))
陆军id(.format“{}}{}”(.metabase-army_-id)(固定派系字符串派系))
陆军名称(.format“{}({})”(确定派系名称派系)(.meta-base-army_-name)))
(打印“类名为”类名)
(打印“陆军id为”陆军id)
(打印“陆军名称为”陆军名称)
(setv类别cand[(HySymbol类别名称)])
(setv类def[`(defclass~(HySymbol类名)[~(HySymbol(.metabase__name__))]
[陆军名称(希斯特林陆军名称)
派系(希斯林派系)
陆军识别号(希斯特林陆军识别号)]
(defn--init--[self]
(.--init--(super)~(HyDict)(交错(genexpr(HyString k)[k类分组])
(循环[(整数1)])
~@(地图(fn[键]
`(.添加类(.self~(HySymbol键))
~(HyList(genexpr(HySymbol(.ut\uuu name\uuuuu))
[ut(获取类分组键)])
类分组)]]))
(,等级def等级cand)))
该函数获取的元数据在python中如下所示:
metadata = [
{'Base': DetachPatrol,
'Sections': {'hq': True, 'elite': False,
'troops': True, 'fast': False,
'heavy': False, 'fliers': False,
'transports': False}}]
并获取具有以下形式的类的列表:
class SomeSection(object):
roles = ['hq']
它需要大量使用hy的内部类,我无法正确地表示True和False,而是求助于HyInteger(1)
和HyInteger(0)
为了从这个函数中获取python代码,我通过反汇编运行它的结果
总结如下:
从Hy生成python代码的最佳方法是什么
什么是真与假的内在表征
可以调用处理其参数并从宏返回带引号的Hy表单的函数吗?如何调用
在Hy中,通常不需要生成Python代码,因为Hy更擅长生成Hy代码,并且它是可执行的。这在Hy宏中一直都是这样做的
在不寻常的情况下,您需要生成真正的Python而不仅仅是Hy,最好的方法是使用字符串,与在Python中使用的方法相同。Hy编译到Python的AST,而不是Python本身。反汇编程序实际上只是为了调试目的。它并不总是生成有效的Python:
=> (setv +!@$ 42)
=> +!@$
42
=> (disassemble '(setv +!@$ 42) True)
'+!@$ = 42'
=> (exec (disassemble '(setv +!@$ 42) True))
Traceback (most recent call last):
File "/home/gilch/repos/hy/hy/importer.py", line 193, in hy_eval
return eval(ast_compile(expr, "<eval>", "eval"), namespace)
File "<eval>", line 1, in <module>
File "<string>", line 1
+!@$ = 42
^
SyntaxError: invalid syntax
=> (exec "spam = 42; print(spam)")
42
您可以询问REPL在引用表单中使用的类型
=> (type 1)
<class 'int'>
=> (type '1)
<class 'hy.models.HyInteger'>
=> (type "foo!")
<class 'str'>
=> (type '"foo!")
<class 'hy.models.HyString'>
=> (type True)
<class 'bool'>
=> (type 'True)
<class 'hy.models.HySymbol'>
Python的dict
由一个哈希表支持,而Hy的HyDict
模型实际上只是一个列表。这是因为它并不表示哈希表本身,而是表示生成dict的代码。这就是为什么可以像列表一样拼接到其中
但是,如果可能,您能否添加一个将动态生成的字符串正确传递到最终引用表达式的示例?据我所知,增加一项作业(即增加报价)就可以完成,但有没有更优雅的方法
它们被认为是公共API的一部分,只是在宏之外很少使用。在需要的时候使用它们是可以的。其他Lisp在代码模型对象和它们生成的数据之间没有相同的区别。Hy这样做是为了更好地实现Python互操作。有人可能会说,~
语法应该为某些数据类型自动进行这种转换,但目前没有。
[更新:在当前主分支上,Hy的编译器将在可能的情况下自动将兼容值包装到Hy模型中,因此您通常不必自己再这样做。]
HySymbol
适用于dynami
=> (type 1)
<class 'int'>
=> (type '1)
<class 'hy.models.HyInteger'>
=> (type "foo!")
<class 'str'>
=> (type '"foo!")
<class 'hy.models.HyString'>
=> (type True)
<class 'bool'>
=> (type 'True)
<class 'hy.models.HySymbol'>
{~@(interleave (map HyString class-grouping) (repeat '1))}
(def class-name (.format "{}_{}" (. meta-base __name__) ...
(def class-name (HySymbol (.format "{}_{}" (. meta-base __name__) ...
(setv class-cand [class-name])
(setv class-def [`(defclass ~class-name ...