Jalokoh
Jalokoh

Reputation: 49

How to use set! on "anything" in scheme?

I am using DrRacket.

This works:

(define foo 1)
(set! foo 2)
foo ;;returns 2

But here I want foo to return 2:

(define foo 1)
(define (setmachine variable newvalue)
    (set! variable newvalue))
(setmachine foo 2)
foo ;; returns 1

How can I make the setmachine work?

Upvotes: 0

Views: 117

Answers (1)

Sylwester
Sylwester

Reputation: 48745

Imagine I do this:

(define bla 10)
(define test bla)
(set! test 20)

What does the third line do? Does it change bla? that is how you assuming your setmachine should work.

(set! variable newvalue)

This changes the variable named variable, not the variable named foo. Your set-machine works, but not as you intended!

(define (setmachine variable newvalue)
  (display variable)       ; displays the value to variable
  (set! variable newvalue) ; changes the binding to the value of newvalue
  (display variable))      ; displays the value of variable (same as newvalue)

(define foo 1)
(setmachine foo 2) ; displays 1, then 2

See it did mutate variable, but not foo. In fact if you passed it 1 instead of foo it still works since it passes arguments by value. You didn't instruct it to change foo. Here is how to do that:

(define-syntax syntaxset
  (syntax-rules ()
    ((_ name expression)
     (set! name expression))))

(define foo 1)
(syntaxset foo 2)
foo ; ==> 2

This is no longer a procedure. In fact what happens is that before the program runs racket will have modified the code from (syntaxset foo 2) to (set! foo 2)

Now if you try to do (syntaxset 1 2) to redefine all accurences of 1 in your code to evaluate to 2 it doesn't work since it becomes (set! 1 2) and set! expects the first argument to be a symbolic expression.

Upvotes: 2

Related Questions