//Understanding assignment by value
//this is a very basic topic, but there are often
//misunderstandings because of behaviour.

//__________In sc everything is passed by value.
a = 0;
b = a;
[a, b, a === b].postln;
a = 1;
[a, b, a === b].postln;

in order to achieve a different behaviour, reference can be used.
a reference is a very simple object (Ref) that has one instance variable,
value. a shortcut is often used which is the `-character,
as seen in Sequencer.kr(`[1, 2, 3], Impulse.kr(2))


//___________use Ref just like Plug or ControlValue (SC3)
a = Ref(0); //a now contains a reference to the number zero
b = a; // a and b now refer to the same object
[a, b, a === b].postln;
a.set(8.0); //change the value of a's reference
[a, b, a === b].postln; // also b has changed.


//__________similarly, an array can be used:
a = [0];   //a now refers to an array containing the number zero
b = a; // a and b now refer to the same object, the array.
[a, b, a === b].postln;
a.put(0, 8.0); //change the value in the array that a contains
[a, b, a === b].postln; // a and b still refer to the same object

//_________note: when the array size is exeeded, a new array gets created.
a.add(2.0);
[a, b, a === b].postln; // nothing has happened
a = a.add(2.0);
[a, b, a === b].postln; // b still is refering to the old array that was used to create the new
      //content of a. a List can be used to avoid this.

//_________this is actually the case for any instance variable.
a = Date.getDate; //create a new instance of Date and store it in a
b = a;  // a and b now refer to the same object, a date.
[a.year, b.year].postln;
a.year = 1792; //set the instance variable of Date (that is contained in a), equivalent to "a.year_(1792);"
[a.year, b.year].postln; //a and b still refer to the same object.

//__________note: also here there is cases where this is not true.
a = Rect.newBy(0, 0, 20, 20);
b = a;
[a.top, b.top].postln;
a = a.moveTo(50, 50);
[a.top, b.top].postln;

//to understand this, one has to have a look at the method moveTo in Rect:
 moveTo { arg h, v;
  ^Rect.new(h, v, right - left + h, bottom - top + v)//and see that a new rectangle is created.
 }

//if it was like the following, it wouldn't show this behaviour
 moveTo { arg h, v;
  right = right - left + h;
  bottom = bottom - top + v;
 }
 
//it does work with the method setExtent:
a = Rect.newBy(0, 0, 20, 20);
b = a;
[a.width, b.width].postln;
a.setExtent(50, 50);
[a.width, b.width].postln;

//because setExtent doesn't create a new rectangle
 setExtent { arg width=0, height=0;
  right = left + width;
  bottom = top + height;
 }