Dear chucklist, I have a question regarding parent and children classes. I'm building a patch with operators that may have one or anoother user defined envelope (i.e. gaussian like, percussive like, etc.). I want to avoid to have to define each operator with 4 different envelopes and then connect-disconnect-reconnect. What I would like is to define a parent class EnvelopeClass from which the rest can inherit. I remember from the past that in chuck inheritance is not very "handy", so if children have different functions or members than its base class, these cannot be accessed. Does anybody have good recommendations to this problem? So the idea is: EnvelopeClass -> this is the base class GaussEnvelope -> children class that inherits from EnvelopeClass PercussiveEnvelope-> children class that inherits from EnvelopeClass now I'd like to have class Operator { SinOsc s; EnvelopeClass @ env; } and be able to assign different envelope types and be able to access their members. Maybe the example at the bottoom of the email is more explanatory. Operator op; GaussianEnvelope gaussEnv @=> op.env; Operator op2; PercussiveEnvelope percEnv @=> op2.env; and even later be able to change the type of the envelope for any operator: GaussianEnvelope gaussEnv2 @=> op2.env; From what I remember, the trick would be that parent and children classes have EXACTLY the same member vars and functions although the implementation contained in it may differ. However, a gauss envelope or a percussive envelope have very different demands, and the best would be to be able to have diffferent implementations for each but inherit from the same base class. any thoughts are very much appreciated, thanks eduard Another example could be: class operator { UGen @ ugen; } Operator op; SinOsc s @=> op.ugen; // this is fine so far but none of the functions of sinosc can be accessed 220 => op.ugen.freq; // this throws an error, as far as I remember....
On Jan 20, 2009, at 12:20 PM, eduard aylon wrote:
I have a question regarding parent and children classes.
I have an example of how I use a not terribly dissimilar structure for handling midi messages here: http://developer.kde.org/~wheeler/files/src/ChucK/include/MidiHandler.ck -Scott
Hello Scott, thanks for your reply. Actually now I realise that my question was incorrect... too tired due to a project deadline. My question, actually, should have been about polymorphism and not inheritance. What I want is that having a base class Point and another class Point2D which inherits from Point, that I can define a Point p, that could morph and become a Point2D. Or in other words, that an UGen, can become a SinOsc. Is that possible? thanks in advance for any thoughts, eduard On Jan 20, 2009, at 12:34 PM, Scott Wheeler wrote:
On Jan 20, 2009, at 12:20 PM, eduard aylon wrote:
I have a question regarding parent and children classes.
I have an example of how I use a not terribly dissimilar structure for handling midi messages here:
http://developer.kde.org/~wheeler/files/src/ChucK/include/MidiHandler.ck
-Scott _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
On Jan 20, 2009, at 11:52 PM, eduard aylon wrote:
Hello Scott, thanks for your reply. Actually now I realise that my question was incorrect... too tired due to a project deadline. My question, actually, should have been about polymorphism and not inheritance. What I want is that having a base class Point and another class Point2D which inherits from Point, that I can define a Point p, that could morph and become a Point2D. Or in other words, that an UGen, can become a SinOsc.
Is that possible?
Still not sure I completely understand -- you can assign a higher class to a reference defined as a subclass, and then you can upcast that. e.g. class Foo { fun void f() { <<< 1 >>>; } } class Bar extends Foo { fun void f() { <<< 2 >>>; } } new Bar @=> Foo @ foo; foo $ Bar @=> Bar @ bar; foo.f(); bar.f(); Produces: 2 :(int) 2 :(int) There's no real "morphing" in there though. Once a class is instantiated it stays the same type, it's just that it can have a handle that refers to it that's a base-class or one of its own type. -Scott
Scott, this is exactly what I want to do. I was getting confuse myself in a very stupid way, but got the answer now. Thanks a lot eduard On Jan 21, 2009, at 12:10 AM, Scott Wheeler wrote:
On Jan 20, 2009, at 11:52 PM, eduard aylon wrote:
Hello Scott, thanks for your reply. Actually now I realise that my question was incorrect... too tired due to a project deadline. My question, actually, should have been about polymorphism and not inheritance. What I want is that having a base class Point and another class Point2D which inherits from Point, that I can define a Point p, that could morph and become a Point2D. Or in other words, that an UGen, can become a SinOsc.
Is that possible?
Still not sure I completely understand -- you can assign a higher class to a reference defined as a subclass, and then you can upcast that. e.g.
class Foo { fun void f() { <<< 1 >>>; } }
class Bar extends Foo { fun void f() { <<< 2 >>>; } }
new Bar @=> Foo @ foo; foo $ Bar @=> Bar @ bar;
foo.f(); bar.f();
Produces:
2 :(int) 2 :(int)
There's no real "morphing" in there though. Once a class is instantiated it stays the same type, it's just that it can have a handle that refers to it that's a base-class or one of its own type.
-Scott _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Eduard; Scott,
this is exactly what I want to do. I was getting confuse myself in a very stupid way, but got the answer now. Thanks a lot
Whoops, and I was completely off-base. Very nice trick that Scott has there, now that I understand it. I had no idea that you could cast that way, is that documented at all? Yours, Kas.
On Jan 21, 2009, at 2:06 AM, Kassen wrote:
Very nice trick that Scott has there, now that I understand it. I had no idea that you could cast that way, is that documented at all?
Not sure. It's another one of those things that I think if fairly obvious if you're coming from a C++ / Java-like type system, so it just seemed natural to me to try. -Scott
Scott;
Not sure. It's another one of those things that I think if fairly obvious if you're coming from a C++ / Java-like type system, so it just seemed natural to me to try.
Ah, I see. I think it was the Joker in the Tim Burton Batman film who shouted "Where does he get those toys?" so that's where. I felt a bit like that :¬). This needs to be documented. It's great that we have such features, it's great that people with C/C++/Java experience can feel at home like that. What's not so great is if stuff like this has no documentation because that way nobody will know about it which would be a shame. I looked it up and right now cast is only mentioned in the manual as a way to turn int's into float's. We've seen some more examples of how it can be used but I had no idea it was *that* general. This changes the whole "fight with the type system game". It is of course spectacularly un-scientific to use yourself as a test-case and maybe my "Sherpa" title is making me vain these days but I more or less feel that if *I* don't know about it then it must be under-documented ;¬). We can't blame anyone for this, it's entirely logical that the developers -who are clearly very experienced with this type of syntax- will feel some things are so natural that they overlook mentioning them. I'll add this to the "missing documentation" page on the wiki tonight. I did some quick testing just now to make sure I understand it all and there is a small issue with this in that we can now address member functions that aren' t there which leads to crashes. //This is fine (if pushing what's sensible to do in one line); new SinOsc @=> UGen foo => dac; 400 => (foo $ SinOsc).freq; second => now; //this is not fine UGen u; 200 => (u $ SinOsc).freq; Of course this is rather predictable but it also means losing the whole VM and IMHO anything that makes us lose the whole VM is a issue. So, a new trick learned and a new way of crashing unearthed, it's a good day for ChucKing! Thanks, Kas.
ps; you'll be fighting the type system. Typically fighting the type system leads to bug-reports. If it's 4am and you're throwing the keyboard against the wall do considder that you may be right and ChucK might be wrong.
Man, that sounds familiar... ;-)
I end up fighting the type system all the time, actually. I ran into
a very similar situation in which I was trying to make a Collection
class. Why can't I do this kind of thing?
class Collection {
Object objects[0];
0 => int count;
fun void add( Object obj ) {
objects << obj;
count++;
}
// this you can't do, apparently...
fun Object pop() {
//objects.popBack() @=> Object s;
//return s;
}
}
Collection myCollection;
SinOsc s;
Gain g;
Event e;
myCollection.add( s );
myCollection.add( g );
myCollection.add( e );
<<< myCollection.count >>>;
// so far so good...
// this doesn't work...
//myCollection.pop() $ Event @=> Event f;
//-------
I really wish that there was at least an isInstanceOf() method (like
in Java, sadly), we could use to programatically determine the class
of an object at runtime. It's my personal, humble opinion that, if
you're going to have a strict typing system, you should provide a way
to programatically determine the type of anything.
-Mike
On Wed, Jan 21, 2009 at 9:58 AM, Kassen
Scott;
Not sure. It's another one of those things that I think if fairly obvious if you're coming from a C++ / Java-like type system, so it just seemed natural to me to try.
Ah, I see.
I think it was the Joker in the Tim Burton Batman film who shouted "Where does he get those toys?" so that's where. I felt a bit like that :¬).
This needs to be documented. It's great that we have such features, it's great that people with C/C++/Java experience can feel at home like that. What's not so great is if stuff like this has no documentation because that way nobody will know about it which would be a shame. I looked it up and right now cast is only mentioned in the manual as a way to turn int's into float's. We've seen some more examples of how it can be used but I had no idea it was *that* general. This changes the whole "fight with the type system game".
It is of course spectacularly un-scientific to use yourself as a test-case and maybe my "Sherpa" title is making me vain these days but I more or less feel that if *I* don't know about it then it must be under-documented ;¬). We can't blame anyone for this, it's entirely logical that the developers -who are clearly very experienced with this type of syntax- will feel some things are so natural that they overlook mentioning them. I'll add this to the "missing documentation" page on the wiki tonight.
I did some quick testing just now to make sure I understand it all and there is a small issue with this in that we can now address member functions that aren' t there which leads to crashes.
//This is fine (if pushing what's sensible to do in one line); new SinOsc @=> UGen foo => dac; 400 => (foo $ SinOsc).freq; second => now;
//this is not fine UGen u; 200 => (u $ SinOsc).freq;
Of course this is rather predictable but it also means losing the whole VM and IMHO anything that makes us lose the whole VM is a issue.
So, a new trick learned and a new way of crashing unearthed, it's a good day for ChucKing!
Thanks, Kas.
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
mike clemow wrote:
// this doesn't work... //myCollection.pop() $ Event @=> Event f;
Are you sure that doesn't work? I swear I have been doing the same with my collection classes.
From ArrayListTest.ck:
class Foo
{
fun int foo()
{
return 1;
}
}
// unit test for ArrayList
class ArrayListTest extends Assert
{
{
true => exitOnFailure;
testConstructor();
testSize();
testGetAddSet();
testIterator();
testForEach();
testAssign();
testTransform();
testAddAll();
testFoo();
<<<"ArrayListTest ok">>>;
}
//...
fun void testFoo()
{
ArrayList list;
Foo fooIn;
list.add(fooIn);
list.get(0) $ Foo @=> Foo fooOut;
assertEquals(fooIn, fooOut);
<<
Michael,
Hrm... Yes, you're right; we've gone over this before. How do you
represent objects in your ArrayList class? Are you using arrays? If
yes, how do you avoid the issues that are brought to the surface by my
code? I'd be surprised if you haven't run into the issues with Arrays
of Objects that Kassen is talking about.
-Mike
On Wed, Jan 21, 2009 at 3:46 PM, Michael Heuer
mike clemow wrote:
// this doesn't work... //myCollection.pop() $ Event @=> Event f;
Are you sure that doesn't work? I swear I have been doing the same with my collection classes.
From ArrayListTest.ck:
class Foo { fun int foo() { return 1; } }
// unit test for ArrayList
class ArrayListTest extends Assert { { true => exitOnFailure; testConstructor(); testSize(); testGetAddSet(); testIterator(); testForEach(); testAssign(); testTransform(); testAddAll(); testFoo();
<<<"ArrayListTest ok">>>; }
//...
fun void testFoo() { ArrayList list; Foo fooIn; list.add(fooIn); list.get(0) $ Foo @=> Foo fooOut; assertEquals(fooIn, fooOut); <<
>>; } } ... [chuck](VM): sporking incoming shred: 1 (ArrayListTest.ck)... 1 :(int) "ArrayListTest ok" : (string)
michael _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
2009/1/21 Michael Heuer
Are you sure that doesn't work? I swear I have been doing the same with my collection classes.
I just tested it again to make absolutely sure. objects.popBack() returns "... :(void)" and objects[count-1] returns something of type "object" so it seems like this is a popback issue more than something that is fundamentally impossible. Below is a corrected version that does work and IMHO .popBack() can go on the bug list. Yours, Kas. class Collection { Object objects[0]; 0 => int count; fun void add( Object obj ) { objects << obj; count++; } // this you can't do, apparently... fun Object pop() { objects[count-1] @=> Object s; count--; objects.size( objects.size()-1); return s; } } Collection myCollection; SinOsc s; Gain g; Event e; myCollection.add( s ); myCollection.add( g ); myCollection.add( e ); <<< myCollection.count >>>; myCollection.pop() $ Event @=> Event f; //make sure we can use it without crashing f.signal(); <<< myCollection.count >>>;
Kassen,
Yeah, that implementation is a good work around. I agree about
popBack() going on the bug list.
Here's a concise demo:
Object objects[0];
SinOsc s;
objects << s;
SinOsc s1;
// should return type Object. Instead returns type void.
objects.popBack() $ SinOsc @=> s1;
Where should I post this?
-Mike
On Wed, Jan 21, 2009 at 4:19 PM, Kassen
2009/1/21 Michael Heuer
Are you sure that doesn't work? I swear I have been doing the same with my collection classes.
I just tested it again to make absolutely sure.
objects.popBack() returns "... :(void)" and
objects[count-1] returns something of type "object" so it seems like this is a popback issue more than something that is fundamentally impossible.
Below is a corrected version that does work and IMHO .popBack() can go on the bug list.
Yours, Kas.
class Collection { Object objects[0]; 0 => int count;
fun void add( Object obj ) { objects << obj; count++; }
// this you can't do, apparently... fun Object pop() { objects[count-1] @=> Object s; count--; objects.size( objects.size()-1); return s; } }
Collection myCollection;
SinOsc s; Gain g; Event e;
myCollection.add( s ); myCollection.add( g ); myCollection.add( e );
<<< myCollection.count >>>;
myCollection.pop() $ Event @=> Event f;
//make sure we can use it without crashing f.signal(); <<< myCollection.count >>>;
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Mike,
Yeah, that implementation is a good work around. I agree about popBack() going on the bug list.
We agree; very good.
Where should I post this?
I'd say on the WiKi on the "bugs hopefully fixed in the next release" page. I post everything there, I always have high hopes for the next release ;¬). We've seen similar things with arrays and Ge knows there are some issues there, I don't think this is a entirely new thing, it seems more like a new expression of the stuff we saw before.
Done.
Thanks, folks!
-mc
On Wed, Jan 21, 2009 at 4:48 PM, Kassen
Mike,
Yeah, that implementation is a good work around. I agree about popBack() going on the bug list.
We agree; very good.
Where should I post this?
I'd say on the WiKi on the "bugs hopefully fixed in the next release" page. I post everything there, I always have high hopes for the next release ;¬).
We've seen similar things with arrays and Ge knows there are some issues there, I don't think this is a entirely new thing, it seems more like a new expression of the stuff we saw before.
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Wow, it's hard to keep up with you guys!
As you inferred, my ArrayList, its Iterator, the forEach method, etc.
all use indexed array access.
michael
On Wed, Jan 21, 2009 at 4:05 PM, mike clemow
Done.
Thanks, folks!
-mc
On Wed, Jan 21, 2009 at 4:48 PM, Kassen
wrote: Mike,
Yeah, that implementation is a good work around. I agree about popBack() going on the bug list.
We agree; very good.
Where should I post this?
I'd say on the WiKi on the "bugs hopefully fixed in the next release" page. I post everything there, I always have high hopes for the next release ;¬).
We've seen similar things with arrays and Ge knows there are some issues there, I don't think this is a entirely new thing, it seems more like a new expression of the stuff we saw before.
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
-- http://michaelclemow.com http://semiotech.org _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Mike; Man, that sounds familiar... ;-)
I thought it might.... // this you can't do, apparently...
fun Object pop() { //objects.popBack() @=> Object s; //return s; }
Actually it seems like objects.popBack() will return something of type void. Sounds like another case of arrays mucking with the type system to me. I don't think the type system would be that bad if it weren't for stuff like that. Arrays seem to somehow lose some of the type of some objects at times.
I really wish that there was at least an isInstanceOf() method (like in Java, sadly), we could use to programatically determine the class of an object at runtime. It's my personal, humble opinion that, if you're going to have a strict typing system, you should provide a way to programatically determine the type of anything.
This sounds like a very good idea to me. At the very least it should make debugging situations like the one you have here much easier. Right now I tend to simply print objects to determine their type; SinOsc foo; Event bar; <<<foo>>>; <<<bar>>>; Clearly the info is there already. Yours, Kas.
Yeah, that must be it. Michael must not use popBack() method in his
classes. This...
fun Object at( int i ) {
return objs[i];
}
...properly returns an Object.
So, does that qualify as a bug in popBack() 's implementation?
-Mike
On Wed, Jan 21, 2009 at 3:49 PM, Kassen
Mike;
Man, that sounds familiar... ;-)
I thought it might....
// this you can't do, apparently... fun Object pop() { //objects.popBack() @=> Object s; //return s; }
Actually it seems like objects.popBack() will return something of type void. Sounds like another case of arrays mucking with the type system to me.
I don't think the type system would be that bad if it weren't for stuff like that. Arrays seem to somehow lose some of the type of some objects at times.
I really wish that there was at least an isInstanceOf() method (like in Java, sadly), we could use to programatically determine the class of an object at runtime. It's my personal, humble opinion that, if you're going to have a strict typing system, you should provide a way to programatically determine the type of anything.
This sounds like a very good idea to me. At the very least it should make debugging situations like the one you have here much easier. Right now I tend to simply print objects to determine their type;
SinOsc foo; Event bar; <<<foo>>>; <<<bar>>>;
Clearly the info is there already.
Yours, Kas.
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Eduard;
My question, actually, should have been about polymorphism and not inheritance. What I want is that having a base class Point and another class Point2D which inherits from Point, that I can define a Point p, that could morph and become a Point2D. Or in other words, that an UGen, can become a SinOsc.
Is that possible?
Well, the thing is; You can assign a SinOsc to a object of type UGen because a SinOsc is a UGen. However, a UGen object doesn't have a .freq() member function so you can't use that with it, even though a SinOsc (which does have that function) has been asigned to it. Let's take a practical example; ----------------8<----------- UGen u; if (maybe) new SinOsc @=> u; else new Gain @=> u; //so far so good //here comes trouble; 440 => u.freq; --------------8<---------------- That last line is the trouble-maker; it adresses a UGen and at that point we're not sure that UGen has that function, hence the parser objects. That line may well be valid but we don't know this for sure. What I think you may need is a new class that can generate modulation signals, then extend that for various behaviours. This won't work like a UGen but you could connect it using a "dummy" Gain UGen in the parrent class that might serve as a output. How you'd do that in practice would depend on the exact scenario, for a extremely general case this could become somehwat lengthy and involved. For a extremely basic frame-work see below. Yours, Kas. --------------8<------------------- //this will parse. It may or may not be the kind of thing you are after. //clearly a lot more infrastucture is needed class Modulator { Gain out; } class Foo extends Modulator { ADSR env => out; } class Bar extends Modulator { Envelope env => out; } Modulator m; m.out => SinOsc s => dac; new Foo @=> m; -----8<---------------------- ps; you'll be fighting the type system. Typically fighting the type system leads to bug-reports. If it's 4am and you're throwing the keyboard against the wall do considder that you may be right and ChucK might be wrong.
participants (5)
-
eduard aylon
-
Kassen
-
Michael Heuer
-
mike clemow
-
Scott Wheeler