jim
jim

Reputation: 1116

Scheme Global variable won't change

I'm pretty new to Scheme and I'm currently working in DR Racket to learn it. So basically my problem is that I'm having trouble permanently changing global variable.

This is my change function:

(define (change b)
  (set! b (- b 1)) b)

As you can note I return the value of a at the end of the function. And this is the output on the console.

> (define a 4)
> (change a)
3
> a
4

As you can see, in the function it returned the value of 3 (4 - 1). But it seems as though the global variable didn't actually change when i call it after the function. How do I leave it changed? Thanks in advance.

Upvotes: 0

Views: 1494

Answers (2)

Leif Andersen
Leif Andersen

Reputation: 22332

First, Racket is NOT Scheme. They both are similar in this example, but they are very different languages. And calling them the same thing is similar to saying C and C++ are the same language.

Now, on to your actual reference.

The reason change doesn't appear to do anything is because you are passing the 'value' into b, rather than any actual variable.

If you want to pass the actual reference of a primitive like this what you need to do is to box it with the box function. Then you can use set-box! to do the actual mutation, and unbox to get the value in the box

Giving you the following function:

(define (change b)
  (set-box! b (- (unbox b) 1)) b)

Now when you use the change function, the variable should update.

> (define a (box 4))
> (change a)
'#&3
> a
'#&3
> (unbox a)
3

(The '#& is just a compact way that the Racket repl says that the next value is in a box. Which is why we get 3 when you unbox it.)

There are plenty of other data structures to that will have the same effect, vectors, structs, etc. But for a single value box is the simplest.

Upvotes: 5

Óscar López
Óscar López

Reputation: 236004

You're not truly changing the global variable! you're just modifying a parameter, which for all practical purposes is acting as a local variable. If you want to modify the global one, don't pass it as a parameter:

(define a 4)

(define (change)
  (set! a (- a 1))
  a)

a
=> 4
(change)
=> 3
a
=> 3

Upvotes: 3

Related Questions