Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / HelpSource / Classes / Maybe.schelp
bloba17cab5f5e3d1065914a5892bc76ffb0cbdf2f60
1 class:: Maybe
2 summary:: referentially transparent proxy object
3 categories:: Libraries>JITLib>Environments
4 related:: Classes/Fdef, Overviews/JITLib
6 description::
7 A Maybe object can contain either nil or some other object, and allows to construct calculations without knowing this other object yet. If the calculation fails, due to a loop or a not yet defined object, Maybe returns nil.
9 The name strong::Maybe:: stems from the programming language Haskell, where it represents a somewhat similar entity. See also: link::Classes/Fdef::
11 ClassMethods::
13 method::new
14 create a new instance
16 argument::thing
17 an object or nil.
18 code::
19 a = Maybe.new;
20 b = Maybe(a + 6);
21 b.value; // => nil
22 a.value = 1;
23 b.value; // => 7
26 InstanceMethods::
28 method::source
29 return or set the contained object
31 method::value
32 set the contained object or return the source, or the value of the contained object, if it is a Maybe. If there is a recursion, return nil.
34 method::apply
35 return the value, or the value of the contained object, if it is a Maybe. This method allows recursion, so that recursive calcualtions can be made.
37 method::doesNotUnderstand
38 (called by any message that Maybe doesn't understand.)
40 returns a composition function that, when evaluated, returns the value.
41 code::
42 a = Maybe.new;
43 a.respondsTo(\flop) // false: Maybe constructs a placeholder instead
44 b = Maybe(a.flop);
45 b.value; // => nil
46 a.value = [1, 2, [2, 3]];
47 b.value;        // => [ [ 1, 2, 2 ], [ 1, 2, 3 ] ]
50 Examples::
52 code::
53 // the following examples use a LazyEnvir with a Maybe as a proxy class.
54 // instead of writing a = Maybe.new; a.value = something;
55 // one can simply write ~a = something.
56 // the Maybe is implictly created for you.
59         p.pop.clear;
60         p = LazyEnvir.new;
61         p.proxyClass = Maybe;
62         p.linkDoc; // here: connect to current doc only.
66 // sets
67 ~a = Set[0, 4, 5, 7];
68 ~b = Set[4, 5];
69 ~c = ~a union: ~b; // union of the two sets (note that the shortcut | does not work here.).
70 ~d = ~a sect: ~b; // intersection of a and b
71 ~c.postcs;""; // post the whole construction
72 ~d.postcs;"";
73 ~c.value; // Set[ 4, 0, 5, 7 ]
74 ~d.value; // Set[ 4, 5 ]
75 ~b = Set[4, 5, 13, 0];
76 ~c.value;
77 ~d.value; // Set[ 4, 0, 5 ]
78 ~b.source.add(~w); // add another placeholder
79 ~c.value; // it is part of the union.
80 ~d.value; // but not part of the intersection
83 // envirs
84 ~a = (note: [1, 2]);
85 ~b = (dur: 1);
86 ~c = ~a.putAll(~b) // provisionally put everything into the placholder
87 ~c.value;
88 ~a = (note: [1, 2, 4]);
89 ~c.value;
90 ~d = ~a.at(\note);
91 ~d.value;
92 ~a = (note: [7.5]);
93 ~d.value; // [7.5]
95 // patterns
96 ~a = Pseq([1, 2, 3]);
97 ~b = Pseq([5, ~a, ~a + 10], inf);
98 ~b.value.asStream.nextN(10);
101 ~a = Prand([100, 200]);
102 ~b.value.asStream.nextN(10);
105 // to do : flop!
107 //////////////// deep recursion
109 // with normal functions:
110 f = { |x| if(x <= 1) { 1 } { x * f.(x - 1) } };
111 f.(12)
114 ~faculty = { |x| if(x == 1) { 1 } { x * ~faculty.(x - 1) } };
115 ~faculty.(12) // doesn't work (=> nil). here we _do_ want recursion ...
117 // for explicit recursion use "apply"
118 ~faculty = { |x| if(x == 1) { 1 } { x * ~faculty.apply(x - 1) } };
119 ~faculty.(12)
121 /*// safety (not yet implemented)
122 Maybe.maxDepth = 1e2; // higher depth is risky..
123 ~faculty = { |x| x * ~faculty.apply(x - 1) }; // infinite recursion
124 ~faculty.(12)
126 Maybe.maxDepth = nil; // unsafe again.*/
129 //////////////// recursion prevention tests
131 ~b = ~a;
132 ~a = ~b;
133 ~a.value; // => nil
136 ~a = ~b;
137 ~b = ~c;
138 ~c = ~a;
139 ~a.value; // => nil
141 ~a = ~b + ~c;
142 ~c = ~a;
143 ~a.value; // => nil
146 ~a = ~b;
147 ~b = 19;
148 ~a.value; // => 19
149 ~b.value; // => 19
151 // function evaluation and argument passing
153 ~a = { |x| x + 2 };
154 ~a.value; // => nil
156 ~a.value(~c); // => nil
157 ~b = 2000;
158 ~a.value(~b); // => 2002
159 ~x = [600, 1000];
161 (~a + 1).value(~b); // 2003
162 (~a + 1).value(~x); // [ 603, 1003 ]
163 (~a + 1).value({ 8 }); // binary op func.
164 (~a + 1).value({ 5 + 3 }).value // 11
166 ~a = { |x| x + 2 + ~b };
167 ~a.value(8); // 2010
169 ~c = nil;
170 ~a = { |x| x + 2 + ~c }; // ~c is undefined.
171 ~a.value(8); // => nil
173 ~c = 100; // define ~c
175 ~a.value(8); // now returns a value.
177 ~c = ~b; // now recursion?
178 ~b = ~a;
179 ~a.value(8); // caught recursion => nil
181 ~c = { 100.rand }; // ~c is a function
183 ~a.value(8);
184 ~a.value(8);
186 ~c = { ~a + ~b };
187 ~a.value(8);    // ~c is a recursion with ~a => nil
190 // function composition
191 ~a = {|x| x + 1 };
192 ~v = ~a <> ~a <> ~a; // same as: { ~a.(~a.(~a)) }
193 ~v.value(0); // => 3
195 ~a = {|x| x + 2 };
196 ~v.value(0); // transparent. => 6
198 // {|x| x }.valueEnvir // doesn't work with current implementation of Function:valueEnvir
201 // calculations with functions:
202 ~c = 0;
203 ~a = { |ff| { ff = ff + 1; ~c + ff + 2 + ~c } };
204 ~x = ~a.value(8);
205 ~x.value; // return 11, 12, 13...
206 ~x.value;
207 ~x.value;
208 ~c = 100;
209 ~x.value; // return 214, 215 ...
210 ~x.value;
212 // binary op functions:
213 ~c = 0;
214 ~a = { |ff| { [600, 800] } + { ff + 2 + ~c } };
216 ~x = ~a.value(8);
217 ~x.value; // return [ 610, 810 ]
219 ~c = { [10, -10].rand };
220 ~x.value; // return random between [ 610..620, 800..810 ]