【问题标题】:Programming language/platform with runtime access to the AST具有对 AST 的运行时访问的编程语言/平台
【发布时间】:2015-10-01 00:39:36
【问题描述】:

我希望为一个简短的演示实现一些概念验证演示,其中正在运行的代码知道当前正在执行的代码块的散列“值”。例如:

function BBB(a) {
  a = 2 * a;
  print me.hash;          --> "xxxxxxx" (value of BBB-syntax represenation)
  return a;                              
}

function AAA(a, b, c) {
  d = BBB(a);
  print me.hash;          --> "yyyyyyy" (value of AAA-Syntax representation, possibly dependant on value of BBB, but not necessary)
  return d;
}

我本能地转向 LISPish 语言,但在 Scheme 上还没有成功。而且我很长时间没有与 Common LISP 保持联系,我怀疑这可能能够做到(提示赞赏)。它不一定要快,或者流行的平台,可以是可用的最学术和最奇怪的平台。这只是一个演示。

有没有人知道一种语言/平台可以开箱即用或几乎不需要修改就可以做到这一点?我更喜欢使用某种解析/树状的东西,而不是实际的源代码。

【问题讨论】:

  • 在普通的 Common Lisp 中,一个正在运行的函数并不知道自己。在特定的实现中,应该可以检查堆栈。

标签: functional-programming programming-languages common-lisp metaprogramming


【解决方案1】:

你猜对了。 Common Lisp 可以很容易地做到这一点:

(defmacro reflective-defun (name args &body body)
  (let ((source-form `(reflective-defun ,name ,args ,@body)))
    `(let ((me ',source-form))
       (defun ,@(cdr source-form)))))

(reflective-defun bbb (a)
  (setf a (* 2 a))
  (print me)
  a)

(reflective-defun aaa (a b c)
  (let ((d (bbb a)))
    (print me)
    d))

(aaa 12 :x :y)

输出:

(REFLECTIVE-DEFUN BBB
    (A)
  (SETF A (* 2 A))
  (PRINT ME)
  A) 
(REFLECTIVE-DEFUN AAA
    (A B C)
  (LET ((D (BBB A)))
    (PRINT ME)
    D)) 
24

以下是编写自重定义函数的方法:

(defun recursive-replace (tree what with)
  "Walks down the TREE and replaces anything that is EQUALP to WHAT with WITH."
  (cond ((equalp tree what)
         with)
        ((listp tree)
         (loop for item in tree
              collect (recursive-replace item what with)))
        (t tree)))

(reflective-defun ccc (a b c)
  (let ((d (bbb a)))
    (print me)
    (if (eql b :use-me-from-now-on)
        (eval (recursive-replace me '(bbb a) '(bbb b))))
    d))

顺便说一句,Scheme(以及任何宏卫生的语言)会竭尽全力阻止您创建一个名为 me 的标识符,该标识符可以被传递给宏的源代码引用。

【讨论】:

  • 除了缺乏文档外,卫生似乎是我与 Julia 之间的隔阂。非常感谢!这正是我所需要的。
【解决方案2】:

不是哈希,但对于唯一 ID,您可以使用 Python 对象身份。将每个函数放在自己的类中,然后使用id()。一个例子,在 Python 3 中:

class cBBB(object):
    def do(a):
        a=2*a
        print(self.id())    # self.id() is the "hash"-like unique value
        return a;
BBB = cBBB()     # now you can call BBB.do(a)

class cAAA(object):
    def do(a,b,c):
        d = BBB.do(a)
        print(self.id())    # self.id() is the "hash"-like unique value
        return d;
AAA = cAAA()     # now you can call AAA.do(a,b,c)

这可以使用__call__ 更简洁地完成。有关__call__ 的更多信息,请参见this question

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-06
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    相关资源
    最近更新 更多