clojure - 解决let里面的符号

时间:2013-03-24 15:50:57

标签: clojure lisp

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

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

我想得到'foo绑定的var。

2 个答案:

答案 0 :(得分:4)

我不完全确定为什么我想要这样的东西,但看起来肯定可以做到。 来自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}

答案 1 :(得分:1)

这里有比你想要的更多,更少和更多的偏见:

(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
         ...)))