///////////////////////////////////////////////////////////////////////////
// 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 //
///////////////////////////////////////////////////////////////////////////
///
/// A functional implementation of a switch clause.
///
/// the type of items in the query
/// the selector query
/// the function to execute when no case matches
/// a list of predicates representing the switch cases,
/// where each predicate has to return True or False indicating whether
/// fallthrough should occur.
///
/// when used, the default action must be explicitly specified
/// due to language restrictions
///
public static void Switch(this IEnumerable query,
// default
Action @default,
// case
// case
// ...
params Predicate[] @case)
{
if (@case.Length % 2 != 0)
throw new ArgumentException("Pairs of predicates expected.");
var enumerable = query as IList ?? 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 //
///////////////////////////////////////////////////////////////////////////
///
/// A functional implementation of a switch clause.
///
/// the type of the item to query
/// the selector query
/// the function to execute when no case matches
/// a list of predicates representing the switch cases,
/// where each predicate has to return True or False indicating whether
/// fallthrough should occur.
///
/// when used, the default action must be explicitly specified
/// due to language restrictions
///
public static void Switch(this T query,
// default
Action @default,
// case
// case
// ...
params Predicate[] @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 //
///////////////////////////////////////////////////////////////////////////
///
/// Invokes pf in case the predicate p resolves or qf in case the predicate q resolves, or ef otherwise.
///
/// the type of items in the query
/// the selector query
/// the condition for invoking pf
/// the action to invoke in case p resolves
/// the condition for invoking qf
/// the action to invoke in case q resolves
/// the action to invoke otherwise
public static void ForAll(this ParallelQuery query, Predicate p, Action pf, Predicate q, Action qf, Action 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 //
///////////////////////////////////////////////////////////////////////////
///
/// Invokes pf in case the predicate p resolves or qf in case the predicate q resolves.
///
/// the type of items in the query
/// the selector query
/// the condition for invoking pf
/// the action to invoke in case p resolves
/// the condition for invoking qf
/// the action to invoke in case q resolves
public static void ForAll(this ParallelQuery query, Predicate p, Action pf, Predicate q, Action 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 //
///////////////////////////////////////////////////////////////////////////
///
/// Invokes pass if and only if predicate resovles or fail otherwise.
///
/// the type of items in the query
/// the selector query
/// the condition for invoking pf
/// the function to invoke in case the predicate resolves
/// the function to invoke otherwise
public static void ForAll(this ParallelQuery query, Predicate condition, Action pass, Action 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 //
///////////////////////////////////////////////////////////////////////////
///
/// Invokes pass if and only if condition holds or fail otherwise.
///
/// the return type of the pass and fail functions
/// the branch condition
/// function with no parameters and return type T in case condition passes
/// function with no parameters and return type T in case condition fails
/// the result of pass in case condition holds or the result of fail otherwise
public static V IfElse(this T arg, Func condition, Func pass, Func fail)
{
return condition.Invoke(arg) ? pass.Invoke(arg) : fail.Invoke(arg);
}
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
///
/// Invokes pass if and only if condition holds or fail otherwise.
///
/// the return type of the pass and fail functions
/// the branch condition
/// function with no parameters and return type T in case condition passes
/// function with no parameters and return type T in case condition fails
/// the result of pass in case condition holds or the result of fail otherwise
public static T IfElse(this bool condition, Func pass, Func fail)
{
return condition ? pass.Invoke() : fail.Invoke();
}
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
///
/// Invokes pass if and only if condition holds or fail otherwise.
///
/// the type of the argument to pass and fail
/// the return type of pass and fail
/// the branch condition
/// function that takes argument arg and returns type V in case condition holds
/// function that takes argument arg and returns type V in case condition fails
/// the argument passed to pass or fail functions
/// the result of pass in case condition holds or the result of fail otherwise
public static V IfElse(this bool condition, Func pass, Func fail, U arg = default(U))
{
return condition ? pass.Invoke(arg) : fail.Invoke(arg);
}
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
///
/// Invokes pass if and only if condition holds or fail otherwise.
///
/// the type of the argument to pass and fail
/// the branch condition
/// function that takes argument arg and returns nothing in case condition holds
/// function that takes argument arg and returns nothing in case condition fails
/// the optional argument passed to pass or fail functions
public static void IfElse(this bool condition, Action pass, Action 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 //
///////////////////////////////////////////////////////////////////////////
///
/// Invokes pass if and only if condition holds or fail otherwise.
///
/// the type of the first argument to the pass or fail functions
/// the type of the second argument to the pass or fail functions
/// the branch condition
/// function that takes argument arg and returns nothing in case condition holds
/// function that takes argument arg and returns nothing in case condition fails
/// first optional argument passed to pass or fail functions
/// second optional argument passed to pass or fail functions
public static void IfElse(this bool condition, Action pass, Action 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 //
///////////////////////////////////////////////////////////////////////////
///
/// Returns true of an enumerable contains more than one element.
///
/// the type of the enumeration
/// the enumeration
/// true if enumeration contains more than one element
/// O(2) worst case
public static bool Some(this IEnumerable e)
{
var i = 0;
using (var iter = e.GetEnumerator())
{
while (iter.MoveNext())
{
if (++i > 1)
return true;
}
return false;
}
}
}
}