【问题标题】:Code Generation in ClojureClojure 中的代码生成
【发布时间】:2009-10-26 22:10:06
【问题描述】:

(免责声明:我是 C# 人。我刚刚开始学习 Clojure。)

我了解 Clojure 程序 具有操纵自身或轻松生成其他程序 的能力。这与 Clojure 中的所有内容都是数据结构有关,生成 程序 与创建任何其他类型的数据结构相同。

有没有人有一个很好的示例程序(或一个参考)来说明这一点?

如果你生成一个程序,你能把那个程序“序列化”到磁盘上供以后执行吗?

仅供参考:

  1. 我正在尝试使用遗传编程。我想生成很多小程序,评估它们,并使用成功的程序来生成更多的程序。查看更多herehere

  2. 我认为我在这里误用了术语。 program 实际上是指 clojure 列表,而 Code Generation 是指“列表生成”。我只需要列表包含实际的函数调用和参数。我需要能够控制此列表何时“执行”。

【问题讨论】:

    标签: clojure


    【解决方案1】:

    考虑(+ 1 2)。作为数据,它是三个项目的链表:符号+ 和两个整数。作为代码,它是一个函数调用,上面写着“使用这两个整数作为参数调用名为+ 的函数并给我结果”。你可以对这个列表做任何你可以对任何其他数据列表做的事情。你也可以eval它来获取结果。

    user> (def x '(+ 1 2))
    #'user/x
    user> (first x)
    +
    user> (rest x)
    (1 2)
    user> (map class x)
    (clojure.lang.Symbol java.lang.Integer java.lang.Integer)
    user> (reverse x)
    (2 1 +)
    user> (concat x (rest x))
    (+ 1 2 1 2)
    user> (eval x)
    3
    user> (defn foo []
            (let [ops '[+ - * /]               ; SO's lisp-highlighting sucks
                  nums (repeatedly #(rand-int 5))
                  expr (list* (rand-elt ops) (take 10 nums))]
              (prn expr)
              (prn (eval expr))))
    user> (foo)
    (+ 4 1 0 3 2 3 4 3 1 2)
    23
    nil
    user> (foo)
    (- 1 3 2 2 1 2 1 4 0 1)
    -15
    nil
    

    【讨论】:

      【解决方案2】:

      Clojure 是一种 LISP,这意味着它是一种homoiconic 语言:数据和代码之间没有结构上的区别。它的列表一直向下。它还有一个可扩展的编译器,允许您通过宏扩展语法。但是从你的问题陈述中并不清楚你真的需要这样的东西。

      您基本上是在运行生成列表的代码(实际上是下一代程序)、保存它们,然后运行新程序。除非您的世代进化需要新语法,否则您可能不需要求助于宏。

      【讨论】:

      • 这正是我所追求的!如果我理解正确,每个“程序”都将是一个列表。我只需要一种方法来“生成”带有函数调用和参数的列表,然后在完成后“执行”该列表。我想我只需要生成以引号为前缀的列表,这样列表就不会被“评估”。
      • 没错。您需要阅读并理解此页面:clojure.org/reader
      【解决方案3】:

      this文章中找到了部分答案:

      prprn 函数就像 他们的 print 和 println 对应物, 但他们的输出形式可以 由 Clojure 阅读器阅读。他们 适合序列化 Clojure 数据结构。默认情况下,他们会 不打印元数据。这可以是 通过绑定特殊符号更改 *print-meta*true

      这至少回答了我问题的第二部分。

      【讨论】:

        【解决方案4】:

        这个问题有些误导,因为 Clojure 还在 Java 字节码中编译 Clojure 源代码时执行动态“代码生成”。

        在这种特殊情况下,我相信你对 Lisp 宏特别感兴趣。我认为这些可能很有趣:

        Clojure documentation itself

        Video, Macros (in Clojure) in 20 minutes

        Standard issue: Wikipedia - Clojure

        请注意,Clojure 中的宏与 Common Lisp 宏(类型 2 lisp)的工作方式非常相似,而不是非常像 Scheme 宏。

        编码愉快。

        【讨论】:

        • 请记住,我是 C# 人。我绝对在这里误用了“代码生成”一词。我想我真正想说的是“列表生成”,但列表需要包含实际的函数调用。
        【解决方案5】:

        看看宏。例如,

        (defmacro defmacro-
          "Same as defmacro but yields a private definition"
          [name & decls]
          (list* `defmacro (with-meta name (assoc (meta name) :private true)) decls))
        

        使用宏,您不需要序列化宏扩展;编译会自动使用它。

        【讨论】:

          猜你喜欢
          • 2013-02-26
          • 1970-01-01
          • 2014-06-14
          • 2012-08-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多