| 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: 24489
 Location: The Netherlands, Enschede
 Audio files: 298
 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: 24489
 Location: The Netherlands, Enschede
 Audio files: 298
 G2 patch files: 320
 
 | 
|  Posted: Tue Sep 08, 2009 11:28 am    Post subject: |    |   
| 
 |  
| Yes it has, just ran into that the other day 	  | Antimon wrote: |  	  | (Objective C?) | 
  _________________
 Jan
 also .. could someone please turn down the thermostat a bit.
 
  |  | 
| Back to top |  | 
 
|  | 
 
|  |