/Lambda/Extensions.cs |
@@ -0,0 +1,309 @@ |
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // |
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // |
// rights of fair usage, the disclaimer and warranty conditions. // |
/////////////////////////////////////////////////////////////////////////// |
|
using System; |
using System.Collections.Generic; |
using System.Linq; |
|
namespace wasSharp.Lambda |
{ |
public static class Extensions |
{ |
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// A functional implementation of a switch clause. |
/// </summary> |
/// <typeparam name="T">the type of items in the query</typeparam> |
/// <param name="query">the selector query</param> |
/// <param name="default">the function to execute when no case matches</param> |
/// <param name="case">a list of predicates representing the switch cases, |
/// where each predicate has to return True or False indicating whether |
/// fallthrough should occur. |
/// </param> |
/// <remarks>when used, the default action must be explicitly specified |
/// due to language restrictions |
/// </remarks> |
public static void Switch<T>(this IEnumerable<T> query, |
// default |
Action<T> @default, |
// case |
// case |
// ... |
params Predicate<T>[] @case) |
{ |
if (@case.Length % 2 != 0) |
throw new ArgumentException("Pairs of predicates expected."); |
|
var enumerable = query as IList<T> ?? query.ToList(); |
using (var iter = enumerable.GetEnumerator()) |
{ |
while (iter.MoveNext()) |
{ |
var match = false; |
for (var i = 0; i < @case.Length; i += 2) |
{ |
if (!@case[i].Invoke(iter.Current)) |
continue; |
|
if (@case[i + 1].Invoke(iter.Current)) |
return; |
|
match = true; |
} |
|
if (!match) |
@default.Invoke(iter.Current); |
} |
} |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// A functional implementation of a switch clause. |
/// </summary> |
/// <typeparam name="T">the type of the item to query</typeparam> |
/// <param name="query">the selector query</param> |
/// <param name="default">the function to execute when no case matches</param> |
/// <param name="case">a list of predicates representing the switch cases, |
/// where each predicate has to return True or False indicating whether |
/// fallthrough should occur. |
/// </param> |
/// <remarks>when used, the default action must be explicitly specified |
/// due to language restrictions |
/// </remarks> |
public static void Switch<T>(this T query, |
// default |
Action<T> @default, |
// case |
// case |
// ... |
params Predicate<T>[] @case) |
{ |
if (@case.Length % 2 != 0) |
throw new ArgumentException("Pairs of predicates expected."); |
|
var match = false; |
for (var i = 0; i < @case.Length; i += 2) |
{ |
if (!@case[i].Invoke(query)) |
continue; |
|
if (@case[i + 1].Invoke(query)) |
return; |
|
match = true; |
} |
|
if (!match) |
@default.Invoke(query); |
|
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Invokes pf in case the predicate p resolves or qf in case the predicate q resolves, or ef otherwise. |
/// </summary> |
/// <typeparam name="T">the type of items in the query</typeparam> |
/// <param name="query">the selector query</param> |
/// <param name="p">the condition for invoking pf</param> |
/// <param name="pf">the action to invoke in case p resolves</param> |
/// <param name="q">the condition for invoking qf</param> |
/// <param name="qf">the action to invoke in case q resolves</param> |
/// <param name="ef">the action to invoke otherwise</param> |
public static void ForAll<T>(this ParallelQuery<T> query, Predicate<T> p, Action<T> pf, Predicate<T> q, Action<T> qf, Action<T> ef) |
{ |
query.ForAll(o => |
{ |
if (p.Invoke(o)) |
{ |
pf.Invoke(o); |
} |
else if (q.Invoke(o)) |
{ |
qf.Invoke(o); |
} |
else |
{ |
ef.Invoke(o); |
} |
}); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Invokes pf in case the predicate p resolves or qf in case the predicate q resolves. |
/// </summary> |
/// <typeparam name="T">the type of items in the query</typeparam> |
/// <param name="query">the selector query</param> |
/// <param name="p">the condition for invoking pf</param> |
/// <param name="pf">the action to invoke in case p resolves</param> |
/// <param name="q">the condition for invoking qf</param> |
/// <param name="qf">the action to invoke in case q resolves</param> |
public static void ForAll<T>(this ParallelQuery<T> query, Predicate<T> p, Action<T> pf, Predicate<T> q, Action<T> qf) |
{ |
query.ForAll(o => |
{ |
if (p.Invoke(o)) |
{ |
pf.Invoke(o); |
return; |
} |
|
if (q.Invoke(o)) |
{ |
qf.Invoke(o); |
return; |
} |
}); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Invokes pass if and only if predicate resovles or fail otherwise. |
/// </summary> |
/// <typeparam name="T">the type of items in the query</typeparam> |
/// <param name="query">the selector query</param> |
/// <param name="condition">the condition for invoking pf</param> |
/// <param name="pass">the function to invoke in case the predicate resolves</param> |
/// <param name="fail">the function to invoke otherwise</param> |
public static void ForAll<T>(this ParallelQuery<T> query, Predicate<T> condition, Action<T> pass, Action<T> fail) |
{ |
query.ForAll(o => |
{ |
switch (condition.Invoke(o)) |
{ |
case true: |
pass.Invoke(o); |
return; |
|
default: |
fail.Invoke(o); |
return; |
} |
}); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Invokes pass if and only if condition holds or fail otherwise. |
/// </summary> |
/// <typeparam name="T">the return type of the pass and fail functions</typeparam> |
/// <param name="condition">the branch condition</param> |
/// <param name="pass">function with no parameters and return type T in case condition passes</param> |
/// <param name="fail">function with no parameters and return type T in case condition fails</param> |
/// <returns>the result of pass in case condition holds or the result of fail otherwise</returns> |
public static T IfElse<T>(this bool condition, Func<T> pass, Func<T> fail) |
{ |
return condition ? pass.Invoke() : fail.Invoke(); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Invokes pass if and only if condition holds or fail otherwise. |
/// </summary> |
/// <typeparam name="U">the type of the argument to pass and fail</typeparam> |
/// <typeparam name="V">the return type of pass and fail</typeparam> |
/// <param name="condition">the branch condition</param> |
/// <param name="pass">function that takes argument arg and returns type V in case condition holds</param> |
/// <param name="fail">function that takes argument arg and returns type V in case condition fails</param> |
/// <param name="arg">the argument passed to pass or fail functions</param> |
/// <returns>the result of pass in case condition holds or the result of fail otherwise</returns> |
public static V IfElse<U, V>(this bool condition, Func<U, V> pass, Func<U, V> fail, U arg = default(U)) |
{ |
return condition ? pass.Invoke(arg) : fail.Invoke(arg); |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Invokes pass if and only if condition holds or fail otherwise. |
/// </summary> |
/// <typeparam name="T">the type of the argument to pass and fail</typeparam> |
/// <param name="condition">the branch condition</param> |
/// <param name="pass">function that takes argument arg and returns nothing in case condition holds</param> |
/// <param name="fail">function that takes argument arg and returns nothing in case condition fails</param> |
/// <param name="arg">the optional argument passed to pass or fail functions</param> |
public static void IfElse<T>(this bool condition, Action<T> pass, Action<T> fail, T arg = default(T)) |
{ |
switch (condition) |
{ |
case true: |
pass.Invoke(arg); |
return; |
|
default: |
fail.Invoke(arg); |
return; |
} |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Invokes pass if and only if condition holds or fail otherwise. |
/// </summary> |
/// <typeparam name="U">the type of the first argument to the pass or fail functions</typeparam> |
/// <typeparam name="V">the type of the second argument to the pass or fail functions</typeparam> |
/// <param name="condition">the branch condition</param> |
/// <param name="pass">function that takes argument arg and returns nothing in case condition holds</param> |
/// <param name="fail">function that takes argument arg and returns nothing in case condition fails</param> |
/// <param name="arga">first optional argument passed to pass or fail functions</param> |
/// <param name="argb">second optional argument passed to pass or fail functions</param> |
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)) |
{ |
switch (condition) |
{ |
case true: |
pass.Invoke(arga, argb); |
return; |
|
default: |
fail.Invoke(arga, argb); |
return; |
} |
} |
|
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // |
/////////////////////////////////////////////////////////////////////////// |
/// <summary> |
/// Returns true of an enumerable contains more than one element. |
/// </summary> |
/// <typeparam name="T">the type of the enumeration</typeparam> |
/// <param name="e">the enumeration</param> |
/// <returns>true if enumeration contains more than one element</returns> |
/// <remarks>O(2) worst case</remarks> |
public static bool Some<T>(this IEnumerable<T> e) |
{ |
var i = 0; |
using (var iter = e.GetEnumerator()) |
{ |
while (iter.MoveNext()) |
{ |
if (++i > 1) |
return true; |
} |
return false; |
} |
} |
} |
} |
/Sets/Extensions.cs |
@@ -0,0 +1,69 @@ |
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // |
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // |
// rights of fair usage, the disclaimer and warranty conditions. // |
/////////////////////////////////////////////////////////////////////////// |
|
using System; |
using System.Collections.Generic; |
using System.Linq; |
|
namespace wasSharp.Sets |
{ |
public static class Extensions |
{ |
/// <summary> |
/// Sequentially removes all the elements from the first sequence that are in the second sequence |
/// or all the elements from the second sequence that are in the first sequence. |
/// </summary> |
/// <typeparam name="T">the type o the collection</typeparam> |
/// <param name="o">the first sequence to remove from</param> |
/// <param name="p">the second sequence to remove</param> |
/// <returns>the first sequence excluding the second sequence or the second sequence excluding the first sequence</returns> |
public static IEnumerable<T> SequenceExceptAny<T>(this IEnumerable<T> o, IEnumerable<T> p) where T : IEquatable<T> |
{ |
var l = new List<T>(o); |
var r = new List<T>(p); |
return l.Count > r.Count |
? l.Zip(r, (x, y) => x.Equals(y) ? default(T) : y) |
.Concat(l.Skip(r.Count)) |
.Where(q => q != null && !q.Equals(default(T))) |
: r.Zip(l, (x, y) => x.Equals(y) ? default(T) : y) |
.Concat(r.Skip(l.Count)) |
.Where(q => q != null && !q.Equals(default(T))); |
} |
|
/// <summary> |
/// Sequentially removes all the elements from the first sequence that are in the second sequence. |
/// </summary> |
/// <typeparam name="T">the type o the collection</typeparam> |
/// <param name="o">the first sequence to remove from</param> |
/// <param name="p">the second sequence to remove</param> |
/// <returns>the first sequence excluding the second sequence</returns> |
public static IEnumerable<T> SequenceExcept<T>(this IEnumerable<T> a, IEnumerable<T> b) where T : IEquatable<T> |
{ |
using (var ea = a.GetEnumerator()) |
{ |
using (var eb = b.GetEnumerator()) |
{ |
while (ea.MoveNext()) |
{ |
if (eb.MoveNext() && ea.Current.Equals(eb.Current)) |
continue; |
yield return ea.Current; |
} |
} |
} |
} |
|
/// <summary> |
/// Determines whether a sequence is contained within another sequence. |
/// </summary> |
/// <returns>true if and only if the first set is contained in the second set</returns> |
/// <param name="a">The set to check</param> |
/// <param name="b">The set to check against</param> |
/// <typeparam name="T">the set type</typeparam> |
public static bool SubsetEquals<T>(this IEnumerable<T> a, IEnumerable<T> b) where T : IEquatable<T> => |
!a.OrderBy(s => s).SequenceExcept(b.OrderBy(s => s)).Any(); |
} |
} |