I want to find some way of controlling various parameters via the keyboard. The problem I'm having is that in order to write some sort of generic class that can change arbitrary UGen parameters (or really anything), one needs to know what types your dealing with. Is there a way of asking chuck what things are? For instance, I can maintain some sort of list of UGens I want to control via an array of UGens, but then when I attempt to access a parameter on one of the objects in that array, it tells me there is no such member in class UGen. THe idea is that the array would contain references to various UGens I want to manipulate, and they may be of any UGen subtype. However, in order to access any members, the compiler needs to know exactly which type each object is. Any ideas? -- Rich
Whan I run the following code, I get an error at line 7 - class UGen has no
member 'mix'.
How do I do this type of thing in chuck?
// code
SinOsc s => Chorus chorus => JCRev reverb => dac;
880.0 => s.freq;
.2 => s.gain;
UGen @ ug[];
chorus @=> ug[0];
reverb @=> ug[1];
0.0 => ug[0].mix;
while (true) {
1::second => now;
} // main loop
----- Original Message -----
From: "Rich Caloggero"
I want to find some way of controlling various parameters via the keyboard. The problem I'm having is that in order to write some sort of generic class that can change arbitrary UGen parameters (or really anything), one needs to know what types your dealing with. Is there a way of asking chuck what things are? For instance, I can maintain some sort of list of UGens I want to control via an array of UGens, but then when I attempt to access a parameter on one of the objects in that array, it tells me there is no such member in class UGen. THe idea is that the array would contain references to various UGens I want to manipulate, and they may be of any UGen subtype. However, in order to access any members, the compiler needs to know exactly which type each object is.
Any ideas?
-- Rich
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Hey Rich,
You can work around the problem by casting ug[0] as a Chorus object like this:
0.0 => (ug[0] $ Chorus).mix;
Casts are ugly, but they'll almost get the example working. The other
thing you need to do is change the line
UGen @ ug[];
to
UGen @ ug[0];
I'm a little rusty on the syntax, but I think what you're doing in
your code is declaring a reference to an array of references to UGens,
when what you want is an array of references to an array of UGens. If
you make the change then you get the array of references. You can then
begin to fill the array using the "array << item" syntax, which adds
elements to the end of the array. So to add the UGens to the array
you'll end up with lines like this:
ug << chorus;
ug << reverb;
// BEGIN CODE
SinOsc s => Chorus chorus => JCRev reverb => dac;
880.0 => s.freq;
.2 => s.gain;
UGen @ ug[0];
ug << chorus;
ug << reverb;
0.0 => (ug[0] $ Chorus).mix;
while (true) {
1::second => now;
} // main loop
// END CODE
And once you've done all this you still have your original problem,
which is that you want to be able to create an array of objects that
all respond to "mix" (or some other method) and treat them the same
way. Unfortunately there isn't a built-in way to do this. Chuck is
strongly-typed, so you can't call a method unless the object is known
to support the method. Chuck doesn't have an introspection system so
you can't ask an object what methods it supports. And Chuck doesn't
have multiple inheritance (nor does it have interfaces) so there isn't
a "MixableUGen" interface that you could use to indicated that all the
UGens in the array support the "mix" method.
You can create your own classes that have references to the UGens and
wrap up the functionality you need, so that you can call the "mix"
method an an object and it will know what to do with its associated
UGen.
andy
On Sun, Nov 7, 2010 at 6:45 PM, Rich Caloggero
Whan I run the following code, I get an error at line 7 - class UGen has no member 'mix'. How do I do this type of thing in chuck?
// code SinOsc s => Chorus chorus => JCRev reverb => dac; 880.0 => s.freq; .2 => s.gain; UGen @ ug[]; chorus @=> ug[0]; reverb @=> ug[1]; 0.0 => ug[0].mix;
while (true) { 1::second => now; } // main loop
----- Original Message ----- From: "Rich Caloggero"
To: "ChucK Users Mailing List" Sent: Sunday, November 07, 2010 1:11 PM Subject: [chuck-users] Intraspection? I want to find some way of controlling various parameters via the keyboard. The problem I'm having is that in order to write some sort of generic class that can change arbitrary UGen parameters (or really anything), one needs to know what types your dealing with. Is there a way of asking chuck what things are? For instance, I can maintain some sort of list of UGens I want to control via an array of UGens, but then when I attempt to access a parameter on one of the objects in that array, it tells me there is no such member in class UGen. THe idea is that the array would contain references to various UGens I want to manipulate, and they may be of any UGen subtype. However, in order to access any members, the compiler needs to know exactly which type each object is.
Any ideas?
-- Rich
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Thanx Andy. I was worried that this would be the case; getting too used to
Javascript where anything is possible.
Will the casting work for any UGen type? I.e. since most (all) UGens support
mix, then can I just pretend that everything in the array is one type (say
Chorus for instance) and then use that type's mix?
Thanx.
-- Rich
----- Original Message -----
From: "Andrew Turley"
Hey Rich,
You can work around the problem by casting ug[0] as a Chorus object like this: 0.0 => (ug[0] $ Chorus).mix; Casts are ugly, but they'll almost get the example working. The other thing you need to do is change the line UGen @ ug[]; to UGen @ ug[0]; I'm a little rusty on the syntax, but I think what you're doing in your code is declaring a reference to an array of references to UGens, when what you want is an array of references to an array of UGens. If you make the change then you get the array of references. You can then begin to fill the array using the "array << item" syntax, which adds elements to the end of the array. So to add the UGens to the array you'll end up with lines like this: ug << chorus; ug << reverb;
// BEGIN CODE SinOsc s => Chorus chorus => JCRev reverb => dac; 880.0 => s.freq; .2 => s.gain; UGen @ ug[0]; ug << chorus; ug << reverb; 0.0 => (ug[0] $ Chorus).mix;
while (true) { 1::second => now; } // main loop // END CODE
And once you've done all this you still have your original problem, which is that you want to be able to create an array of objects that all respond to "mix" (or some other method) and treat them the same way. Unfortunately there isn't a built-in way to do this. Chuck is strongly-typed, so you can't call a method unless the object is known to support the method. Chuck doesn't have an introspection system so you can't ask an object what methods it supports. And Chuck doesn't have multiple inheritance (nor does it have interfaces) so there isn't a "MixableUGen" interface that you could use to indicated that all the UGens in the array support the "mix" method.
You can create your own classes that have references to the UGens and wrap up the functionality you need, so that you can call the "mix" method an an object and it will know what to do with its associated UGen.
andy
On Sun, Nov 7, 2010 at 6:45 PM, Rich Caloggero
wrote: Whan I run the following code, I get an error at line 7 - class UGen has no member 'mix'. How do I do this type of thing in chuck?
// code SinOsc s => Chorus chorus => JCRev reverb => dac; 880.0 => s.freq; .2 => s.gain; UGen @ ug[]; chorus @=> ug[0]; reverb @=> ug[1]; 0.0 => ug[0].mix;
while (true) { 1::second => now; } // main loop
----- Original Message ----- From: "Rich Caloggero"
To: "ChucK Users Mailing List" Sent: Sunday, November 07, 2010 1:11 PM Subject: [chuck-users] Intraspection? I want to find some way of controlling various parameters via the keyboard. The problem I'm having is that in order to write some sort of generic class that can change arbitrary UGen parameters (or really anything), one needs to know what types your dealing with. Is there a way of asking chuck what things are? For instance, I can maintain some sort of list of UGens I want to control via an array of UGens, but then when I attempt to access a parameter on one of the objects in that array, it tells me there is no such member in class UGen. THe idea is that the array would contain references to various UGens I want to manipulate, and they may be of any UGen subtype. However, in order to access any members, the compiler needs to know exactly which type each object is.
Any ideas?
-- Rich
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
On 8 November 2010 19:35, Rich Caloggero
Thanx Andy. I was worried that this would be the case; getting too used to Javascript where anything is possible. Will the casting work for any UGen type? I.e. since most (all) UGens support mix, then can I just pretend that everything in the array is one type (say Chorus for instance) and then use that type's mix?
Yes. If all of the UGens that you use there support .mix() you can cast to any one type of UGen that has .mix() and use it. The one downside to this is that you are removing the safety that the parser gives in type-checking so if somehow some UGen that lacks .mix() ends up in your array you'll crash the VM. With STKInstrument and it's sub-classes this works quite well, with members like .noteOn() being shared so there it's quite safe if done properly. Sadly we lack a "Effect" class that all effects like Churus could extend and that would provide extra safety and convenience in your case. Hope that helps, Kas.
On Mon, Nov 8, 2010 at 11:07 AM, Kassen
On 8 November 2010 19:35, Rich Caloggero
wrote: Thanx Andy. I was worried that this would be the case; getting too used to Javascript where anything is possible. Will the casting work for any UGen type? I.e. since most (all) UGens support mix, then can I just pretend that everything in the array is one type (say Chorus for instance) and then use that type's mix?
Yes. If all of the UGens that you use there support .mix() you can cast to any one type of UGen that has .mix() and use it. The one downside to this is that you are removing the safety that the parser gives in type-checking so if somehow some UGen that lacks .mix() ends up in your array you'll crash the VM. With STKInstrument and it's sub-classes this works quite well, with members like .noteOn() being shared so there it's quite safe if done properly. Sadly we lack a "Effect" class that all effects like Churus could extend and that would provide extra safety and convenience in your case. Hope that helps, Kas.
Kas, I'm not sure that's true. I just tried this: // BEGIN CODE SinOsc s => Chorus chorus => JCRev reverb => dac; 880.0 => s.freq; .2 => s.gain; UGen @ ug[0]; ug << chorus; ug << reverb; 0.0 => (ug[1] $ Chorus).mix; while (true) { 1::second => now; } // main loop // END CODE and I got the following: chuck_instr.cpp:4530: failed assertion `m_offset < obj->vtable->funcs.size()' Abort trap The "mix" method won't have a common location in the vtable. You might get lucky casting a JCRev to a PitShift since "mix" is the first method for both of them, but I certainly wouldn't count on that to always work. andy
Andy;
I'm not sure that's true. I just tried this:
You are right. I doubted for a moment because of the array and how arrays tend to muck with the type system but this fails too; JCRev foo; .1 => ((foo $ UGen) $ Chorus).mix;
The "mix" method won't have a common location in the vtable. You might get lucky casting a JCRev to a PitShift since "mix" is the first method for both of them, but I certainly wouldn't count on that to always work.
Indeed! Turns out we just got lucky a lot of times. It does work for the STKInstruments and the convenience filters. I seem to remember you can also have it work for anything that has a .freq() but maybe there too we just got lucky so far. That's a bit disappointing; it was a nice trick while it lasted. I suppose it still is for those places where you can get away with it. I think I talked about this before, but I'd like any object to have a .type() that would return a array like this; ["Object", "UGen", "Filter, "LPF"]. The VM has all of that data, we just can't get to it. Yours, Kas.
Kassen:
Andy;
I'm not sure that's true. I just tried this:
You are right. I doubted for a moment because of the array and how arrays tend to muck with the type system but this fails too; JCRev foo; .1 => ((foo $ UGen) $ Chorus).mix;
The "mix" method won't have a common location in the vtable. You might get lucky casting a JCRev to a PitShift since "mix" is the first method for both of them, but I certainly wouldn't count on that to always work.
Indeed! Turns out we just got lucky a lot of times. It does work for the STKInstruments and the convenience filters. I seem to remember you can also have it work for anything that has a .freq() but maybe there too we just got lucky so far. That's a bit disappointing; it was a nice trick while it lasted. I suppose it still is for those places where you can get away with it. I think I talked about this before, but I'd like any object to have a .type() that would return a array like this; ["Object", "UGen", "Filter, "LPF"]. The VM has all of that data, we just can't get to it.
There is some relevant code for the cast operator, chuck_type.cpp, line 2488 and related. It looks rather incomplete to me, and maybe this is the most telling line 2530: // TODO: dynamic type checking If anyone can hack together an instanceof operator from this, the effort would be greatly appreciated. :) michael
Oh heck, let's just cut to the chase and hack a Chuck
meta-object protocol...
(oops, sorry. that just slipped out. ;)
Honestly, I've run into this a lot in the past and I'm familiar with this
frustration. I even hacked my own version of chuck in which each object
responded to a .typeOf(); message that returned a string representation (I
know, it's ugly) of it's class name. I used this to make do smart casting,
which I admit is still a huge compromise. I still think that each class
name (reserved word) should be able to represent itself. Something to the
tune of:
if( myUgen.typeOf() == SinOsc ) { // seems reasonable, right?
myUgen $ SinOsc => SinOsc s;
}
But even then, short of wrapping all UGens in another class in order to gain
more control from these sorts of operations, we still have to do the cast
ourselves, which would make some sense if it was ever reasonable to cast a
SinOsc as anything other than a UGen, but that would be... frankly,
bizarre.
For this reason, I think that the Chuck language should take care of this
situation for us (at least where UGens are concerned--we can build). If we
are forced to cast because Chuck is strictly typed, so be it. But then we
should be able to ask any object what it really is an instance of. There
are good reasons why Chuck is strictly typed, however, IMHO, this is an
unnecessary restriction. Even Java can do this--and I rarely stick my neck
out for Java.
Anyway, I've been on this soapbox before, so I'll stop my drivel.
Mike
On Mon, Nov 8, 2010 at 2:50 PM, Michael Heuer
Kassen:
Andy;
I'm not sure that's true. I just tried this:
You are right. I doubted for a moment because of the array and how arrays tend to muck with the type system but this fails too; JCRev foo; .1 => ((foo $ UGen) $ Chorus).mix;
The "mix" method won't have a common location in the vtable. You might get lucky casting a JCRev to a PitShift since "mix" is the first method for both of them, but I certainly wouldn't count on that to always work.
Indeed! Turns out we just got lucky a lot of times. It does work for the STKInstruments and the convenience filters. I seem to remember you can also have it work for anything that has a .freq() but maybe there too we just got lucky so far. That's a bit disappointing; it was a nice trick while it lasted. I suppose it still is for those places where you can get away with it. I think I talked about this before, but I'd like any object to have a .type() that would return a array like this; ["Object", "UGen", "Filter, "LPF"]. The VM has all of that data, we just can't get to it.
There is some relevant code for the cast operator, chuck_type.cpp, line 2488 and related. It looks rather incomplete to me, and maybe this is the most telling
line 2530: // TODO: dynamic type checking
If anyone can hack together an instanceof operator from this, the effort would be greatly appreciated. :)
michael _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
mike clemow wrote:
Honestly, I've run into this a lot in the past and I'm familiar with this frustration. I even hacked my own version of chuck in which each object responded to a .typeOf(); message that returned a string representation (I know, it's ugly) of it's class name. I used this to make do smart casting, which I admit is still a huge compromise. I still think that each class name (reserved word) should be able to represent itself. Something to the tune of: if( myUgen.typeOf() == SinOsc ) { // seems reasonable, right? myUgen $ SinOsc => SinOsc s; }
I don't find that ugly, it's a cool hack. What if the method were called className()? I vote for adding such to the git repo and push to get it added upstream. michael
That bit of code would be great, if it worked. What I made did this:
if( myUgen.typeOf() == "SinOsc" ) { // a string is ugly...
myUgen $ SinOsc => SinOsc s;
}
However, if the reserved word-- SinOsc --could be made equivalent to what
was returned from .typeOf() or .className(), then it would be totally great.
My hack was trivial, but this one wouldn't be.
Mike
On Tue, Nov 9, 2010 at 12:13 PM, Michael Heuer
mike clemow wrote:
Honestly, I've run into this a lot in the past and I'm familiar with this frustration. I even hacked my own version of chuck in which each object responded to a .typeOf(); message that returned a string representation (I know, it's ugly) of it's class name. I used this to make do smart casting, which I admit is still a huge compromise. I still think that each class name (reserved word) should be able to represent itself. Something to the tune of: if( myUgen.typeOf() == SinOsc ) { // seems reasonable, right? myUgen $ SinOsc => SinOsc s; }
I don't find that ugly, it's a cool hack. What if the method were called className()?
I vote for adding such to the git repo and push to get it added upstream.
michael _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Mike;
However, if the reserved word-- SinOsc --could be made equivalent to what was returned from .typeOf() or .className(), then it would be totally great.
Are you proposing a new type representing "keyword"? I don't think that would fly in the long term, unless we could add to the keywords. I still want this to -one day- fly: class Distortion extends UGen { fun float tick() { .....etc...} } Furthermore there are more object types than UGens; so far we only discussed UGens but we need a general solution that will be able to deal with a array containing -say- objects of type "note" and type "melody" or "loop" and whatever. Without needing to implement what would amount to a custom type system. Yours, Kas.
Kas,
(This conversation is faster that I can keep up with!)
No, not a type: Keyword, more likely a type: Class. Or, it may be easier to
deal with strings, or arrays of string. I thought that strings, being
mutable, might be dangerous. I think that we could get more specific errors
if we had this all built into the language.
Mike
2010/11/9 Kassen
Mike;
However, if the reserved word-- SinOsc --could be made equivalent to what was returned from .typeOf() or .className(), then it would be totally great.
Are you proposing a new type representing "keyword"? I don't think that would fly in the long term, unless we could add to the keywords. I still want this to -one day- fly:
class Distortion extends UGen { fun float tick() { .....etc...} }
Furthermore there are more object types than UGens; so far we only discussed UGens but we need a general solution that will be able to deal with a array containing -say- objects of type "note" and type "melody" or "loop" and whatever. Without needing to implement what would amount to a custom type system.
Yours, Kas.
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Right, that's why I proposed className().
A real instanceof keyword would return true for all of
(myUgen instanceof SinOsc.class)
(myUgen instanceof UGen.class)
(myUgen instanceof Object.class)
which would help with Kas' use case. How about
fun String className()
fun String[] classNames()
?
mike clemow
That bit of code would be great, if it worked. What I made did this: if( myUgen.typeOf() == "SinOsc" ) { // a string is ugly... myUgen $ SinOsc => SinOsc s; }
However, if the reserved word-- SinOsc --could be made equivalent to what was returned from .typeOf() or .className(), then it would be totally great. My hack was trivial, but this one wouldn't be. Mike On Tue, Nov 9, 2010 at 12:13 PM, Michael Heuer
wrote: mike clemow wrote:
Honestly, I've run into this a lot in the past and I'm familiar with this frustration. I even hacked my own version of chuck in which each object responded to a .typeOf(); message that returned a string representation (I know, it's ugly) of it's class name. I used this to make do smart casting, which I admit is still a huge compromise. I still think that each class name (reserved word) should be able to represent itself. Something to the tune of: if( myUgen.typeOf() == SinOsc ) { // seems reasonable, right? myUgen $ SinOsc => SinOsc s; }
I don't find that ugly, it's a cool hack. What if the method were called className()?
I vote for adding such to the git repo and push to get it added upstream.
michael _______________________________________________ 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
Yes, I like this. Or a new type: Class.
As long as the method of comparison is safe (as safe as the typing system,
anyway), it makes tons of sense to do it.
If we used className() and it returned an array of strings, would we get the
entire hierarchy? I mean:
a[0]: Object
a[1]: UGen
a[2]: SinOsc
?
Mike
On Tue, Nov 9, 2010 at 12:46 PM, Michael Heuer
Right, that's why I proposed className().
A real instanceof keyword would return true for all of
(myUgen instanceof SinOsc.class) (myUgen instanceof UGen.class) (myUgen instanceof Object.class)
which would help with Kas' use case. How about
fun String className() fun String[] classNames()
?
mike clemow
: That bit of code would be great, if it worked. What I made did this: if( myUgen.typeOf() == "SinOsc" ) { // a string is ugly... myUgen $ SinOsc => SinOsc s; }
However, if the reserved word-- SinOsc --could be made equivalent to what was returned from .typeOf() or .className(), then it would be totally great. My hack was trivial, but this one wouldn't be. Mike On Tue, Nov 9, 2010 at 12:13 PM, Michael Heuer
wrote: mike clemow wrote:
Honestly, I've run into this a lot in the past and I'm familiar with this frustration. I even hacked my own version of chuck in which each
object
responded to a .typeOf(); message that returned a string representation (I know, it's ugly) of it's class name. I used this to make do smart casting, which I admit is still a huge compromise. I still think that each class name (reserved word) should be able to represent itself. Something to the tune of: if( myUgen.typeOf() == SinOsc ) { // seems reasonable, right? myUgen $ SinOsc => SinOsc s; }
I don't find that ugly, it's a cool hack. What if the method were called className()?
I vote for adding such to the git repo and push to get it added upstream.
michael _______________________________________________ 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
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
2010/11/9 mike clemow
Yes, I like this. Or a new type: Class.
As long as the method of comparison is safe (as safe as the typing system, anyway), it makes tons of sense to do it.
I think it'd be safe; the "==" operator is only overloaded to deal with identical types, I think. That is excepting the automatic and implied casting of ints to floats, I believe.
If we used className() and it returned an array of strings, would we get the entire hierarchy? I mean:
a[0]: Object a[1]: UGen a[2]: SinOsc
Yes! I think that makes at least some sense; it doesn't require any new concepts, it's simple and it seems powerful. I also want that for UGen connections. Iterating and -where needed- recursing as a way of dealing with trees is very, very powerful. It might be more of a Lisp-style strategy than a Java/C++ one but as far as I can see it can't do any real harm here and it's not especially inconsistent with anything we have so far. Of course I'm just making stuff up here, stuff I've had on my mind for quite a while (especially the bit about the UGen Graph) but there may well be huge holes it. By all means open fire on the plan and we'll see what bits keep standing. Let's just blurt out ideas and let Ge do the sorting :¬) Kas.
On 9 November 2010 18:46, Michael Heuer
Right, that's why I proposed className().
Check.
A real instanceof keyword would return true for all of
(myUgen instanceof SinOsc.class) (myUgen instanceof UGen.class) (myUgen instanceof Object.class)
I'm a bit lost about this notation. Is this in the C++ stuff? I'd be happy with "my_ugen.instanceOf( SinOsc )" returning true or false as well. This would probably make code smaller and it would make debug printing slightly more complicated, though we can simply print the object and get a (useless) memory address and it's type.
which would help with Kas' use case. How about
fun String className() fun String[] classNames()
where ".classname()" would be equivalent to ".classNames()[ .classnames().cap() - 1 ]", assuming we go from the most general to the most specific right? I'm not sure about that order yet. It will depend on whether we'd mostly be happy with some general info and would go into the details more rarely or whether we would tend to try something specific, then go up the tree until we encounter something that would hold. I suspect the first case to be more common. That's a bit of a detail though. Yours, Kas.
FYI: we've had this conversation before...
https://lists.cs.princeton.edu/pipermail/chuck-dev/2006-March/000135.html
Graham Coleman actually implemented this at one point using an instanceof
keyword, like in Java.
-Mike
2010/11/9 Kassen
On 9 November 2010 18:46, Michael Heuer
wrote: Right, that's why I proposed className().
Check.
A real instanceof keyword would return true for all of
(myUgen instanceof SinOsc.class) (myUgen instanceof UGen.class) (myUgen instanceof Object.class)
I'm a bit lost about this notation. Is this in the C++ stuff? I'd be happy with "my_ugen.instanceOf( SinOsc )" returning true or false as well. This would probably make code smaller and it would make debug printing slightly more complicated, though we can simply print the object and get a (useless) memory address and it's type.
which would help with Kas' use case. How about
fun String className() fun String[] classNames()
where ".classname()" would be equivalent to ".classNames()[ .classnames().cap() - 1 ]", assuming we go from the most general to the most specific right? I'm not sure about that order yet. It will depend on whether we'd mostly be happy with some general info and would go into the details more rarely or whether we would tend to try something specific, then go up the tree until we encounter something that would hold. I suspect the first case to be more common. That's a bit of a detail though.
Yours, Kas.
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
2010/11/9 mike clemow
FYI: we've had this conversation before...
Indeed. But I also think we have -since then- found such glaring holes in the type-system as it relates to arrays and passing references that I think we resolved new features there made no sense until there were some big fixes. And then there is the GC stuff... That may or may not explain why that patch wasn't pushed in? Yours, Kas.
Oh maybe. I can't speak for the devs. There were definitely issues with
references not being counted that were causing much grief. I was just
pointing out that we're not covering new ground here. There may be a leg-up
in that patch from Graham that cold make implementing this really easy, if
it does go through.
I ditched my work-around because I was having compatibility issues with
others who weren't using my own secret, hacked version! No fun to chuck
alone. :)
Mike
2010/11/9 Kassen
2010/11/9 mike clemow
FYI: we've had this conversation before...
Indeed. But I also think we have -since then- found such glaring holes in the type-system as it relates to arrays and passing references that I think we resolved new features there made no sense until there were some big fixes. And then there is the GC stuff...
That may or may not explain why that patch wasn't pushed in?
Yours, Kas.
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Just to be contrarian here, I would like to point out that
"instanceof" and run-time type checking are generally considered a bad
idea in OO languages. Take a look at these to start:
http://c2.com/cgi/wiki?InstanceofInConditionals
http://www.artima.com/intv/constP.html (see the section "When to Use RTTI")
Maybe you could argue that for quick scripts the benefits outweigh the
problems, but I think I would look harder for an OO solution. Granted,
Chuck has somewhat limited support for OO, so maybe we just don't have
the tools we need for a better solution (multiple-inheritance [also
problematic], dynamic dispatch, type-safe downcasts, interfaces, etc).
I'm not trying to make the great the enemy of the good here, I'm just
saying that there might be better ways of solving this problem, at
least from a software engineering standpoint.
andy
2010/11/9 Kassen
On 9 November 2010 18:46, Michael Heuer
wrote: Right, that's why I proposed className().
Check.
A real instanceof keyword would return true for all of
(myUgen instanceof SinOsc.class) (myUgen instanceof UGen.class) (myUgen instanceof Object.class)
I'm a bit lost about this notation. Is this in the C++ stuff? I'd be happy with "my_ugen.instanceOf( SinOsc )" returning true or false as well. This would probably make code smaller and it would make debug printing slightly more complicated, though we can simply print the object and get a (useless) memory address and it's type.
which would help with Kas' use case. How about
fun String className() fun String[] classNames()
where ".classname()" would be equivalent to ".classNames()[ .classnames().cap() - 1 ]", assuming we go from the most general to the most specific right? I'm not sure about that order yet. It will depend on whether we'd mostly be happy with some general info and would go into the details more rarely or whether we would tend to try something specific, then go up the tree until we encounter something that would hold. I suspect the first case to be more common. That's a bit of a detail though. Yours, Kas. _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
On 9 November 2010 19:27, Andrew Turley
Just to be contrarian here, I would like to point out that "instanceof" and run-time type checking are generally considered a bad idea in OO languages. Take a look at these to start: http://c2.com/cgi/wiki?InstanceofInConditionals http://www.artima.com/intv/constP.html (see the section "When to Use RTTI")
I take it that by OO -here- you mean languages like C++ and Java, and not something like Scheme which is extremely OO (functions and primitives are objects there too, unlike in ChucK). If so, and I'm not terribly misunderstanding something, then yes, it probably is... but then those languages are typically used in a context of writing code, compiling it and having a executable. Compared to them we are relatively focussed on adding to a running program and editing it, something that is typically used in very different sorts of languages.
Maybe you could argue that for quick scripts the benefits outweigh the problems, but I think I would look harder for an OO solution. Granted, Chuck has somewhat limited support for OO, so maybe we just don't have the tools we need for a better solution (multiple-inheritance [also problematic], dynamic dispatch, type-safe downcasts, interfaces, etc).
I'm not trying to make the great the enemy of the good here, I'm just saying that there might be better ways of solving this problem, at least from a software engineering standpoint.
I'd be very enthusiastic about a better solution to the issue; I just made some stuff up that sounded convenient. One of the things that affects this and that affects livecoding is the namespace which much of the time gets in our way. If there are other ways of determining the nature of some object we wouldn't need to do this.... Or we could have some sort of way that would allow us to try doing things to objects where we are unsure of their capabilities and not have the whole thing come crashing down. I'm not too attached to the proposed solution, any other way of dealing with the problem would also be fine. Kas.
I don't find that ugly, it's a cool hack. What if the method were called className()?
I vote for adding such to the git repo and push to get it added upstream.
The reason why I suggested using a array of strings instead of a string (this array may well be of length 1) is that UGens will belong to multiple classes; for one thing they are UGens. The system proposed here won't detect whether or not the given object is a UGen without using a exhaustive list of UGens in the check. If all we want to do is set a .gain() then simply verifying the given object is a UGen would do. In other cases detecting that it is a STKIinstrument or Filter would be more relevant than the exact way in which the given object extends those classes. A array of strings will make the general case possible, at the expense of a slight complication of the specific case. A utility function that takes a string and a array of strings as arguments, returning true if any element in the array equals the string and false in all other cases would probably solve that. This will only become more pressing once extending UGen will become possible. Similarly I'd like to propose that .connectsTo() and .connectsFrom() be added as UGen member functions and return arrays of references to UGens. With those two things we could edit the UGen graph without being bothered by the namespace. In fact calling .connectsTo() on the dac and blackhole, then recursing would make the entire active UGen graph accessible from our code. It'd be even nicer if we could also poll those UGens for the name that they have in their local namespace, if any. You see; we can have anonymous UGens, I just discovered, this parses just fine; new SinOsc => blackhole; Yours, Kas.
participants (5)
-
Andrew Turley
-
Kassen
-
Michael Heuer
-
mike clemow
-
Rich Caloggero