Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clojure - resolve a symbol inside let

Tags:

clojure

lisp

How do I write a function to resolve a symbol in a lexical environment?

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

I want to get the var that 'foo is bound to.

like image 571
navgeet Avatar asked Mar 24 '13 15:03

navgeet


2 Answers

I am not completely sure why I want something like this, but looks like it can certainly be done. from 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}
like image 77
navgeet Avatar answered Nov 01 '22 16:11

navgeet


Here is both more, less and skew to than you wanted:

(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
         ...)))
like image 1
GoZoner Avatar answered Nov 01 '22 16:11

GoZoner