Trouble with this macro
令人尴尬的是,我在正确设计此宏时遇到了一些麻烦。
这是我写的宏:
1 2 3 4 | (defmacro construct-vertices [xs ys] (cons 'draw-line-strip (map #(list vertex %1 %2) xs ys))) |
它需要接受两个集合或序列,
1 2 3 | (draw-line-strip (vertex 0 1) (vertex 1 1) (vertex 3 3) (vertex 5 6) (vertex 7 8)) |
…对于
如果我给我的宏简单的n个简单向量(例如
我意识到这是因为这些未传递给未经评估的宏,因此我得到了例如
我确定我在这里缺少某种基本的语法-quote / unquote模式-我很乐意提供一些帮助/指针!
非常感谢。
编辑我应该提到,
编辑2这是我需要的自定义图形工具,创建它的主要动机是要比JFreeCharts和company更快。
编辑3我想我应该注意,我确实有一个宏版本正在工作,正如我上面提到的那样,它只是恐怖和骇人。它使用
1 2 3 4 | (defmacro construct-vertices [xs ys] (cons 'draw-line-strip (map #(list vertex %1 %2) (eval xs) (eval ys)))) |
不幸的是,我得到…
…与数千个长列表一起使用时。这是因为我在预编译的代码中写的太多了,而类文件无法处理(我想)那么多的数据/代码。就像我建议的那样,看来我需要以某种方式获取
但是,我仍然对这个问题有一个更优雅,更朴实的宏解决方案持开放态度。如果存在!
我查看了画线条纹的宏扩展,发现它只是将主体包裹在一个绑定,gl-begin和gl-end中。因此,您可以将所需的任何代码放入其中。
所以
1 2 3 | (defn construct-vertices [xs ys] (draw-line-strip (dorun (map #(vertex %1 %2) xs ys)))) |
应该管用。
如果您确实需要
1 2 3 4 | (defn construct-vertices [xs ys] (eval `(draw-line-strip ~@(map #(list 'vertex %1 %2) xs ys)))) ; ^- not sure what vertex is ; and thus whether you need this quote |
请注意,除非确实必要,否则这是可怕的样式。
为什么不这样呢,使用函数而不是宏:
1 2 | (defn construct-vertices [xs ys] (apply draw-line-strip (map #(list vertex %1 %2) xs ys))) |
那应该用必需的参数调用draw-line-strip。此示例不是最适合宏的示例,不应在函数可以使用的地方使用它。
注意:我没有尝试过,因为我没有在此盒子上设置粘液。
编辑:再次查看,我不知道您是否要在调用draw-line-strip之前评估顶点。在这种情况下,函数将如下所示:
1 2 | (defn construct-vertices [xs ys] (apply draw-line-strip (map #(vertex %1 %2) xs ys))) |
这看起来像是Lisp中某些宏系统的典型问题。通常使用Lisp文献。例如,Paul Graham撰写的On Lisp(使用Common Lisp)。
通常,宏使用它所包含的源并生成新的源。如果宏调用为(foo bar),并且宏应基于bar的值生成一些不同的东西,则通常是不可能的,因为bar的值通常不适用于编译器。 BAR实际上仅在运行时具有一个值,而在编译器扩展宏时则没有。因此,人们需要在运行时生成正确的代码-这可能是可行的,但通常被认为是不好的风格。
在这些宏系统中,不能应用宏。一个典型的解决方案如下所示(Common Lisp):
1 2 3 | (apply (lambda (a b c) (a-macro-with-three-args a b c)) list-of-three-elements) |
但是,并非总是可以使用上述解决方案。例如,当参数数量变化时。
DRAW-LINE-STRIP是宏也不是一个好主意。最好将其编写为函数。