你能得到“代码作为数据”在Clojure中加载函数? [英] Can you get the "code as data" of a loaded function in Clojure?

查看:177
本文介绍了你能得到“代码作为数据”在Clojure中加载函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

另一种方式,好的,代码是数据...

该线程解决了如何从源文件读取,但我想知道如何获取已加载的函数的s表达式到数据结构我可以阅读和操纵。

That thread addresses how to read from a source file, but I'm wondering how to get the s-expression of an already-loaded function into a data structure that I can read and manipulate.

换句话说,如果我说,

(defn example [a b] (+ a b))

在运行时?这不是代码作为数据的整体点吗?

can't I get that list at runtime? Isn't this the whole point of "code as data"?

这真的是一个通用的Lisp问题,但我正在寻找一个答案在Clojure。 p>

This is really a general Lisp question, but I'm looking for an answer in Clojure.

推荐答案

您可以使用 clojure.repl / source 宏来获取源的符号:

You can use the clojure.repl/source macro to get the source of a symbol:

user> (source max)
(defn max
  "Returns the greatest of the nums."
  {:added "1.0"
   :inline-arities >1?
   :inline (nary-inline 'max)}
  ([x] x)
  ([x y] (. clojure.lang.Numbers (max x y)))
  ([x y & more]
   (reduce1 max (max x y) more)))
nil

但这只是答案的一部分。 AFAICT source 查找定义给定符号的源文件名和行号,然后从文件打印源代码。因此, source 将不适用于您没有源代码的符号,即AOT编译的clojure代码。

But this is only part of the answer. AFAICT source looks up the source filename and line number that define the given symbol, and then prints the source code from the file. Therefore, source will not work on symbols that you do not have the source for, i.e. AOT-compiled clojure code.

回到你原来的问题,你可以认为 source 读取与给定符号相关联的元数据,只是打印它。也就是说它的作弊。它不以任何方式返回代码作为数据给你,代码我的意思是编译clojure函数。

Coming back to your original question, you can think of source as reading the meta data associated with the given symbol and simply printing that. I.e. it's cheating. It's not in any way returning "code as data" to you, where with code I mean a compiled clojure function.

在我看来,代码作为数据是指lisps的特性,其中源代码实际上是一个lisp数据结构,因此它可以被lisp读取器读取。也就是说,我可以创建一个有效的lisp代码和 eval 的数据结构。

In my mind "code as data" refers to the feature of lisps where source code is effectively a lisp data structure, and therefore it can be read by the lisp reader. That is, I can create a data structure that is valid lisp code, and eval that.

user=> (eval '(+ 1 1))
2

'(+ 1 1)是一个文字列表,它被clojure读取器读取,然后被计算为clojure代码。

Here '(+ 1 1) is a literal list which gets read by the clojure reader and then evaluated as clojure code.

: Yehonathan Sharvit在其中一个注释中询问是否可以修改函数的代码。以下代码段读取函数的源代码,修改生成的数据结构,最后计算数据结构,产生一个新函数 my-nth ,定义如下: / p>

Update: Yehonathan Sharvit was asking in one of the comments if it's possible to modify the code for a function. The following snippet reads in the source for a function, modifies the resulting data structure, and finally evaluates the data structure resulting in a new function, my-nth, being defined:

(eval
 (let [src (read-string (str (source-fn 'clojure.core/nth) "\n"))]
   `(~(first src) my-nth ~@(nnext src))))

syntax-quote 行用替换 nth 表单中的 defn 表格

这篇关于你能得到“代码作为数据”在Clojure中加载函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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