ChucK does not have cloning for reference object, right? That is, the semantic equivalent of an this explicit copy-constructor pseudocode: class A {...} A a0; ... new A(a0) @=> A a1; That is, instead of merely setting a1 to the same reference as that of a0, create a new independent copy, and set its references to that of a0 (shallow copy). It is a problem in the program I wrote, scale.ck: if modifying tuning data, one actually manipulates the data of the original tuning loaded into memory. This is cool, but if I want to be able to reload the original data, I will have to write my own cloning operator. The difference is illustrated in the code below. First I make a shallow copy of a to b, which means that I can change b without changing a. Then I set a reference of a to b, after which changing b also changes a. Hans ---- clone.ck ---- class A { string s; } A a; "a" @=> a.s; A b; "b" @=> b.s; chout <= "a.s = " <= a.s <= ", b.s = " <= b.s <= ".\n"; "c" @=> b.s; chout <= "\"c\" @=> b.s; a = " <= a.s <= ", b = " <= b.s <= ".\n"; a.s @=> b.s; chout <= "a.s @=> b.s; a.s = " <= a.s <= ", b.s = " <= b.s <= ".\n"; "d" @=> b.s; chout <= "\"d\" @=> b.s; a.s = " <= a.s <= ", b.s = " <= b.s <= ".\n"; a @=> b; chout <= "a @=> b; a.s = " <= a.s <= ", b.s = " <= b.s <= ".\n"; "e" @=> b.s; chout <= "\"e\" @=> b.s; a.s = " <= a.s <= ", b.s = " <= b.s <= ".\n"; ---- run ---- $ chuck clone.ck a.s = a, b.s = b. "c" @=> b.s; a = a, b = c. a.s @=> b.s; a.s = a, b.s = a. "d" @=> b.s; a.s = a, b.s = d. a @=> b; a.s = a, b.s = a. "e" @=> b.s; a.s = e, b.s = e. --------
Yeah, the trouble with making your own clone method here is that members are
initialized once, and then written to again in the clone method. The cool
thing about constructors is that it offers a way to make a first
initialization of members depending on input to the constructor.
For a moment I thought you might be able to do something like this:
A cloneA;
class A {
cloneA.x => int x;
cloneA.y => int y;
}
1 => cloneA.x;
A a;
<<< "A.x=", a.x >>>;
... which is kind of insane (what would clone.x be before you assign the 1!)
Just for kicks I tried running it, rendering a "NullPointerException",
unsurprisingly.
/Stefan
On Fri, Dec 11, 2009 at 3:05 PM, Hans Aberg
ChucK does not have cloning for reference object, right? That is, the semantic equivalent of an this explicit copy-constructor pseudocode: class A {...} A a0; ... new A(a0) @=> A a1; That is, instead of merely setting a1 to the same reference as that of a0, create a new independent copy, and set its references to that of a0 (shallow copy).
It is a problem in the program I wrote, scale.ck: if modifying tuning data, one actually manipulates the data of the original tuning loaded into memory. This is cool, but if I want to be able to reload the original data, I will have to write my own cloning operator.
The difference is illustrated in the code below. First I make a shallow copy of a to b, which means that I can change b without changing a. Then I set a reference of a to b, after which changing b also changes a.
Hans
---- clone.ck ---- class A { string s; }
A a; "a" @=> a.s; A b; "b" @=> b.s;
chout <= "a.s = " <= a.s <= ", b.s = " <= b.s <= ".\n";
"c" @=> b.s; chout <= "\"c\" @=> b.s; a = " <= a.s <= ", b = " <= b.s <= ".\n";
a.s @=> b.s; chout <= "a.s @=> b.s; a.s = " <= a.s <= ", b.s = " <= b.s <= ".\n";
"d" @=> b.s; chout <= "\"d\" @=> b.s; a.s = " <= a.s <= ", b.s = " <= b.s <= ".\n";
a @=> b; chout <= "a @=> b; a.s = " <= a.s <= ", b.s = " <= b.s <= ".\n";
"e" @=> b.s; chout <= "\"e\" @=> b.s; a.s = " <= a.s <= ", b.s = " <= b.s <= ".\n";
---- run ---- $ chuck clone.ck a.s = a, b.s = b. "c" @=> b.s; a = a, b = c. a.s @=> b.s; a.s = a, b.s = a. "d" @=> b.s; a.s = a, b.s = d. a @=> b; a.s = a, b.s = a. "e" @=> b.s; a.s = e, b.s = e. --------
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
-- Release me, insect, or I will destroy the Cosmos!
On 11 Dec 2009, at 15:42, Stefan Blixt wrote:
Yeah, the trouble with making your own clone method here is that members are initialized once, and then written to again in the clone method. The cool thing about constructors is that it offers a way to make a first initialization of members depending on input to the constructor.
For a moment I thought you might be able to do something like this:
A cloneA; class A { cloneA.x => int x; cloneA.y => int y; }
1 => cloneA.x; A a; <<< "A.x=", a.x >>>;
... which is kind of insane (what would clone.x be before you assign the 1!) Just for kicks I tried running it, rendering a "NullPointerException", unsurprisingly.
I think just writing fun A clone(A x) { A tmp; ... // Set data of x to tmp. return tmp; } will do it. Hans
Stefan; Yeah, the trouble with making your own clone method here is that members are
initialized once, and then written to again in the clone method. The cool thing about constructors is that it offers a way to make a first initialization of members depending on input to the constructor.
I see more issues here. A object may contain other objects, which in ChucK's case might be Shreds. These Shreds have a state and I don't think it's clear what we would do with that. For one thing you couldn't make a *exact* clone in that case as both the original's Shred and the clone's would need to be shreduled and they can't be shreduled at the same spot (though of course they may be a the same logical time). This seems natural and even interesting, considering the many thought experiments about clones that slowly deviate from the original, but it's something that would have to be kept in mind. Just my cents, Kas.
On 11 Dec 2009, at 20:17, Kassen wrote:
I see more issues here. A object may contain other objects, which in ChucK's case might be Shreds. These Shreds have a state and I don't think it's clear what we would do with that. For one thing you couldn't make a *exact* clone in that case as both the original's Shred and the clone's would need to be shreduled and they can't be shreduled at the same spot (though of course they may be a the same logical time).
This seems natural and even interesting, considering the many thought experiments about clones that slowly deviate from the original, but it's something that would have to be kept in mind.
Some objects cannot be cloned, and others can, like files, but the expected default behavior is handing over e reference. In addition, one may want to have a deep clone - not just cloning the top level object. So one might have one operator, say !=> which some objects that can be cloned properly may have. The => selects a default behavior. So for a file, => would mean @=> and for a float, !=>. Applying != on a streamwhich cannot be copied would produce an error. This would be for a top-level clone, which is what is used the most. For a deep clone, introduce yet another operator !!=>. It produces !=> on the subobjects that have it, but @=> otherwise. So if an object contains a float that can be copied and a stream that cannot, !!=> on the object will copy the float, but hand over a reference of the stream. In addition, a label "const" might useful to prevent copying. If I write Interval m2; m2.setr(256.0/243); // Pythagorean minor second. then it is clear that I do not want the value m2 altered by mistake. Hans
participants (3)
-
Hans Aberg
-
Kassen
-
Stefan Blixt