2013-03-24 10 views
5

Jak napisać funkcję, aby rozwiązać symbol w środowisku leksykalnym?clojure - rozwiązać symbol w środku niech

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

Chcę uzyskać var, do którego jest przypisane foo.

+3

Niech nie tworzy nowych Vars, więc w zasadzie nie można rozwiązać im – Ankur

+0

Ale to jest możliwe, aby uzyskać otoczenie wewnątrz makro z & Kop. – navgeet

+0

@navgeet, nie, to nie jest możliwe. '(defmacro m [x & env] '(x env))' rozwinie się w ten sposób: '(m 1 2 3 4 5) ->' (1 (2 3 4 5))', tzn. 'i env' da ci dostęp do varargs. W Clojure nie ma sposobu na uzyskanie aktualnego środowiska leksykalnego. –

Odpowiedz

4

nie jestem całkowicie pewien, dlaczego chcę coś takiego, ale wygląda to na pewno może być zrobione. z 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

Oto zarówno bardziej, mniej i pochylać się niż chciałeś:

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

Wygląda na to, że @navgeet szuka rozwiązania Clojure, którego nie ma. – dfreeman

+0

i nie jest to nawet rozwiązanie ... – GoZoner

+0

Cóż, pytanie jest oznaczone jako "seplenienie". –

Powiązane problemy