wasSharp – Diff between revs 46 and 47

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 46 Rev 47
1 /////////////////////////////////////////////////////////////////////////// 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // 2 // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
3 // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // 3 // Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
4 // rights of fair usage, the disclaimer and warranty conditions. // 4 // rights of fair usage, the disclaimer and warranty conditions. //
5 /////////////////////////////////////////////////////////////////////////// 5 ///////////////////////////////////////////////////////////////////////////
6   6  
7 using System; 7 using System;
8 using System.Collections.Generic; 8 using System.Collections.Generic;
9 using System.Linq; 9 using System.Linq;
10   10  
11 namespace wasSharp.Linq 11 namespace wasSharp.Linq
12 { 12 {
13 public static class Extensions 13 public static class Extensions
14 { 14 {
15 /////////////////////////////////////////////////////////////////////////// 15 ///////////////////////////////////////////////////////////////////////////
16 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 16 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
17 /////////////////////////////////////////////////////////////////////////// 17 ///////////////////////////////////////////////////////////////////////////
18 /// <summary> 18 /// <summary>
19 /// A functional implementation of a switch clause. 19 /// A functional implementation of a switch clause.
20 /// </summary> 20 /// </summary>
21 /// <typeparam name="T">the type of items in the query</typeparam> 21 /// <typeparam name="T">the type of items in the query</typeparam>
22 /// <param name="query">the selector query</param> 22 /// <param name="query">the selector query</param>
23 /// <param name="default">the function to execute when no case matches</param> 23 /// <param name="default">the function to execute when no case matches</param>
24 /// <param name="case">a list of predicates representing the switch cases, 24 /// <param name="case">a list of predicates representing the switch cases,
25 /// where each predicate has to return True or False indicating whether 25 /// where each predicate has to return True or False indicating whether
26 /// fallthrough should occur. 26 /// fallthrough should occur.
27 /// </param> 27 /// </param>
-   28 /// <remarks>when used, the default action must be explicitly specified
-   29 /// due to language restrictions
-   30 /// </remarks>
28 public static void Switch<T>(this IEnumerable<T> query, 31 public static void Switch<T>(this IEnumerable<T> query,
29 // default 32 // default
30 Action<T> @default, 33 Action<T> @default,
31 // case 34 // case
32 // case 35 // case
33 // ... 36 // ...
34 params Predicate<T>[] @case) 37 params Predicate<T>[] @case)
35 { 38 {
36 if (@case.Length % 2 != 0) 39 if (@case.Length % 2 != 0)
37 throw new ArgumentException("Pairs of predicates expected."); 40 throw new ArgumentException("Pairs of predicates expected.");
38   41  
39 var enumerable = query as IList<T> ?? query.ToList(); 42 var enumerable = query as IList<T> ?? query.ToList();
40 using (var iter = enumerable.GetEnumerator()) 43 using (var iter = enumerable.GetEnumerator())
41 { 44 {
42 while (iter.MoveNext()) 45 while (iter.MoveNext())
43 { 46 {
44 var match = false; 47 var match = false;
45 for (var i = 0; i < @case.Length; i += 2) 48 for (var i = 0; i < @case.Length; i += 2)
46 { 49 {
47 if (!@case[i].Invoke(iter.Current)) 50 if (!@case[i].Invoke(iter.Current))
48 continue; 51 continue;
49   52  
50 if (@case[i + 1].Invoke(iter.Current)) 53 if (@case[i + 1].Invoke(iter.Current))
51 return; 54 return;
52   55  
53 match = true; 56 match = true;
54 } 57 }
55   58  
56 if (!match) 59 if (!match)
57 @default.Invoke(iter.Current); 60 @default.Invoke(iter.Current);
58 } 61 }
59 } 62 }
60 } 63 }
61   64  
62 /////////////////////////////////////////////////////////////////////////// 65 ///////////////////////////////////////////////////////////////////////////
63 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 66 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
64 /////////////////////////////////////////////////////////////////////////// 67 ///////////////////////////////////////////////////////////////////////////
65 /// <summary> 68 /// <summary>
66 /// Invokes pf in case the predicate p resolves or qf in case the predicate q resolves, or ef otherwise. 69 /// Invokes pf in case the predicate p resolves or qf in case the predicate q resolves, or ef otherwise.
67 /// </summary> 70 /// </summary>
68 /// <typeparam name="T">the type of items in the query</typeparam> 71 /// <typeparam name="T">the type of items in the query</typeparam>
69 /// <param name="query">the selector query</param> 72 /// <param name="query">the selector query</param>
70 /// <param name="p">the condition for invoking pf</param> 73 /// <param name="p">the condition for invoking pf</param>
71 /// <param name="pf">the action to invoke in case p resolves</param> 74 /// <param name="pf">the action to invoke in case p resolves</param>
72 /// <param name="q">the condition for invoking qf</param> 75 /// <param name="q">the condition for invoking qf</param>
73 /// <param name="qf">the action to invoke in case q resolves</param> 76 /// <param name="qf">the action to invoke in case q resolves</param>
74 /// <param name="ef">the action to invoke otherwise</param> 77 /// <param name="ef">the action to invoke otherwise</param>
75 public static void ForAll<T>(this ParallelQuery<T> query, Predicate<T> p, Action<T> pf, Predicate<T> q, Action<T> qf, Action<T> ef) 78 public static void ForAll<T>(this ParallelQuery<T> query, Predicate<T> p, Action<T> pf, Predicate<T> q, Action<T> qf, Action<T> ef)
76 { 79 {
77 query.ForAll(o => 80 query.ForAll(o =>
78 { 81 {
79 if (p.Invoke(o)) 82 if (p.Invoke(o))
80 { 83 {
81 pf.Invoke(o); 84 pf.Invoke(o);
82 } 85 }
83 else if (q.Invoke(o)) 86 else if (q.Invoke(o))
84 { 87 {
85 qf.Invoke(o); 88 qf.Invoke(o);
86 } 89 }
87 else 90 else
88 { 91 {
89 ef.Invoke(o); 92 ef.Invoke(o);
90 } 93 }
91 }); 94 });
92 } 95 }
93   96  
94 /////////////////////////////////////////////////////////////////////////// 97 ///////////////////////////////////////////////////////////////////////////
95 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 98 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
96 /////////////////////////////////////////////////////////////////////////// 99 ///////////////////////////////////////////////////////////////////////////
97 /// <summary> 100 /// <summary>
98 /// Invokes pf in case the predicate p resolves or qf in case the predicate q resolves. 101 /// Invokes pf in case the predicate p resolves or qf in case the predicate q resolves.
99 /// </summary> 102 /// </summary>
100 /// <typeparam name="T">the type of items in the query</typeparam> 103 /// <typeparam name="T">the type of items in the query</typeparam>
101 /// <param name="query">the selector query</param> 104 /// <param name="query">the selector query</param>
102 /// <param name="p">the condition for invoking pf</param> 105 /// <param name="p">the condition for invoking pf</param>
103 /// <param name="pf">the action to invoke in case p resolves</param> 106 /// <param name="pf">the action to invoke in case p resolves</param>
104 /// <param name="q">the condition for invoking qf</param> 107 /// <param name="q">the condition for invoking qf</param>
105 /// <param name="qf">the action to invoke in case q resolves</param> 108 /// <param name="qf">the action to invoke in case q resolves</param>
106 public static void ForAll<T>(this ParallelQuery<T> query, Predicate<T> p, Action<T> pf, Predicate<T> q, Action<T> qf) 109 public static void ForAll<T>(this ParallelQuery<T> query, Predicate<T> p, Action<T> pf, Predicate<T> q, Action<T> qf)
107 { 110 {
108 query.ForAll(o => 111 query.ForAll(o =>
109 { 112 {
110 if (p.Invoke(o)) 113 if (p.Invoke(o))
111 { 114 {
112 pf.Invoke(o); 115 pf.Invoke(o);
113 return; 116 return;
114 } 117 }
115   118  
116 if (q.Invoke(o)) 119 if (q.Invoke(o))
117 { 120 {
118 qf.Invoke(o); 121 qf.Invoke(o);
119 return; 122 return;
120 } 123 }
121 }); 124 });
122 } 125 }
123   126  
124 /////////////////////////////////////////////////////////////////////////// 127 ///////////////////////////////////////////////////////////////////////////
125 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 128 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
126 /////////////////////////////////////////////////////////////////////////// 129 ///////////////////////////////////////////////////////////////////////////
127 /// <summary> 130 /// <summary>
128 /// Invokes pass if and only if predicate resovles or fail otherwise. 131 /// Invokes pass if and only if predicate resovles or fail otherwise.
129 /// </summary> 132 /// </summary>
130 /// <typeparam name="T">the type of items in the query</typeparam> 133 /// <typeparam name="T">the type of items in the query</typeparam>
131 /// <param name="query">the selector query</param> 134 /// <param name="query">the selector query</param>
132 /// <param name="condition">the condition for invoking pf</param> 135 /// <param name="condition">the condition for invoking pf</param>
133 /// <param name="pass">the function to invoke in case the predicate resolves</param> 136 /// <param name="pass">the function to invoke in case the predicate resolves</param>
134 /// <param name="fail">the function to invoke otherwise</param> 137 /// <param name="fail">the function to invoke otherwise</param>
135 public static void ForAll<T>(this ParallelQuery<T> query, Predicate<T> condition, Action<T> pass, Action<T> fail) 138 public static void ForAll<T>(this ParallelQuery<T> query, Predicate<T> condition, Action<T> pass, Action<T> fail)
136 { 139 {
137 query.ForAll(o => 140 query.ForAll(o =>
138 { 141 {
139 switch (condition.Invoke(o)) 142 switch (condition.Invoke(o))
140 { 143 {
141 case true: 144 case true:
142 pass.Invoke(o); 145 pass.Invoke(o);
143 return; 146 return;
144   147  
145 default: 148 default:
146 fail.Invoke(o); 149 fail.Invoke(o);
147 return; 150 return;
148 } 151 }
149 }); 152 });
150 } 153 }
151   154  
152 /////////////////////////////////////////////////////////////////////////// 155 ///////////////////////////////////////////////////////////////////////////
153 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 156 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
154 /////////////////////////////////////////////////////////////////////////// 157 ///////////////////////////////////////////////////////////////////////////
155 /// <summary> 158 /// <summary>
156 /// Invokes pass if and only if condition holds or fail otherwise. 159 /// Invokes pass if and only if condition holds or fail otherwise.
157 /// </summary> 160 /// </summary>
158 /// <typeparam name="T">the return type of the pass and fail functions</typeparam> 161 /// <typeparam name="T">the return type of the pass and fail functions</typeparam>
159 /// <param name="condition">the branch condition</param> 162 /// <param name="condition">the branch condition</param>
160 /// <param name="pass">function with no parameters and return type T in case condition passes</param> 163 /// <param name="pass">function with no parameters and return type T in case condition passes</param>
161 /// <param name="fail">function with no parameters and return type T in case condition fails</param> 164 /// <param name="fail">function with no parameters and return type T in case condition fails</param>
162 /// <returns>the result of pass in case condition holds or the result of fail otherwise</returns> 165 /// <returns>the result of pass in case condition holds or the result of fail otherwise</returns>
163 public static T IfElse<T>(this bool condition, Func<T> pass, Func<T> fail) 166 public static T IfElse<T>(this bool condition, Func<T> pass, Func<T> fail)
164 { 167 {
165 return condition ? pass.Invoke() : fail.Invoke(); 168 return condition ? pass.Invoke() : fail.Invoke();
166 } 169 }
167   170  
168 /////////////////////////////////////////////////////////////////////////// 171 ///////////////////////////////////////////////////////////////////////////
169 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 172 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
170 /////////////////////////////////////////////////////////////////////////// 173 ///////////////////////////////////////////////////////////////////////////
171 /// <summary> 174 /// <summary>
172 /// Invokes pass if and only if condition holds or fail otherwise. 175 /// Invokes pass if and only if condition holds or fail otherwise.
173 /// </summary> 176 /// </summary>
174 /// <typeparam name="U">the type of the argument to pass and fail</typeparam> 177 /// <typeparam name="U">the type of the argument to pass and fail</typeparam>
175 /// <typeparam name="V">the return type of pass and fail</typeparam> 178 /// <typeparam name="V">the return type of pass and fail</typeparam>
176 /// <param name="condition">the branch condition</param> 179 /// <param name="condition">the branch condition</param>
177 /// <param name="pass">function that takes argument arg and returns type V in case condition holds</param> 180 /// <param name="pass">function that takes argument arg and returns type V in case condition holds</param>
178 /// <param name="fail">function that takes argument arg and returns type V in case condition fails</param> 181 /// <param name="fail">function that takes argument arg and returns type V in case condition fails</param>
179 /// <param name="arg">the argument passed to pass or fail functions</param> 182 /// <param name="arg">the argument passed to pass or fail functions</param>
180 /// <returns>the result of pass in case condition holds or the result of fail otherwise</returns> 183 /// <returns>the result of pass in case condition holds or the result of fail otherwise</returns>
181 public static V IfElse<U, V>(this bool condition, Func<U, V> pass, Func<U, V> fail, U arg = default(U)) 184 public static V IfElse<U, V>(this bool condition, Func<U, V> pass, Func<U, V> fail, U arg = default(U))
182 { 185 {
183 return condition ? pass.Invoke(arg) : fail.Invoke(arg); 186 return condition ? pass.Invoke(arg) : fail.Invoke(arg);
184 } 187 }
185   188  
186 /////////////////////////////////////////////////////////////////////////// 189 ///////////////////////////////////////////////////////////////////////////
187 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 190 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
188 /////////////////////////////////////////////////////////////////////////// 191 ///////////////////////////////////////////////////////////////////////////
189 /// <summary> 192 /// <summary>
190 /// Invokes pass if and only if condition holds or fail otherwise. 193 /// Invokes pass if and only if condition holds or fail otherwise.
191 /// </summary> 194 /// </summary>
192 /// <typeparam name="T">the type of the argument to pass and fail</typeparam> 195 /// <typeparam name="T">the type of the argument to pass and fail</typeparam>
193 /// <param name="condition">the branch condition</param> 196 /// <param name="condition">the branch condition</param>
194 /// <param name="pass">function that takes argument arg and returns nothing in case condition holds</param> 197 /// <param name="pass">function that takes argument arg and returns nothing in case condition holds</param>
195 /// <param name="fail">function that takes argument arg and returns nothing in case condition fails</param> 198 /// <param name="fail">function that takes argument arg and returns nothing in case condition fails</param>
196 /// <param name="arg">the optional argument passed to pass or fail functions</param> 199 /// <param name="arg">the optional argument passed to pass or fail functions</param>
197 public static void IfElse<T>(this bool condition, Action<T> pass, Action<T> fail, T arg = default(T)) 200 public static void IfElse<T>(this bool condition, Action<T> pass, Action<T> fail, T arg = default(T))
198 { 201 {
199 switch (condition) 202 switch (condition)
200 { 203 {
201 case true: 204 case true:
202 pass.Invoke(arg); 205 pass.Invoke(arg);
203 return; 206 return;
204   207  
205 default: 208 default:
206 fail.Invoke(arg); 209 fail.Invoke(arg);
207 return; 210 return;
208 } 211 }
209 } 212 }
210   213  
211 /////////////////////////////////////////////////////////////////////////// 214 ///////////////////////////////////////////////////////////////////////////
212 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // 215 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
213 /////////////////////////////////////////////////////////////////////////// 216 ///////////////////////////////////////////////////////////////////////////
214 /// <summary> 217 /// <summary>
215 /// Invokes pass if and only if condition holds or fail otherwise. 218 /// Invokes pass if and only if condition holds or fail otherwise.
216 /// </summary> 219 /// </summary>
217 /// <typeparam name="U">the type of the first argument to the pass or fail functions</typeparam> 220 /// <typeparam name="U">the type of the first argument to the pass or fail functions</typeparam>
218 /// <typeparam name="V">the type of the second argument to the pass or fail functions</typeparam> 221 /// <typeparam name="V">the type of the second argument to the pass or fail functions</typeparam>
219 /// <param name="condition">the branch condition</param> 222 /// <param name="condition">the branch condition</param>
220 /// <param name="pass">function that takes argument arg and returns nothing in case condition holds</param> 223 /// <param name="pass">function that takes argument arg and returns nothing in case condition holds</param>
221 /// <param name="fail">function that takes argument arg and returns nothing in case condition fails</param> 224 /// <param name="fail">function that takes argument arg and returns nothing in case condition fails</param>
222 /// <param name="arga">first optional argument passed to pass or fail functions</param> 225 /// <param name="arga">first optional argument passed to pass or fail functions</param>
223 /// <param name="argb">second optional argument passed to pass or fail functions</param> 226 /// <param name="argb">second optional argument passed to pass or fail functions</param>
224 public static void IfElse<U, V>(this bool condition, Action<U, V> pass, Action<U, V> fail, U arga = default(U), V argb = default(V)) 227 public static void IfElse<U, V>(this bool condition, Action<U, V> pass, Action<U, V> fail, U arga = default(U), V argb = default(V))
225 { 228 {
226 switch (condition) 229 switch (condition)
227 { 230 {
228 case true: 231 case true:
229 pass.Invoke(arga, argb); 232 pass.Invoke(arga, argb);
230 return; 233 return;
231   234  
232 default: 235 default:
233 fail.Invoke(arga, argb); 236 fail.Invoke(arga, argb);
234 return; 237 return;
235 } 238 }
236 } 239 }
237   240  
238 /////////////////////////////////////////////////////////////////////////// 241 ///////////////////////////////////////////////////////////////////////////
239 // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // 242 // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 //
240 /////////////////////////////////////////////////////////////////////////// 243 ///////////////////////////////////////////////////////////////////////////
241 /// <summary> 244 /// <summary>
242 /// Returns true of an enumerable contains more than one element. 245 /// Returns true of an enumerable contains more than one element.
243 /// </summary> 246 /// </summary>
244 /// <typeparam name="T">the type of the enumeration</typeparam> 247 /// <typeparam name="T">the type of the enumeration</typeparam>
245 /// <param name="e">the enumeration</param> 248 /// <param name="e">the enumeration</param>
246 /// <returns>true if enumeration contains more than one element</returns> 249 /// <returns>true if enumeration contains more than one element</returns>
247 /// <remarks>O(2) worst case</remarks> 250 /// <remarks>O(2) worst case</remarks>
248 public static bool Some<T>(this IEnumerable<T> e) 251 public static bool Some<T>(this IEnumerable<T> e)
249 { 252 {
250 var i = 0; 253 var i = 0;
251 using (var iter = e.GetEnumerator()) 254 using (var iter = e.GetEnumerator())
252 { 255 {
253 while (iter.MoveNext()) 256 while (iter.MoveNext())
254 { 257 {
255 if (++i > 1) 258 if (++i > 1)
256 return true; 259 return true;
257 } 260 }
258 return false; 261 return false;
259 } 262 }
260 } 263 }
261   264  
262 /// <summary> 265 /// <summary>
263 /// Sequentially removes all the elements from the first sequence that are in the second sequence 266 /// Sequentially removes all the elements from the first sequence that are in the second sequence
264 /// or all the elements from the second sequence that are in the first sequence. 267 /// or all the elements from the second sequence that are in the first sequence.
265 /// </summary> 268 /// </summary>
266 /// <typeparam name="T">the type o the collection</typeparam> 269 /// <typeparam name="T">the type o the collection</typeparam>
267 /// <param name="o">the first sequence to remove from</param> 270 /// <param name="o">the first sequence to remove from</param>
268 /// <param name="p">the second sequence to remove</param> 271 /// <param name="p">the second sequence to remove</param>
269 /// <returns>the first sequence excluding the second sequence or the second sequence excluding the first sequence</returns> 272 /// <returns>the first sequence excluding the second sequence or the second sequence excluding the first sequence</returns>
270 public static IEnumerable<T> SequenceExceptAny<T>(this IEnumerable<T> o, IEnumerable<T> p) where T : IEquatable<T> 273 public static IEnumerable<T> SequenceExceptAny<T>(this IEnumerable<T> o, IEnumerable<T> p) where T : IEquatable<T>
271 { 274 {
272 var l = new List<T>(o); 275 var l = new List<T>(o);
273 var r = new List<T>(p); 276 var r = new List<T>(p);
274 return l.Count > r.Count 277 return l.Count > r.Count
275 ? l.Zip(r, (x, y) => x.Equals(y) ? default(T) : y) 278 ? l.Zip(r, (x, y) => x.Equals(y) ? default(T) : y)
276 .Concat(l.Skip(r.Count)) 279 .Concat(l.Skip(r.Count))
277 .Where(q => q != null && !q.Equals(default(T))) 280 .Where(q => q != null && !q.Equals(default(T)))
278 : r.Zip(l, (x, y) => x.Equals(y) ? default(T) : y) 281 : r.Zip(l, (x, y) => x.Equals(y) ? default(T) : y)
279 .Concat(r.Skip(l.Count)) 282 .Concat(r.Skip(l.Count))
280 .Where(q => q != null && !q.Equals(default(T))); 283 .Where(q => q != null && !q.Equals(default(T)));
281 } 284 }
282   285  
283 /// <summary> 286 /// <summary>
284 /// Sequentially removes all the elements from the first sequence that are in the second sequence. 287 /// Sequentially removes all the elements from the first sequence that are in the second sequence.
285 /// </summary> 288 /// </summary>
286 /// <typeparam name="T">the type o the collection</typeparam> 289 /// <typeparam name="T">the type o the collection</typeparam>
287 /// <param name="o">the first sequence to remove from</param> 290 /// <param name="o">the first sequence to remove from</param>
288 /// <param name="p">the second sequence to remove</param> 291 /// <param name="p">the second sequence to remove</param>
289 /// <returns>the first sequence excluding the second sequence</returns> 292 /// <returns>the first sequence excluding the second sequence</returns>
290 public static IEnumerable<T> SequenceExcept<T>(this IEnumerable<T> a, IEnumerable<T> b) where T : IEquatable<T> 293 public static IEnumerable<T> SequenceExcept<T>(this IEnumerable<T> a, IEnumerable<T> b) where T : IEquatable<T>
291 { 294 {
292 using (var ea = a.GetEnumerator()) 295 using (var ea = a.GetEnumerator())
293 { 296 {
294 using (var eb = b.GetEnumerator()) 297 using (var eb = b.GetEnumerator())
295 { 298 {
296 while (ea.MoveNext()) 299 while (ea.MoveNext())
297 { 300 {
298 if (eb.MoveNext() && ea.Current.Equals(eb.Current)) 301 if (eb.MoveNext() && ea.Current.Equals(eb.Current))
299 continue; 302 continue;
300 yield return ea.Current; 303 yield return ea.Current;
301 } 304 }
302 } 305 }
303 } 306 }
304 } 307 }
305 } 308 }
306 } 309 }
307   310