[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