Author |
Message |
witt0191
Joined: Feb 13, 2008 Posts: 23 Location: UK
|
Posted: Mon Sep 07, 2009 10:26 am Post subject:
Passing control methods into functions how? |
|
|
Hi been looking at this all day and just cant get it to work
Trying to spork a function with what I think is called a control method as an argument eg.
Code: | SinOsc s => dac;
fun void thing(what_here gg){
440 => gg;
}
spork ~ thing(s.freq);
1000::ms => now; |
Any ideas?
Scott |
|
Back to top
|
|
|
Kassen
Janitor
Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3
|
Posted: Mon Sep 07, 2009 10:35 am Post subject:
|
|
|
Yes, I see.
In ChucK functions aren't objects and so can't be used as parameters. What you can do though is pass a object like a UGen as a parameter, then call a member function on that.
if you really, absolutely, must use references to functions you will have to create a "functor" class with a single member function called something like "do()" that you would overload for various such functions. You'd then pass a instance of one of those classes and call the ".do()" on that reference.
How you'd go about this depends a bit on what you'd like to accomplish. _________________ Kassen |
|
Back to top
|
|
|
witt0191
Joined: Feb 13, 2008 Posts: 23 Location: UK
|
Posted: Mon Sep 07, 2009 10:51 am Post subject:
|
|
|
Kassen wrote: | Yes, I see.
In ChucK functions aren't objects and so can't be used as parameters. What you can do though is pass a object like a UGen as a parameter, then call a member function on that. |
That sounds interesting could you point me to an example of this? |
|
Back to top
|
|
|
Antimon
Joined: Jan 18, 2005 Posts: 4145 Location: Sweden
Audio files: 371
G2 patch files: 100
|
Posted: Mon Sep 07, 2009 12:38 pm Post subject:
|
|
|
Curious how function-oriented programming is seeping into the mainstream (not assuming you're mainstream, witt0191, I just see this stuff more and more everywhere). I feel like I'll be old hat soon with my object-oriented thinking (not to mention that I lapse into procedural programming every now and then), if I don't read up on this stuff.
Something like this maybe:
Code: | class Functor {
fun void do(int i);
}
fun void thing(Functor f) {
440 => f.do;
}
class FreqSetter extends Functor {
UGen @ ugen;
fun void do(int i) {
i => ugen.freq;
}
}
FreqSetter => freqSetter;
SinOsc sinOsc @=> freqSetter.ugen;
spork ~ thing(freqSetter);
1000::ms => now;
|
Didn't test to compile it. It's cludgy - even if you specialize it (maybe you don't need a general Functor, maybe you'll only use one particualr UGen everywhere.) I'd try to solve it some other way, bhut I don't know your specific problem.
/Stefan _________________ Antimon's Window
@soundcloud @Flattr home - you can't explain music |
|
Back to top
|
|
|
Kassen
Janitor
Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3
|
Posted: Mon Sep 07, 2009 12:53 pm Post subject:
|
|
|
Here you go;
Code: | class Functor
{
fun float run( float arg1, float arg2)
{
return 0.0;
}
}
class Add extends Functor
{
fun float run(float arg1, float arg2)
{
return arg1 + arg2;
}
}
Add add;
class Mull extends Functor
{
fun float run(float arg1, float arg2)
{
return arg1 * arg2;
}
}
Mull mull;
class Wait extends Functor
{
fun float run(float arg1, float arg2)
{
arg1::second => now;
arg2::ms => now;
return 0.0;
}
}
Wait wait;
class SideEffect extends Functor
{
fun float run(float arg1, float arg2)
{
SinOsc s => dac;
Std.rand2f(arg1,arg2)::second => now;
return s.last();
}
}
SideEffect fx;
fun void example (Functor arg)
{
<<<arg.run(3, 2)>>>;
}
example(mull);
example(add);
example(fx);
example(wait); |
This is of quite basic but it's the principle that matters. The types should still line up but that's strong typing for you. _________________ Kassen |
|
Back to top
|
|
|
Kassen
Janitor
Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3
|
Posted: Mon Sep 07, 2009 1:09 pm Post subject:
|
|
|
Antimon wrote: | Curious how function-oriented programming is seeping into the mainstream (not assuming you're mainstream, witt0191, I just see this stuff more and more everywhere). |
Quite so. According to some every generation of procedural languages becomes more like lisp.
Quote: | I feel like I'll be old hat soon with my object-oriented thinking (not to mention that I lapse into procedural programming every now and then), if I don't read up on this stuff. |
Well... actually many functional languages are also object oriented, it's just that the typical object they deal with if a object of type "function". This is basically the core of lisp, where everything is a list or list-element and functions may be such elements (likely returning lists...).
Quote: |
Didn't test to compile it. It's cludgy - even if you specialize it (maybe you don't need a general Functor, maybe you'll only use one particualr UGen everywhere.) I'd try to solve it some other way, bhut I don't know your specific problem.
|
I ran mine and it works. I wouldn't do this unless needed but when I look at it like this it does seem fairly ok-ish. From a distance. I wouldn't push it much further than this because pushing it further will likely involve arrays, then there will be "Clemow's Bane". Also; we can't extend Functor with a overloaded "run" that returns a Functor because of the type-system (according to the language specs) however the parser -if memory serves- won't catch that and then there will be crashes. _________________ Kassen |
|
Back to top
|
|
|
witt0191
Joined: Feb 13, 2008 Posts: 23 Location: UK
|
Posted: Mon Sep 07, 2009 6:23 pm Post subject:
|
|
|
Hi,
Thanks for your replies.
I find that I tend to write functions and then spork them to change values like in the example above often, so I though that being able to throw the direct target into them rather than creating one for each purpose would be useful. Also could imagine use in a more dynamic system for that sort of capability.
Could see myself wanting to do something like
spork ~ changevalue(s.freq);
spork ~ changevalue(k.freq);
I suppose to be really useful there would be additional arguments setting other variables in the function
spork ~ changevalue(s.freq,500,1000::ms);
I could see this allowing me to reuse lots of functions more |
|
Back to top
|
|
|
Kassen
Janitor
Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3
|
Posted: Tue Sep 08, 2009 5:13 am Post subject:
|
|
|
Yes, but in that case it's different, in that case you pass the UGen (which is already a object) as the argument.
Code: |
fun void setFreq(UGen u, float freq)
{
//not all UGens have a ".freq()" se we need to cast.
//I just pick SinOsc here because it has a .freq()
//it's the function name that matters.
//this works fine as long as you never pass UGens without a .freq() member.
freq => (u $ SinOsc).freq;
} |
With a little loop and a extra duration argument you could create a glide. _________________ Kassen |
|
Back to top
|
|
|
witt0191
Joined: Feb 13, 2008 Posts: 23 Location: UK
|
Posted: Tue Sep 08, 2009 5:47 am Post subject:
|
|
|
Hi,
Thats ace could just explain whats going on in this portion of your code?
(u $ SinOsc)
thanks really like that |
|
Back to top
|
|
|
Antimon
Joined: Jan 18, 2005 Posts: 4145 Location: Sweden
Audio files: 371
G2 patch files: 100
|
Posted: Tue Sep 08, 2009 6:21 am Post subject:
|
|
|
witt0191 wrote: | Hi,
Thats ace could just explain whats going on in this portion of your code?
(u $ SinOsc)
thanks really like that |
That's a cast, in Java or C this would look something like this:
Code: | UGen ugen;
(...)
SinOsc s = (SinOsc) ugen; |
It tries to narrow down the type of a variable, if possible. If the variable isn't an instance of the type that you try to cast to (or a subtype of it), you will get a runtime error.
/Stefan _________________ Antimon's Window
@soundcloud @Flattr home - you can't explain music |
|
Back to top
|
|
|
Kassen
Janitor
Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3
|
Posted: Tue Sep 08, 2009 7:25 am Post subject:
|
|
|
Indeed.
more formally; things like SinOsc, LPF and Moog are all UGens and all have a .freq() member function. However, the "UGen" object iself doesn't have one and is just a abstraction (in fact it's virtually indentical to "Gain").
So; if we have a function that we'd like to be able to pass all of those types of UGens it would need to take "Ugen" as it's argument type.
Now there is a issue, as we may have a SinOsc (that does have a .freq) but we are considering it like a UGen, making the .freq inaccessible.
Here the cast ($) operator comes in. We can cast any type to a type that extends it (also to a type it's a extension off and float and int can be cast to each other). So; we cast this UGent-argument to a type that we know has the desired member function.
WARNING; this work, it's legal... but we are over-riding the type system so the type system no longer helps us make sure we are not making typos. When you would feed a "Gain" to this function you will have a VM crash. In the case of the mini that will mean losing all your unsaved code.
It's more or less like when I'd hand you a box and say there is a animal in it. You would not say say "I'm going to milk it" on your own because not all animals can be milked; there might be a beetle in there. The casting is like me guaranteeing you there is a cow, sheep or snake in there (that you will have to milk). If I'd make a mistake and accidentally put a ostrich in the box you would probably quit following my orders as they make no sense, which is exactly what the VM will do. _________________ Kassen |
|
Back to top
|
|
|
blue hell
Site Admin
Joined: Apr 03, 2004 Posts: 24079 Location: The Netherlands, Enschede
Audio files: 278
G2 patch files: 320
|
Posted: Tue Sep 08, 2009 9:57 am Post subject:
|
|
|
Does ChucK have run time type information? Such that I could ask an UGen if it in fact is an osc, or if in fact does have a freq() method?
In Pascal I'd write something like :
if anObject is TOscillator
then TOscillator( anObject).frequency := 1000; _________________ Jan
also .. could someone please turn down the thermostat a bit.
|
|
Back to top
|
|
|
Antimon
Joined: Jan 18, 2005 Posts: 4145 Location: Sweden
Audio files: 371
G2 patch files: 100
|
Posted: Tue Sep 08, 2009 10:44 am Post subject:
|
|
|
Yeah, in Java you would type
Code: | if (anObject instanceof TOscillator) |
I'm not aware of a similar test operator in ChucK. Some languages (Objective C?) even have an operator for testing if an object supports a particular function ("if ugen has freq" or some such).
/Stefan _________________ Antimon's Window
@soundcloud @Flattr home - you can't explain music |
|
Back to top
|
|
|
blue hell
Site Admin
Joined: Apr 03, 2004 Posts: 24079 Location: The Netherlands, Enschede
Audio files: 278
G2 patch files: 320
|
Posted: Tue Sep 08, 2009 11:28 am Post subject:
|
|
|
Antimon wrote: | (Objective C?) | Yes it has, just ran into that the other day _________________ Jan
also .. could someone please turn down the thermostat a bit.
|
|
Back to top
|
|
|
|