A reference is a managed pointer to an existing variable. It acts as an alias. A reference is a variable in itself but does not carry its own value. It can read from as well as write to the original variable.
You can create a reference using the
&
symbol.
var name = "Kal".
var lang = &name. ;; ref to name
ref.kal
Here,
name
is the original variable which holds an actual value.
lang
on the other hand is a reference that refers/points to name.
lang
itself does not have its own value.
Also note that, lang directly points to “Kal”, it does not copy the value. Since a reference is not a copy, it occupies very little space in the memory.
You can have multiple references to an existing variable. Modifying the reference also modifies the original value.
var count = 0.
stdout "Count = " count "\n".
var countRef = &count.
countRef = 10.
stdout "Count = " count "\n".
ref.kal
You can have references to elements of lists and dictionaries as well.
var data = [1, 2, 3].
var item = &data[1].
item = item * 10.
stdout data "\n".
ref.kal
You must be very careful when creating references as any unintended change to the reference will change the base variable.
When you pass a variable to a function, it treats it as a value and makes a copy. This is where references can be useful.
You may not want to pass data as value for two main reasons:
- Modify the data via the function.
- Avoid making extra copies.
Passing by reference addresses both of these reasons.
Let's look at an example:
fn change -> x {
x = x * 10.
stdout "In Fn: " x "\n".
}
var data = 5.
stdout "Before: " data "\n".
:change data.
stdout "After: " data "\n". passByRefBuggy.kal
That's weird, right?
data
should have changed but it didn't. Well, here's what happened:
When
data
was passed to the function
change
, the function made a copy of it and assigned it to
x
, therefore
x
changed, but
data
never did.
The change was visible only inside the function.
To make this example code work, simply pass
data
to change by reference as
&data
.
fn change -> x {
x = x * 10.
stdout "In Fn: " x "\n".
}
var data = 5.
stdout "Before: " data "\n".
:change &data. ;; passed by reference
stdout "After: " data "\n". passByRef.kal
References can be passed during the function invocation. They do not need to be declared in any way during function definition.
Similarly, you can also loop over an array by reference:
var data = [1, 2, 3].
stdout "Before: " data "\n".
loop &each in data {
each = each * 10.
}
stdout "After: " data "\n".
loopByRef.kal