[chuck-users] OOP and Style Qs

Spencer Salazar ssalazar at CS.Princeton.EDU
Sat Mar 17 01:42:25 EDT 2007


Hi Veli-Pekka,
please see responses below.

On Mar 16, 2007, at 6:55 PM, Veli-Pekka Tätilä wrote:

> 1. Is the code in the class OK in terms of style and implementation  
> i.e. is
> there something highly uncanonical in naming or some things that  
> could be
> done smarter for such a simple thing?

Looks pretty good from here.  A disconnect method is something that I  
can see being useful, though.

> - In particular, I'm not sure if the gain module is needed in the  
> output.

It shouldnt be needed, but may be useful if you wanted to adjust the  
gain of the entire UGen unilaterally.

> - Is there a better way to grow the array on demand? In Perl I can  
> just
> assign to higher indeces and it will grow, or use the push function  
> to add
> an arbitraryly sized list at the end. And Java has array lists, too.

Yes, your approach is currently the only way to grow the numeric part  
of the array.  It is a goal to eventually have the ability to  
dynamically adjust the capacity of an array.

> - ALso in the test script, I would like to initialize my UGen array
> anonymously without having to make up variable names for each  
> object and
> manully assign the indeces, I'm lazy  I guess.

I don't see this as laziness, necessarily--it is a completely  
legitimate thing to want to do.  Fortunately, there is the 'new'  
operator, which, similar to its counterparts in Java and C++,  
anonymously allocates an object of the specified type.  Amending part  
of your code below to use this operator would look something like this:

> UGen @oscs[3];
> // Our oscs.
> new SinOsc @=> oscs[0];
> new SawOsc @=> oscs[1];
> new SqrOsc @=> oscs[2];

or even this:

> [ new SinOsc $ UGen, new SawOsc, new SqrOsc ] @=> UGen @oscs[];

Note that the initial $ UGen (typecast to UGen) is needed to tell the  
compiler that this is a UGen array, not a SinOsc array.

One caveat to this technique is that you won't be able to set any  
parameters to your oscillators beyond those that are present in every  
UGen.  Notably, UGen doesn't have a frequency parameter.

> - Is there a style manual for ChucK? Until we can inherit from UGen  
> it would
> be great to have a common set of method names for UGen like modules.
> Currently I've drawn my influences from Java and Dinky.ck.

There is no style manual, but I think following the lead of the  
examples and Java is probably the best approach at this point.

> - Which reminds me, does chucK support duck typing? Abstractly put,
> Suppose a class or interface c with the method name m and an object  
> o such
> that not o instanceof c. Does o.m() get called in its own class,  
> even if o
> is not related to c by inheritance. Polymorphism that works based  
> on a name
> is there in Perl and Python, I think, where as Java is stricter and  
> requires
> that the object be a subclass or interface implementation of c, a  
> common
> method name is not good enough.

ChucK follows the Java model, requiring explicit inheritance for  
polymorphism to be (ab)used.

> 2. How is ChucK naming like?
> Suppose we have a parameter p of type t. I would like to create its
> accessors as:
>
> - function void p(t i); // set
>   function t p(); // get
> Yet although chucK supports overloading functions, it does not let  
> them
> differ only by return type, right? In a test class I get stuff like:
>
> [test.ck]:line(5): function signatures differ in return type...
>
> The same thing with JAva really and I do understand it could often be
> ambiguous. Perl is one of the few languages in which this works  
> well as
> scalar is the only primitive scalar type and it has list and void  
> context to
> make things more or less unambiguous. But ChucK is not Perl, nough  
> said.

Yes, ChucK is a strongly typed language, which generally require  
return types of functions to be known at run-time.  One practice you  
might consider adopting is returning the value of the parameter in  
your set method, i.e.

> function t p(t i); // set
> function t p(); // get

This approach also makes things like this possible, which is  
sometimes appealing (or appalling):

class myClass
{
     int _p;
     fun int p( int __p ) { return __p => _p; }
     fun int p() { return _p; }
}

myClass a, b, c, d;
1 => a.p => b.p => c.p => d.p;

> - As I think parameters with the verbs get and set are slightly  
> redundant,
> if boolean stuff starts with e.g. is , I thought I would use:
> function t p();
> function setP(t i);
> However, if there is already a data member named p chucK does not  
> let me hav
> a member function named p in the same class, right? After modding  
> my test
> class, I got:
>
> [test.ck]:line(4): function name 'p' is already used by another value

Yes, this is similar semantically to many C-like languages.  A common  
practice that I see is, for a given parameter p, to call it _p and  
then have the accessors use p, as in the myClass example above.  m_p  
(for member variable p) is another popular approach.

> 3. To save some duplicated code, and as there's no constructor  
> support, it
> occurred to me I could write a function that given an array of UGens,
> instanciates my audio switch (OneOfN), populates it and returns a  
> reference.

Ah, yes, a "factory" method.  You might consider making this function  
a static member function of the OneOfN class rather than a non-class  
function.  This has the advantage of making the function accessible  
to all shreds if OneOfN is a public class.  (Its also liable to  
satisfy any object oriented nitpickers reading your code.)

> What might be wrong, i.e. why does it think an array of UGen is  
> just a UGen rather than an array? I'm mightily confused here. The  
> code:
> [...]
>    choices.caps() => int max; // Cache it, so only one method call.

I believe this should be choices.cap() (no 's').

> 4. When I use my audio switch to determine whether audio flows  
> through, i.e.
> as an audio relay one of whose inputs is practically disconnected  
> (I've
> patched blackhole there), it seems to work OK i.e. I get the sound of
> silence when expected. However, if I change my array initializer in
> OneOfN.ck:
>
> from:
>
> blackhole @=> newIn[i]; // Not connected initially.
>
> to
>
> null @=> newIn[i]; // Not connected initially.
>
> Strange things start to happen. I don't get a null pointer  
> exception at
> runtime as I would expect in my test script, as the unconnected  
> input is
> actually null. In stead ChucK crashes spectacularly with the standard
> WIndows XP dialog about it.

Yes!  This is a known bug in the currently release version.  It  
should be fixed in the current release candidate, and the upcoming  
release as well (feel free to test/try to break it at your convenience).

> [Speaking of Dracula, I'm just reading Frankenstein, talk about funny
> co-incidences. Hmm what's the code name for the next release?]

Coincidentally, frankenstein was the code name of the original ChucK  
release.  dracula is the code name for the current series of ChucK  
releases, whatever that means, so the name will probably be dracula  
for a while.

> I think these were my questions. As I tend to have a bad habbit of  
> asking
> all too much, when someone who knows far more than I do is around, I'd
> actually be pleased if even half of these would get answered  
> eventually,
> <smile>.

No worries!  We're all here to help.

spencer





More information about the chuck-users mailing list