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.
<pre>
	assign(@a, 1)
	assign(@b, @a) # Note we are assigning @b to @a
	msg(@a) # Msg's 1
	msg(@b) # Also msg's 1
	assign(@a, 5) # Now we are assigning something different to @a
	msg(@a) # Msg's 5
	msg(@b) # Msg's 1 still
</pre>

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.

<pre>
	assign(@a, array(1, 2, 3))
	assign(@b, @a)
	msg(array_implode(@a, ', ')) # Msg's 1, 2, 3
	msg(array_implode(@b, ', ')) # Msg's 1, 2, 3
	assign(@a, array(4, 5, 6))
	msg(array_implode(@a, ', ')) # Msg's 4, 5, 6
	msg(array_implode(@b, ', ')) # Still msg's 1, 2, 3
</pre>

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.

<pre>
	assign(@a, array(1, 2, 3))
	assign(@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
</pre>

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 assign() provides a convenience method
for setting values in arrays, so this code performs the same way:

<pre>
	assign(@a, array(1, 2, 3))
	assign(@b, @a)
	msg(array_implode(@a, ', ')) # Msg's 1, 2, 3
	msg(array_implode(@b, ', ')) # Msg's 1, 2, 3
	assign(@a[0], 4)
	assign(@a[1], 5)
	assign(@a[2], 6)
	msg(array_implode(@a, ', ')) # Msg's 4, 5, 6
	msg(array_implode(@b, ', ')) # Now msg's 4, 5, 6
</pre>

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.

<pre>

proc(_myProc, @a, @b,
	assign(@a, array('a', 'b', 'c'))    # This call might actually get optimized out 
										# entirely since it's not used, but 
										# anyway, it has no effect

	assign(@b[0], 4)
	assign(@b[1], 5)
	assign(@b[2], 6)
)

assign(@myA, array(1, 2, 3))
assign(@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

</pre>

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:

<pre>
assign(@myA, array(1, 2, 3))
assign(@myB, @myA)

msg(array_implode(@myA, ', ')) # msg's 1, 2, 3
msg(array_implode(@myB, ', ')) # msg's 1, 2, 3
# _myProc:
assign(@myA, array('a', 'b', 'c'))
assign(@myB[0], 4)
assign(@myB[1], 5)
assign(@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

</pre>

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:

<pre>
assign(@myA, array(1, 2, 3))
assign(@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
assign(@a, @myA)
assign(@b, @myB)

#_myProc:
assign(@a, array('a', 'b', 'c'))
assign(@b[0], 4)
assign(@b[1], 5)
assign(@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

</pre>

{{LearningTrail}}