There is no equivalent to set-car!, because conses are not mutable. Only 
vars, refs, atoms, and agents are mutable, and they are simply containers 
for immutable values.  You could put a cons inside an atom and put a new 
transformed list into the atom. (Note even among schemes set-car! is highly 
discouraged, and I don't think Racket even has it in core 
anymore: 
http://blog.racket-lang.org/2007/11/getting-rid-of-set-car-and-set-cdr.html)

The idiomatic Clojure way of handling this is to always have an immutable 
environment and contain it in a single environment atom.  When you change 
the environment, you return a new copy of it with your change and put it in 
to the global env atom. The SICP mutates the environment instead. There's 
probably a reason for this (late/dynamic binding?) which would have a 
completely different approach in Clojure.

Some more notes:

(empty? nil) ;=> true

def and defn create namespace-global vars as a side effect--the vars are 
not lexically scoped! This is NOT like scheme's "define." I suspect all of 
your inner uses of def and defn should be let and letfn instead. def and 
defn are used at the top level or (rarely) are used a level or two down to 
close over some private data (e.g. a def inside a let). However, defs are 
practically never inside other defs.

On Thursday, August 6, 2015 at 12:36:20 PM UTC-5, 杨旸 wrote:
>
> Hi everyone,
> I am current trying to implement a scheme interpreter in clojure following 
> the instruction on SICP chap4.
>
> Where I encounter a problem with adding/modifying a def var/fn in 
> enviroment.
>
> according to chap4  4.1.3 the set-variable-value! function looks like the 
> following in scheme:
> (define (set-variable-value! var val env)
>   (define (env-loop env)
>     (define (scan vars vals)
>       (cond ((null? vars)
>              (env-loop (enclosing-environment env)))
>             ((eq? var (car vars))
>              (set-car! vals val))
>             (else (scan (cdr vars) (cdr vals)))))
>     (if (eq? env the-empty-environment)
>         (error "Unbound variable -- SET!" var)
>         (let ((frame (first-frame env)))
>           (scan (frame-variables frame)
>                 (frame-values frame)))))
>   (env-loop env))
>
>
>
>
> But I found there's no set-car! in clojure, which make me have to 
> re-create the env while loop though the defied variables like:
> *https://github.com/zacyang/sicp-in-clj/blob/master/src/sicp/ch4/core.clj 
> <https://github.com/zacyang/sicp-in-clj/blob/master/src/sicp/ch4/core.clj> 
> line #348*
>
>
> (defn set-variable-value!
>   [var-looking-for val-to-be-set env]
>
>
>   (defn find-and-change [vars vals]
>     (cond
>      (empty? vars)   '()
>      (= (first vars) var-looking-for)  (conj (find-and-change (rest vars) 
> (rest vals))  val-to-be-set) 
>      :else (conj (find-and-change (rest vars) (rest vals)) (first vals))))
>
>
>   (defn env-loop
>     [e]
>     
>     (if (= @env @the-empty-environment) 
>       :ERROR-TRY-SET-UNBOUND-VARIABLE
>       (let  [frame (first-frame e)
>              frame-vars (frame-variables frame)
>              frame-vals (frame-values frame)]
>         
>         (if (not= @(enclosing-enviroment e) @the-empty-environment)
>           (extend-enviroment frame-vars frame-vals (env-loop 
> (enclosing-enviroment e)))
>           (extend-enviroment 
>            frame-vars
>            (find-and-change frame-vars frame-vals)
>            the-empty-environment)))))
>
>
>   (env-loop env)
> )
>
> My question is, is there any good substitution for set-car! in scenarios 
> where I need just *change* the car and cdr of something created by cons??
>
> PS: tried swap! atom , but it will also need to change the whole 
> environment structure. 
>
>
>
>   
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to