【问题标题】:clojure - resolve a symbol inside letclojure - 解析 let 中的符号
【发布时间】:2013-03-24 15:50:56
【问题描述】:

如何编写函数来解析词法环境中的符号?

(let [foo some-var]
  (let [sym 'foo]
    (resolve-sym sym)))

我想获取 'foo 绑定到的 var。

【问题讨论】:

  • 我们不会创建新的变量,所以基本上你无法解决它们
  • 但是可以使用 &env 获取宏内部的环境。
  • @navgeet,不,这是不可能的。 (defmacro m [x & env] '(x env)) 将以这种方式扩展:(m 1 2 3 4 5) -> '(1 (2 3 4 5)),即& env 将允许您访问可变参数。 Clojure 中无法获取当前的词法环境。
  • @VladimirMatveev,navgeet 不是在谈论可变参数。 blog.jayfields.com/2011/02/clojure-and.html
  • @navgeet:您能发布您要解决的问题吗?可能有更好的方法来做到这一点

标签: clojure lisp


【解决方案1】:

我不完全确定我为什么想要这样的东西,但看起来肯定可以做到。 来自http://clojuredocs.org/circumspec/circumspec.should/local-bindings

(defmacro local-bindings
  "Produces a map of the names of local bindings to their values.
   For now, strip out gensymed locals. TODO: use 1.2 feature."
  []
  (let [symbols (remove #(.contains (str %) "_")
                        (map key @clojure.lang.Compiler/LOCAL_ENV))]
    (zipmap (map (fn [sym] `(quote ~sym)) symbols) symbols)))


(let [foo 1 bar 2]
  (local-bindings))
=> {foo 1, bar 2}

【讨论】:

    【解决方案2】:

    这里比你想要的更多、更少和偏斜:

    (define (make-let-core name value body)
      `(CORE LET ,name ,value ,body))
    
    (define (env-extend env a-name its-denotation)
      (lambda (name)
        (if (equal? name a-name)
            its-denotation
            (if env (env name) 'unknown))))
    
    (define (env-base)
      (lambda (name)
        (if (member name '(let resolve-sym #| ... |#))
            'syntactic-keyword
            'unknown)))
    
    (define (expand exp env)
      (cond ((literal? exp) ...)
            ((symbol?  exp) ...)
            ((list? exp)
             (let ((operator (car exp))
                   (operands (cdr exp)))
               (cond ((symbol? operator)
                      (case (env operator)
                        ((syntactic-keyword)
                         (case operator
                           ((let)
                            (let ((bound-name  (caar  operands))
                                  (bound-value (cadar operands))
                                  (body (cdr operands)))
                              (make-let-core bound-name
                                             (expand bound-value env)
                                             (expand body
                                                     (env-extend bound-name
                                                                 'variable)))))
                           ((resolve-sym)
                            (let ((name (car operands)))
                              ;; right here
                              ...))
                           (...)))
                        ((variable) ;; function call
                         ...)
    
                        ((unknown)  ;; syntax error
                         ...)))
    
                     ((list? operator) ;; function call
                      ...)
    
                     (else ;; syntax error
                      ...))))
            (else ;; syntax error
             ...)))
    

    【讨论】:

    • 看起来@navgeet 正在寻找 Clojure 解决方案,但事实并非如此。
    • 嗯,这个问题被标记为“lisp”。
    猜你喜欢
    • 2012-02-10
    • 2019-09-05
    • 1970-01-01
    • 1970-01-01
    • 2015-06-17
    • 1970-01-01
    • 1970-01-01
    • 2018-03-14
    • 2015-10-18
    相关资源
    最近更新 更多