You are viewing an older version of the site. Click here to view
the latest version of this page. (This may be a dead link, if so, try the root page of the docs
here.)
In mscript, all values are passed by value of a reference, and assignments are too. However,
primitives do not have a "reference," so are simply passed by value of.
It is important to understand what this means in terms of how this will affect your code. Since
this is a difficult concept to understand even for seasoned programmers, the concept will
be described through examples.
==Reference vs. Value==
In programming in general, when you create a variable, it can be created in two ways,
it can either create a new object/value, or it can simply point to an existing one.
When you have a ''pointer'' to an existing value, it works much like a symlink on
a file system; making changes to a pointer actually makes changes to the value pointed
to. However, assignments (and by extension passing a value to a procedure) change what
value the variable points to. For primitives, that is, a string or a number, this concept
doesn't actually matter, because you can't "change" the underlying primitive value, you
can only reassign a new value to the existing variable, and that assignment doesn't affect
other variables.
This code demonstrates assignment by value of primitives.
Copy Code
As you can see, even though @b is assigned to @a, since it is actually assigned by
value, changing the value of @a does not affect @b. This mechanism works in all cases for arrays
as well.
Copy Code
When we do the second assignment to @a, we aren't changing the ''value'' of what's
being pointed to, we are simply changing what we are pointing to.
Now, let's look at changing the underlying value of an array.
Copy Code
As you can see, we are now changing the underlying value, instead of completely changing what
value as a whole @a references. What might be confusing is that assignments provide a convenience method
for setting values in arrays, so this code performs the same way:
Copy Code
Keep in mind that it's not ''really'' an assign, however, it's simply an array_set() wrapped
up in a more aesthetic syntax.
When you think of sending parameters to a procedure as assign()'s, it becomes easier to see
how the same concept applies to a proc as well.
Copy Code
As you can see here, though @a was re-assigned in the procedure, it did not affect
@myA, as you can essentially think of the procedure call as working by doing several
mini-assignments: assign(@a, @myA) assign(@b, @myB). When we change the assignment
of @a inside the procedure, @myA is not affected, however changing the internals of
the value @b, that does affect @myB (and by extension @myA, since @myA points to @myB).
If we seemingly "''inline''" (we actually aren't inlining it, see below)
the procedure, we get different results though:
Copy Code
This works differently, because we have forgotten that a procedure call introduces
an extra "assignment" before it runs. To truly "inline" a procedure, we must do an
assignment beforehand, so something like this:
Copy Code
== Why the differences? ==
An array could be quite large, so copying it around each time it is assigned could severely impact
performance and memory usage. So by default, it copies the reference instead of the value (which is constant
sized and much smaller typically), however, the easy
clone operator means that you can quickly copy the value, without much hassle, if that's truly
what you need.
Copy Code
The above example copied by reference, as was explained in the earlier section. Changes
to @array1 are reflected in @array2, because they both "point" to the same array. The
variable itself only contains a reference to the array, not the value of the array itself.
Contrast this to a cloned array, which copies the value over:
Copy Code
In this example, the value wasn't changed in array2. However, this comes at a cost.
For large arrays, we now have two mostly identical copies of the array in memory. Sometimes
this is required, and if so, there's nothing that can be done. But since most often this
isn't strictly required, there's no point in eating up more memory than we actually
need. Why aren't primitives handled the same way then? Well, actually, strings are
reference based, thanks to the way the JVM works, but since they aren't modifiable,
assigning by reference or value doesn't make a difference. But for other primitives,
passing by value is done because there is no memory hit for reference vs value, because
in general, the memory used to "point" to an int will be the same as just keeping the
value of the int itself, but the extra layer of abstraction would slow down accesses.
So passing by value makes more sense for primitives.
{{LearningTrail}}
@a = 1;
@b = @a; # Note we are assigning @b to @a
msg(@a); # Msg's 1
msg(@b); # Also msg's 1
@a = 5; # Now we are assigning something different to @a
msg(@a); # Msg's 5
msg(@b); # Msg's 1 still
Copy Code1 @a = 1;
2 @b = @a; # Note we are assigning @b to @a
3
4 {{function|msg}}(@a); # Msg's 1
5
6 {{function|msg}}(@b); # Also msg's 1
7
8 @a = 5; # Now we are assigning something different to @a
9
10 {{function|msg}}(@a); # Msg's 5
11
12 {{function|msg}}(@b); # Msg's 1 still
@a = array(1, 2, 3);
@b = @a;
msg(array_implode(@a, ', ')); # Msg's 1, 2, 3
msg(array_implode(@b, ', ')); # Msg's 1, 2, 3
@a = array(4, 5, 6);
msg(array_implode(@a, ', ')); # Msg's 4, 5, 6
msg(array_implode(@b, ', ')); # Still msg's 1, 2, 3
Copy Code1 @a = {{function|array}}(1, 2, 3);
2 @b = @a;
3 {{function|msg}}({{function|array_implode}}(@a, ', ')); # Msg's 1, 2, 3
4
5 {{function|msg}}({{function|array_implode}}(@b, ', ')); # Msg's 1, 2, 3
6
7 @a = {{function|array}}(4, 5, 6);
8 {{function|msg}}({{function|array_implode}}(@a, ', ')); # Msg's 4, 5, 6
9
10 {{function|msg}}({{function|array_implode}}(@b, ', ')); # Still msg's 1, 2, 3
@a = array(1, 2, 3);
@b = @a;
msg(array_implode(@a, ', ')); # Msg's 1, 2, 3
msg(array_implode(@b, ', ')); # Msg's 1, 2, 3
array_set(@a, 0, 4);
array_set(@a, 1, 5);
array_set(@a, 2, 6);
msg(array_implode(@a, ', ')); # Msg's 4, 5, 6
msg(array_implode(@b, ', ')); # Now msg's 4, 5, 6
Copy Code1 @a = {{function|array}}(1, 2, 3);
2 @b = @a;
3 {{function|msg}}({{function|array_implode}}(@a, ', ')); # Msg's 1, 2, 3
4
5 {{function|msg}}({{function|array_implode}}(@b, ', ')); # Msg's 1, 2, 3
6
7 {{function|array_set}}(@a, 0, 4);
8 {{function|array_set}}(@a, 1, 5);
9 {{function|array_set}}(@a, 2, 6);
10 {{function|msg}}({{function|array_implode}}(@a, ', ')); # Msg's 4, 5, 6
11
12 {{function|msg}}({{function|array_implode}}(@b, ', ')); # Now msg's 4, 5, 6
@a = array(1, 2, 3);
@b = @a;
msg(array_implode(@a, ', ')); # Msg's 1, 2, 3
msg(array_implode(@b, ', ')); # Msg's 1, 2, 3
@a[0] = 4;
@a[1] = 5;
@a[2] = 6;
msg(array_implode(@a, ', ')); # Msg's 4, 5, 6
msg(array_implode(@b, ', ')); # Now msg's 4, 5, 6
Copy Code1 @a = {{function|array}}(1, 2, 3);
2 @b = @a;
3 {{function|msg}}({{function|array_implode}}(@a, ', ')); # Msg's 1, 2, 3
4
5 {{function|msg}}({{function|array_implode}}(@b, ', ')); # Msg's 1, 2, 3
6
7 @a[0] = 4;
8 @a[1] = 5;
9 @a[2] = 6;
10 {{function|msg}}({{function|array_implode}}(@a, ', ')); # Msg's 4, 5, 6
11
12 {{function|msg}}({{function|array_implode}}(@b, ', ')); # Now msg's 4, 5, 6
proc(_myProc, @a, @b){
@a = array('a', 'b', 'c'); # This call might actually get optimized out
# entirely since it's not used, but
# anyway, it has no effect
@b[0] = 4;
@b[1] = 5;
@b[2] = 6;
}
@myA = array(1, 2, 3);
@myB = @myA;
msg(array_implode(@myA, ', ')); # msg's 1, 2, 3
msg(array_implode(@myB, ', ')); # msg's 1, 2, 3
_myProc(@myA, @myB);
msg(array_implode(@myA, ', ')); # msg's 4, 5, 6
msg(array_implode(@myB, ', ')); # msg's 4, 5, 6
Copy Code01
02 {{keyword|proc}}(_myProc, @a, @b){
03 @a = {{function|array}}('a', 'b', 'c'); # This call might actually get optimized out
04
05 # entirely since it's not used, but
06
07 # anyway, it has no effect
08
09
10 @b[0] = 4;
11 @b[1] = 5;
12 @b[2] = 6;
13 }
14
15 @myA = {{function|array}}(1, 2, 3);
16 @myB = @myA;
17
18 {{function|msg}}({{function|array_implode}}(@myA, ', ')); # msg's 1, 2, 3
19
20 {{function|msg}}({{function|array_implode}}(@myB, ', ')); # msg's 1, 2, 3
21
22 {{function|_myProc}}(@myA, @myB);
23 {{function|msg}}({{function|array_implode}}(@myA, ', ')); # msg's 4, 5, 6
24
25 {{function|msg}}({{function|array_implode}}(@myB, ', ')); # msg's 4, 5, 6
@myA = array(1, 2, 3);
@myB = @myA;
msg(array_implode(@myA, ', ')); # msg's 1, 2, 3
msg(array_implode(@myB, ', ')); # msg's 1, 2, 3
# _myProc:
@myA = array('a', 'b', 'c');
@myB[0] = 4;
@myB[1] = 5;
@myB[2] = 6;
msg(array_implode(@myA, ', ')); # msg's a, b, c <- Note the difference here
msg(array_implode(@myB, ', ')); # msg's 4, 5, 6
Copy Code01 @myA = {{function|array}}(1, 2, 3);
02 @myB = @myA;
03
04 {{function|msg}}({{function|array_implode}}(@myA, ', ')); # msg's 1, 2, 3
05
06 {{function|msg}}({{function|array_implode}}(@myB, ', ')); # msg's 1, 2, 3
07
08 # _myProc:
09
10 @myA = {{function|array}}('a', 'b', 'c');
11 @myB[0] = 4;
12 @myB[1] = 5;
13 @myB[2] = 6;
14
15 {{function|msg}}({{function|array_implode}}(@myA, ', ')); # msg's a, b, c <- Note the difference here
16
17 {{function|msg}}({{function|array_implode}}(@myB, ', ')); # msg's 4, 5, 6
@myA = array(1, 2, 3);
@myB = @myA;
msg(array_implode(@myA, ', ')); # msg's 1, 2, 3
msg(array_implode(@myB, ', ')); # msg's 1, 2, 3
# This bit duplicates the implied assignments done by the procedure
@a = @myA;
@b = @myB;
#_myProc:
@a = array('a', 'b', 'c');
@b[0] = 4;
@b[1] = 5;
@b[2] = 6;
msg(array_implode(@myA, ', ')); # msg's 4, 5, 6 <- Now it's back to what it was with an actual procedure
msg(array_implode(@myB, ', ')); # msg's 4, 5, 6
Copy Code01 @myA = {{function|array}}(1, 2, 3);
02 @myB = @myA;
03
04 {{function|msg}}({{function|array_implode}}(@myA, ', ')); # msg's 1, 2, 3
05
06 {{function|msg}}({{function|array_implode}}(@myB, ', ')); # msg's 1, 2, 3
07
08
09 # This bit duplicates the implied assignments done by the procedure
10
11 @a = @myA;
12 @b = @myB;
13
14 #_myProc:
15
16 @a = {{function|array}}('a', 'b', 'c');
17 @b[0] = 4;
18 @b[1] = 5;
19 @b[2] = 6;
20
21
22 {{function|msg}}({{function|array_implode}}(@myA, ', ')); # msg's 4, 5, 6 <- Now it's back to what it was with an actual procedure
23
24 {{function|msg}}({{function|array_implode}}(@myB, ', ')); # msg's 4, 5, 6
# Copy by reference
@array1 = array(1, 2, 3);
@array2 = @array1;
@array1[0] = 'a';
msg(@array1); # msg's a, 2, 3
msg(@array2); # msg's a, 2, 3
Copy Code1 # Copy by reference
2
3 @array1 = {{function|array}}(1, 2, 3);
4 @array2 = @array1;
5 @array1[0] = 'a';
6 {{function|msg}}(@array1); # msg's a, 2, 3
7
8 {{function|msg}}(@array2); # msg's a, 2, 3
#Copy by value
@array1 = array(1, 2, 3);
@array2 = @array1[]; #Note the clone operation here
@array1[0] = 'a';
msg(@array1); # msg's a, 2, 3
msg(@array2); # msg's 1, 2, 3
Copy Code1 #Copy by value
2
3 @array1 = {{function|array}}(1, 2, 3);
4 @array2 = @array1[]; #Note the clone operation here
5
6 @array1[0] = 'a';
7 {{function|msg}}(@array1); # msg's a, 2, 3
8
9 {{function|msg}}(@array2); # msg's 1, 2, 3
Find a bug in this page? Edit this page yourself, then submit a pull request.