5.13. ref[This]Value

[<<<] [>>>]

v = hash::refThisValue(h)
v = hash::refValue(h)

These two functions retrieve a reference to a value stored in a hash and should only be used by advanced programmers, who deeply understand how ScriptBasic stores variables and handles reference values. Use of these functions may help the advanced programmers to increase program speed and effectiveness. On the other hand improper use of the functions may result non-deterministic behavior and memory corruption, process halt, core dump.

The simple definition of the functions is that they do the same as their non-ref pairs with the extension that they return the value of the element, while the non-ref pair returns a copy of the value. Lets see a simple example!

import hash.bas
Const nl="\n"
h = hash::New()
hash::SetValue h,"evil",666
Zazu = hash::Value(h,"evil")
print Zazu,nl
Zazu = "BILL"
print hash::Value(h,"evil"),nl
hash::Release h

This will print the number 666 twice. This is what we have expected. We have a variable that is named Zazu, and we have assigned the string value "BILL" to it, but this has nothing to do with the hash. Now let us alter the code:

import hash.bas
Const nl="\n"
h = hash::New()
hash::SetValue h,"evil",666
Zazu = hash::refValue(h,"evil")
print Zazu,nl
Zazu = "BILL"
print hash::Value(h,"evil"),nl
hash::Release h

The only difference is that we use the function hash::refValue instead of hash::Value. This time the program prints 666 on the first line and BILL on the second. The reason is that the variable Zazu not only holds the value assigned to the key evil, but it is the value.

The situation is exactly the same as function argument passing and is implemented the same way. When a variable is passed to a function by reference the local variable holds a reference to the original variable and whenever the local variable is altered the original variable is altered. The functions hash::refThisValue and hash::refValue return a reference to the unnamed variable stored inside the hash structure holding the value. Whenever the variable is altered the referenced variable is altered inside the hash.

What is the benefit? To have a reference to a value you can alter it without researching the hash. You can just assign a new value to the variable holding the reference value and in a snap you have altered the value of an existing key without searching for the key.

What is the drawback? To have a reference to a value you should be careful otherwise you may get memory corrupting code. Let's see some erroneous examples.

import hash.bas
Const nl="\n"
h = hash::New()
hash::SetValue h,"good",999
hash::SetValue h,"evil",666
Zazu = hash::refValue(h,"evil")
print Zazu,nl
Zazu = "BILL"
print hash::Value(h,"evil"),nl
Zazu = hash::refValue(h,"good")
hash::SetValue h,"evil","William"
print Zazu,nl
hash::Release h

This program will print out 666, BILL and finally William. Why does it print William on the third line? Don't Zazu hold the value for the key "good"? (Yes, it does.) Why does it have to do anything with the altered value of the key "evil"?

The answer is the following. When we have assigned the reference to the value of the key "evil" to the variable Zazu we actually said that all assignments to Zazu will alter the value in the hash. Assigning the reference to the value assigned to the key "good" to Zazu assigned the reference to this key to the value assigned to the key "evil". This means that the keys "evil" and "good" share the same value, which sometimes they pretend to also in real life.

You should never forget a variable that has a reference into the hash! In an artificial example the programmer forgets that the variable Zazu at a certain point in the program was already set to hold a reference to a value in the hash and tries to set it to hold another reference to the same key.

import hash.bas
Const nl="\n"
h = hash::New()
hash::SetValue h,"good",999
hash::SetValue h,"evil",666
Zazu = hash::refValue(h,"evil")
print Zazu,nl
Zazu = "BILL"
' here the programmer makes a mistake and
' forgets that Zazu holds a reference
print hash::Value(h,"evil"),nl
Zazu = hash::refValue(h,"evil")
print Zazu,nl
hash::Release h

The code stops with an error. When assigning the reference to the value of "evil" second time, the value of "evil" is assigned to itself. It becomes a reference that references itself. The program recognizes the situation. It stops with an error after a few iteration trying to resolve the reference. (Builds before 18 of ScriptBasicv1.0 got into an infinite loop.)

The solution is to use the command ByVal as soon as we want to get rid of the reference in the variable. The following program runs fine:

import hash.bas
Const nl="\n"
h = hash::New()
hash::SetValue h,"good",999
hash::SetValue h,"evil",666
Zazu = hash::refValue(h,"evil")
print Zazu,nl
Zazu = "BILL"
ByVal Zazu
print hash::Value(h,"evil"),nl
Zazu = hash::refValue(h,"evil")
print Zazu,nl
hash::Release h

Basic rules that you should keep when using references to hash values:


[<<<] [>>>]