I want to convert IEnumerable<Task<T>> to IObservable<T>. I found solution to this here:
IObservable<T> ToObservable<T>(IEnumerable<Task<T>> source)
{
return source.Select(t => t.ToObservable()).Merge();
}
It is perfectly ok for usual cases, but I need to handle exceptions, that could raise in that Tasks... So IObservable<T> should not be dead after first exception.
What I read, recommendation for this use case is to use some wrapper, that will carry actual value or error. So my attempt was
IObservable<Either<T, Exception>> ToObservable<T>(IEnumerable<Task<T>> source)
{
var subject = new Subject<Either<T, Exception>>();
foreach (var observable in GetIntsIEnumerable().Select(t => t.ToObservable()))
{
observable.Subscribe(i => subject.OnNext(i), e => subject.OnNext(e));
}
return subject;
}
With Either<T, Exception> borrowed from this article.
But this is not ok either, because OnCompleted() is not called. How should I solve it? I'm pretty new with Rx concept.
Here is full code for testing...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Reactive.Threading.Tasks;
using System.Threading;
using System.Threading.Tasks;
namespace Test
{
class Program
{
static Task Main()
{
SemaphoreSlim signal = new SemaphoreSlim(0, 1);
//GetInts1().Subscribe(
// i => Console.WriteLine($"OK: {i}"),
// e => Console.WriteLine($"ERROR: {e.Message}"),
// () => signal.Release());
GetInts2().Subscribe(r => Console.WriteLine(r.Match(
i => $"OK: {i}",
e => $"ERROR: {e.Message}")),
() => signal.Release());
return signal.WaitAsync();
}
static IObservable<int> GetInts1()
{
return GetIntsIEnumerable().Select(t => t.ToObservable()).Merge();
}
static IObservable<Either<int, Exception>> GetInts2()
{
var subject = new Subject<Either<int, Exception>>();
foreach (var observable in GetIntsIEnumerable().Select(t => t.ToObservable()))
{
observable.Subscribe(i => subject.OnNext(i), e => subject.OnNext(e));
}
return subject;
}
static IEnumerable<Task<int>> GetIntsIEnumerable()
{
Random rnd = new Random();
foreach (int i in Enumerable.Range(1, 10))
{
yield return Task.Run(async () =>
{
await Task.Delay(rnd.Next(0, 5000));
if (i == 6)
throw new ArgumentException();
return i;
});
}
}
}
/// <summary>
/// Functional data data to represent a discriminated
/// union of two possible types.
/// </summary>
/// <typeparam name="TL">Type of "Left" item.</typeparam>
/// <typeparam name="TR">Type of "Right" item.</typeparam>
public class Either<TL, TR>
{
private readonly TL left;
private readonly TR right;
private readonly bool isLeft;
public Either(TL left)
{
this.left = left;
this.isLeft = true;
}
public Either(TR right)
{
this.right = right;
this.isLeft = false;
}
public T Match<T>(Func<TL, T> leftFunc, Func<TR, T> rightFunc)
{
if (leftFunc == null)
{
throw new ArgumentNullException(nameof(leftFunc));
}
if (rightFunc == null)
{
throw new ArgumentNullException(nameof(rightFunc));
}
return this.isLeft ? leftFunc(this.left) : rightFunc(this.right);
}
/// <summary>
/// If right value is assigned, execute an action on it.
/// </summary>
/// <param name="rightAction">Action to execute.</param>
public void DoRight(Action<TR> rightAction)
{
if (rightAction == null)
{
throw new ArgumentNullException(nameof(rightAction));
}
if (!this.isLeft)
{
rightAction(this.right);
}
}
public TL LeftOrDefault() => this.Match(l => l, r => default);
public TR RightOrDefault() => this.Match(l => default, r => r);
public static implicit operator Either<TL, TR>(TL left) => new Either<TL, TR>(left);
public static implicit operator Either<TL, TR>(TR right) => new Either<TL, TR>(right);
}
}
There's a built-in mechanism for handling errors like this. Simply use the .Materialize() operator which changes an IObservable<T> to an IObservable<Notification<T>> and allows errors and completions to be viewed as normal values.
So, as an example, Observable.Return<int>(42) produces a value 42 and a completion, but Observable.Return<int>(42).Materialize() produces a value Notification.CreateOnNext<int>(42), followed by a value Notification.CreateOnCompleted<int>(), followed by a normal completion.
If you have a sequence that produces an error then you effectively get a value Notification.CreateOnError<T>(exception) followed by a normal completion.
This all means that you can change your code like this:
IObservable<Notification<T>> ToObservable<T>(IEnumerable<Task<T>> source)
{
return source.Select(t => t.ToObservable().Materialize()).Merge();
}
Your test code is a little bit complicated for my liking. You should never need to use a SemaphoreSlim nor a Subject in the way that you're using them.
I've written my own test code.
void Main()
{
var r = new Random();
IEnumerable<Task<int>> source =
Enumerable
.Range(0, 10).Select(x => Task.Factory.StartNew(() =>
{
Thread.Sleep(r.Next(10000));
if (x % 3 == 0) throw new NotSupportedException($"Failed on {x}");
return x;
}));
IObservable<Notification<int>> query = source.ToObservable();
query
.Do(x =>
{
if (x.Kind == NotificationKind.OnError)
{
Console.WriteLine(x.Exception.Message);
}
})
.Where(x => x.Kind == NotificationKind.OnNext) // Only care about vales
.Select(x => x.Value)
.Subscribe(x => Console.WriteLine(x), () => Console.WriteLine("Done."));
}
public static class Ex
{
public static IObservable<Notification<T>> ToObservable<T>(this IEnumerable<Task<T>> source)
{
return source.Select(t => t.ToObservable().Materialize()).Merge();
}
}
A typical run of that code produces:
Failed on 3
2
5
4
Failed on 0
Failed on 9
Failed on 6
7
1
8
Done.
The Rx library contains a Merge overload that merges tasks directly and efficiently, instead of converting each task to an intermediate throw-away observable sequence:
// Merges results from all source tasks into a single observable sequence.
public static IObservable<TSource> Merge<TSource>(
this IObservable<Task<TSource>> sources);
You could use this operator for the implementation of the ToObservable method like this:
IObservable<Either<T, Exception>> ToObservable<T>(IEnumerable<Task<T>> source)
{
return source
.Select(async task =>
{
try { return new Either<T, Exception>(await task); }
catch (Exception ex) { return new Either<T, Exception>(ex); }
})
.ToObservable()
.Merge();
}
You can place the ToObservable operator before or after the Select operator, it doesn't make any difference.
Btw there is available a minimalistic library (Try by Stephen Cleary) that contains a Try<T> type, which is similar in functionality to the Either type, but is specialized for having an Exception as the second type (as an Either<T, Exception>). Using this library, you could implement the ToObservable method like this:
IObservable<Try<T>> ToObservable<T>(IEnumerable<Task<T>> source)
{
return source
.Select(task => Try.Create(() => task))
.ToObservable()
.Merge();
}
Here is the definition of the Try.Create method:
// Executes the specified function, and wraps either the result or the exception.
public static Task<Try<T>> Create<T>(Func<Task<T>> func);
Related
I'm using some functional stuff in C# and keep getting stuck on the fact that List.Add doesn't return the updated list.
In general, I'd like to call a function on an object and then return the updated object.
For example it would be great if C# had a comma operator:
((accum, data) => accum.Add(data), accum)
I could write my own "comma operator" like this:
static T comma(Action a, Func<T> result) {
a();
return result();
}
It looks like it would work but the call site would ugly. My first example would be something like:
((accum, data) => comma(accum.Add(data), ()=>accum))
Enough examples! What's the cleanest way to do this without another developer coming along later and wrinkling his or her nose at the code smell?
I know this as Fluent.
A Fluent example of a List.Add using Extension Methods
static List<T> MyAdd<T>(this List<T> list, T element)
{
list.Add(element);
return list;
}
I know that this thread is very old, but I want to append the following information for future users:
There isn't currently such an operator. During the C# 6 development cycle a semicolon operator was added, as:
int square = (int x = int.Parse(Console.ReadLine()); Console.WriteLine(x - 2); x * x);
which can be translated as follows:
int square = compiler_generated_Function();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int compiler_generated_Function()
{
int x = int.Parse(Console.ReadLine());
Console.WriteLine(x - 2);
return x * x;
}
However, this feature was dropped before the final C# release.
You can do almost exactly the first example naturally using code blocks in C# 3.0.
((accum, data) => { accum.Add(data); return accum; })
This is what Concat http://msdn.microsoft.com/en-us/library/vstudio/bb302894%28v=vs.100%29.aspx is for. Just wrap a single item in an array. Functional code should not mutate the original data. If performance is a concern, and this isn't good enough, then you'll no longer be using the functional paradigm.
((accum, data) => accum.Concat(new[]{data}))
Another technique, straight from functional programming, is as follows. Define an IO struct like this:
/// <summary>TODO</summary>
public struct IO<TSource> : IEquatable<IO<TSource>> {
/// <summary>Create a new instance of the class.</summary>
public IO(Func<TSource> functor) : this() { _functor = functor; }
/// <summary>Invokes the internal functor, returning the result.</summary>
public TSource Invoke() => (_functor | Default)();
/// <summary>Returns true exactly when the contained functor is not null.</summary>
public bool HasValue => _functor != null;
X<Func<TSource>> _functor { get; }
static Func<TSource> Default => null;
}
and make it a LINQ-able monad with these extension methods:
[SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces")]
public static class IO {
public static IO<TSource> ToIO<TSource>( this Func<TSource> source) {
source.ContractedNotNull(nameof(source));
return new IO<TSource>(source);
}
public static IO<TResult> Select<TSource,TResult>(this IO<TSource> #this,
Func<TSource,TResult> projector
) =>
#this.HasValue && projector!=null
? New(() => projector(#this.Invoke()))
: Null<TResult>();
public static IO<TResult> SelectMany<TSource,TResult>(this IO<TSource> #this,
Func<TSource,IO<TResult>> selector
) =>
#this.HasValue && selector!=null
? New(() => selector(#this.Invoke()).Invoke())
: Null<TResult>();
public static IO<TResult> SelectMany<TSource,T,TResult>(this IO<TSource> #this,
Func<TSource, IO<T>> selector,
Func<TSource,T,TResult> projector
) =>
#this.HasValue && selector!=null && projector!=null
? New(() => { var s = #this.Invoke(); return projector(s, selector(s).Invoke()); } )
: Null<TResult>();
public static IO<TResult> New<TResult> (Func<TResult> functor) => new IO<TResult>(functor);
private static IO<TResult> Null<TResult>() => new IO<TResult>(null);
}
and now you can use the LINQ comprehensive syntax thus:
using Xunit;
[Fact]
public static void IOTest() {
bool isExecuted1 = false;
bool isExecuted2 = false;
bool isExecuted3 = false;
bool isExecuted4 = false;
IO<int> one = new IO<int>( () => { isExecuted1 = true; return 1; });
IO<int> two = new IO<int>( () => { isExecuted2 = true; return 2; });
Func<int, IO<int>> addOne = x => { isExecuted3 = true; return (x + 1).ToIO(); };
Func<int, Func<int, IO<int>>> add = x => y => { isExecuted4 = true; return (x + y).ToIO(); };
var query1 = ( from x in one
from y in two
from z in addOne(y)
from _ in "abc".ToIO()
let addOne2 = add(x)
select addOne2(z)
);
Assert.False(isExecuted1); // Laziness.
Assert.False(isExecuted2); // Laziness.
Assert.False(isExecuted3); // Laziness.
Assert.False(isExecuted4); // Laziness.
int lhs = 1 + 2 + 1;
int rhs = query1.Invoke().Invoke();
Assert.Equal(lhs, rhs); // Execution.
Assert.True(isExecuted1);
Assert.True(isExecuted2);
Assert.True(isExecuted3);
Assert.True(isExecuted4);
}
When one desires an IO monad that composes but returns only void, define this struct and dependent methods:
public struct Unit : IEquatable<Unit>, IComparable<Unit> {
[CLSCompliant(false)]
public static Unit _ { get { return _this; } } static Unit _this = new Unit();
}
public static IO<Unit> ConsoleWrite(object arg) =>
ReturnIOUnit(() => Write(arg));
public static IO<Unit> ConsoleWriteLine(string value) =>
ReturnIOUnit(() => WriteLine(value));
public static IO<ConsoleKeyInfo> ConsoleReadKey() => new IO<ConsoleKeyInfo>(() => ReadKey());
which readily allow the writing of code fragments like this:
from pass in Enumerable.Range(0, int.MaxValue)
let counter = Readers.Counter(0)
select ( from state in gcdStartStates
where _predicate(pass, counter())
select state )
into enumerable
where ( from _ in Gcd.Run(enumerable.ToList()).ToIO()
from __ in ConsoleWrite(Prompt(mode))
from c in ConsoleReadKey()
from ___ in ConsoleWriteLine()
select c.KeyChar.ToUpper() == 'Q'
).Invoke()
select 0;
where the old C comma operator is readily recognized for what it is: a monadic compose operation.
The true merit of the comprehension syntax is apparent when one attempts to write that fragment in the flunt style:
( Enumerable.Range(0,int.MaxValue)
.Select(pass => new {pass, counter = Readers.Counter(0)})
.Select(_ => gcdStartStates.Where(state => _predicate(_.pass,_.counter()))
.Select(state => state)
)
).Where(enumerable =>
( (Gcd.Run(enumerable.ToList()) ).ToIO()
.SelectMany(_ => ConsoleWrite(Prompt(mode)),(_,__) => new {})
.SelectMany(_ => ConsoleReadKey(), (_, c) => new {c})
.SelectMany(_ => ConsoleWriteLine(), (_,__) => _.c.KeyChar.ToUpper() == 'Q')
).Invoke()
).Select(list => 0);
The extension method is arguably the best solution, but for completeness' sake, don't forget the obvious alternative: a wrapper class.
public class FList<T> : List<T>
{
public new FList<T> Add(T item)
{
base.Add(item);
return this;
}
public new FList<T> RemoveAt(int index)
{
base.RemoveAt(index);
return this;
}
// etc...
}
{
var list = new FList<string>();
list.Add("foo").Add("remove me").Add("bar").RemoveAt(1);
}
I thought it would be interesting to make a version of my wrapper class answer that doesn't require you write the wrapper methods.
public class FList<T> : List<T>
{
public FList<T> Do(string method, params object[] args)
{
var methodInfo = GetType().GetMethod(method);
if (methodInfo == null)
throw new InvalidOperationException("I have no " + method + " method.");
if (methodInfo.ReturnType != typeof(void))
throw new InvalidOperationException("I'm only meant for void methods.");
methodInfo.Invoke(this, args);
return this;
}
}
{
var list = new FList<string>();
list.Do("Add", "foo")
.Do("Add", "remove me")
.Do("Add", "bar")
.Do("RemoveAt", 1)
.Do("Insert", 1, "replacement");
foreach (var item in list)
Console.WriteLine(item);
}
Output:
foo
replacement
bar
EDIT
You can slim down the syntax by exploiting C# indexed properties.
Simply add this method:
public FList<T> this[string method, params object[] args]
{
get { return Do(method, args); }
}
And the call now looks like:
list = list["Add", "foo"]
["Add", "remove me"]
["Add", "bar"]
["RemoveAt", 1]
["Insert", 1, "replacement"];
With the linebreaks being optional, of course.
Just a bit of fun hacking the syntax.
I have the following code:
IEnumerable<KeyValuePair<T, double>> items =
sequence.Select(item => new KeyValuePair<T, double>(item, weight(item)));
if (items.Any(pair => pair.Value<0))
throw new ArgumentException("Item weights cannot be less than zero.");
double sum = items.Sum(pair => pair.Value);
foreach (KeyValuePair<T, double> pair in items) {...}
Where weight is a Func<T, double>.
The problem is I want weight to be executed as few times as possible. This means it should be executed at most once for each item. I could achieve this by saving it to an array. However, if any weight returns a negative value, I don't want to continue execution.
Is there any way to accomplish this easily within the LINQ framework?
Sure, that's totally doable:
public static Func<A, double> ThrowIfNegative<A, double>(this Func<A, double> f)
{
return a=>
{
double r = f(a);
// if r is NaN then this will throw.
if ( !(r >= 0.0) )
throw new Exception();
return r;
};
}
public static Func<A, R> Memoize<A, R>(this Func<A, R> f)
{
var d = new Dictionary<A, R>();
return a=>
{
R r;
if (!d.TryGetValue(a, out r))
{
r = f(a);
d.Add(a, r);
}
return r;
};
}
And now...
Func<T, double> weight = whatever;
weight = weight.ThrowIfNegative().Memoize();
and you're done.
One way is to move the exception into the weight function, or at least simulate doing so, by doing something like:
Func<T, double> weightWithCheck = i =>
{
double result = weight(i);
if (result < 0)
{
throw new ArgumentException("Item weights cannot be less than zero.");
}
return result;
};
IEnumerable<KeyValuePair<T, double>> items =
sequence.Select(item => new KeyValuePair<T, double>(item, weightWithCheck(item)));
double sum = items.Sum(pair => pair.Value);
By this point, if there is an exception to be had, you should have it. You do have to enumerate items before you can be assured of getting the exception, though, but once you get it, you will not call weight again.
Both answers are good (where to throw the exception, and memoizing the function).
But your real problem is that your LINQ expression is evaluated every time you use it, unless you force it to evaluate and store as a List (or similar). Just change this:
sequence.Select(item => new KeyValuePair<T, double>(item, weight(item)));
To this:
sequence.Select(item => new KeyValuePair<T, double>(item, weight(item))).ToList();
You could possibly do it with a foreach loop. Here is a way to do it in one statement:
IEnumerable<KeyValuePair<T, double>> items = sequence
.Select(item => new KeyValuePair<T, double>(item, weight(item)))
.Select(kvp =>
{
if (kvp.Value < 0)
throw new ArgumentException("Item weights cannot be less than zero.");
else
return kvp;
}
);
No, there is nothing already IN the LINQ framework to do this, but you could surely write up your own methods and invoke them from the linq query (As has already been shown by many).
Personally, I would either ToList the first query or use Eric's suggestion.
Instead of a functional memoization suggested by other answers, you can also employ a memoization for the whole data sequence:
var items = sequence
.Select(item => new KeyValuePair<T, double>(item, weight(item)))
.Memoize();
(Note a call to Memoize() method at the end of the expression above)
A nice property of data memoization is that it represents a drop-in replacement for ToList() or ToArray() approaches.
The fully featured implementation is pretty involved though:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
static class MemoizationExtensions
{
/// <summary>
/// Memoize all elements of a sequence, e.g. ensure that every element of a sequence is retrieved only once.
/// </summary>
/// <remarks>
/// The resulting sequence is not thread safe.
/// </remarks>
/// <typeparam name="T">The type of the elements of source.</typeparam>
/// <param name="source">The source sequence.</param>
/// <returns>The sequence that fully replicates the source with all elements being memoized.</returns>
public static IEnumerable<T> Memoize<T>(this IEnumerable<T> source) => Memoize(source, false);
/// <summary>
/// Memoize all elements of a sequence, e.g. ensure that every element of a sequence is retrieved only once.
/// </summary>
/// <typeparam name="T">The type of the elements of source.</typeparam>
/// <param name="source">The source sequence.</param>
/// <param name="isThreadSafe">Indicates whether resulting sequence is thread safe.</param>
/// <returns>The sequence that fully replicates the source with all elements being memoized.</returns>
public static IEnumerable<T> Memoize<T>(this IEnumerable<T> source, bool isThreadSafe)
{
switch (source)
{
case null:
return null;
case CachedEnumerable<T> existingCachedEnumerable:
if (!isThreadSafe || existingCachedEnumerable is ThreadSafeCachedEnumerable<T>)
{
// The source is already memoized with compatible parameters.
return existingCachedEnumerable;
}
break;
case IList<T> _:
case IReadOnlyList<T> _:
case string _:
// Given source types are intrinsically memoized by their nature.
return source;
}
if (isThreadSafe)
return new ThreadSafeCachedEnumerable<T>(source);
else
return new CachedEnumerable<T>(source);
}
class CachedEnumerable<T> : IEnumerable<T>, IReadOnlyList<T>
{
public CachedEnumerable(IEnumerable<T> source)
{
_Source = source;
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
IEnumerable<T> _Source;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
IEnumerator<T> _SourceEnumerator;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
protected readonly IList<T> Cache = new List<T>();
public virtual int Count
{
get
{
while (_TryCacheElementNoLock()) ;
return Cache.Count;
}
}
bool _TryCacheElementNoLock()
{
if (_SourceEnumerator == null && _Source != null)
{
_SourceEnumerator = _Source.GetEnumerator();
_Source = null;
}
if (_SourceEnumerator == null)
{
// Source enumerator already reached the end.
return false;
}
else if (_SourceEnumerator.MoveNext())
{
Cache.Add(_SourceEnumerator.Current);
return true;
}
else
{
// Source enumerator has reached the end, so it is no longer needed.
_SourceEnumerator.Dispose();
_SourceEnumerator = null;
return false;
}
}
public virtual T this[int index]
{
get
{
_EnsureItemIsCachedNoLock(index);
return Cache[index];
}
}
public IEnumerator<T> GetEnumerator() => new CachedEnumerator<T>(this);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
internal virtual bool EnsureItemIsCached(int index) => _EnsureItemIsCachedNoLock(index);
bool _EnsureItemIsCachedNoLock(int index)
{
while (Cache.Count <= index)
{
if (!_TryCacheElementNoLock())
return false;
}
return true;
}
internal virtual T GetCacheItem(int index) => Cache[index];
}
sealed class ThreadSafeCachedEnumerable<T> : CachedEnumerable<T>
{
public ThreadSafeCachedEnumerable(IEnumerable<T> source) :
base(source)
{
}
public override int Count
{
get
{
lock (Cache)
return base.Count;
}
}
public override T this[int index]
{
get
{
lock (Cache)
return base[index];
}
}
internal override bool EnsureItemIsCached(int index)
{
lock (Cache)
return base.EnsureItemIsCached(index);
}
internal override T GetCacheItem(int index)
{
lock (Cache)
return base.GetCacheItem(index);
}
}
sealed class CachedEnumerator<T> : IEnumerator<T>
{
CachedEnumerable<T> _CachedEnumerable;
const int InitialIndex = -1;
const int EofIndex = -2;
int _Index = InitialIndex;
public CachedEnumerator(CachedEnumerable<T> cachedEnumerable)
{
_CachedEnumerable = cachedEnumerable;
}
public T Current
{
get
{
var cachedEnumerable = _CachedEnumerable;
if (cachedEnumerable == null)
throw new InvalidOperationException();
var index = _Index;
if (index < 0)
throw new InvalidOperationException();
return cachedEnumerable.GetCacheItem(index);
}
}
object IEnumerator.Current => Current;
public void Dispose()
{
_CachedEnumerable = null;
}
public bool MoveNext()
{
var cachedEnumerable = _CachedEnumerable;
if (cachedEnumerable == null)
{
// Disposed.
return false;
}
if (_Index == EofIndex)
return false;
_Index++;
if (!cachedEnumerable.EnsureItemIsCached(_Index))
{
_Index = EofIndex;
return false;
}
else
{
return true;
}
}
public void Reset()
{
_Index = InitialIndex;
}
}
}
More info and a readily available NuGet package: https://github.com/gapotchenko/Gapotchenko.FX/tree/master/Source/Gapotchenko.FX.Linq#memoize
I have an IObservable<string> and several observers that handle strings based on some condition:
observable.Subscribe(s => { if (s.StartsWith("a")) {...} });
observable.Subscribe(s => { if (s.StartsWith("b")) {...} });
observable.Subscribe(s => { if (s.StartsWith("c")) {...} });
observable.Subscribe(s => { if (s.StartsWith("d")) {...} });
....
This is a simplified example (the condition is more complex and the observed events aren't strings) but you get the idea.
I'd like to have an IObserver<string> that catches all strings that are not handled by any other observer. Observers with different conditions (i.e.: StartsWith("e")) can be added at any time and the set of conditions does not overlap.
Is this scenario somehow supported? Or do I have to mark observed strings as handled and subscribe to unhandled strings once all other observers have tried (and how do I implement that)?
I've got two approaches.
The first provides a way to chain together the predicate/action pairs to "syphon" off values that match. It follows the Rx operator style.
I can write this:
observable
.Syphon(s => s.StartsWith("a"), s => { })
.Syphon(s => s.StartsWith("b"), s => { })
.Syphon(s => s.StartsWith("c"), s => { })
.Syphon(s => s.StartsWith("d"), s => { })
.Subscribe(s => { /* otherwise */ });
If I have this extension method:
public static IObservable<T> Syphon<T>(
this IObservable<T> source,
Func<T, bool> predicate,
Action<T> action)
{
if (source == null) throw new ArgumentNullException("source");
if (predicate == null) throw new ArgumentNullException("predicate");
if (action == null) throw new ArgumentNullException("action");
return Observable.Create<T>(o =>
source.Subscribe(
t =>
{
if (predicate(t))
{
action(t);
}
else
{
o.OnNext(t);
}
},
ex =>
o.OnError(ex),
() =>
o.OnCompleted()));
}
It doesn't allow you to add and remove predicate/action pairs on the fly, but it is a fairly simple operator that might be useful.
To have the full add/remove functionality I have come up with this approach:
Func<Func<string, bool>, Action<string>, IDisposable> add;
observable
.Syphon(out add)
.Subscribe(s => { /* otherwise */ });
var startsWithA = add(s => s.StartsWith("a"), s => { /* a */ });
var startsWithB = add(s => s.StartsWith("b"), s => { /* b */ });
startsWithA.Dispose();
var startsWithC = add(s => s.StartsWith("c"), s => { /* c */ });
var startsWithD = add(s => s.StartsWith("d"), s => { /* d */ });
startsWithC.Dispose();
startsWithB.Dispose();
startsWithD.Dispose();
The .Syphon(out add) extension method overload allows the method to effectively return two results - the normal return value is the IObservable<T> and the second comes out as a Func<Func<T, bool>, Action<T>, IDisposable>. This second return value allows new predicate/action pairs to be added to the syphon operator and then removed by calling Dispose on the returned subscription - very Rx-ish.
Here's the extension method:
public static IObservable<T> Syphon<T>(
this IObservable<T> source,
out Func<Func<T, bool>, Action<T>, IDisposable> subscriber)
{
if (source == null) throw new ArgumentNullException("source");
var pas = new List<Tuple<Func<T, bool>, Action<T>>>();
subscriber = (p, a) =>
{
lock (pas)
{
var tuple = Tuple.Create(p, a);
pas.Add(tuple);
return Disposable.Create(() =>
{
lock (pas)
{
pas.Remove(tuple);
}
});
}
};
return Observable.Create<T>(o =>
source.Subscribe(
t =>
{
Action<T> a = null;
lock (pas)
{
var pa = pas.FirstOrDefault(x => x.Item1(t));
if (pa != null)
{
a = pa.Item2;
}
}
if (a != null)
{
a(t);
}
else
{
o.OnNext(t);
}
},
ex =>
o.OnError(ex),
() =>
o.OnCompleted()));
}
I tested the code with this:
var xs = Observable.Interval(TimeSpan.FromSeconds(0.2));
Func<Func<long, bool>, Action<long>, IDisposable> subscriber;
xs
.Syphon(out subscriber)
.Subscribe(x => Console.WriteLine(x));
var divBy3 = subscriber(
x => x % 3 == 0,
x => Console.WriteLine("divBy3"));
Thread.Sleep(2000);
var divBy2 = subscriber(
x => x % 2 == 0,
x => Console.WriteLine("divBy2"));
Thread.Sleep(2000);
divBy3.Dispose();
Thread.Sleep(2000);
divBy2.Dispose();
Thread.Sleep(10000);
And it produced:
divBy3
1
2
divBy3
4
5
divBy3
7
8
divBy3
divBy2
11
divBy3
13
divBy2
divBy3
divBy2
17
divBy3
19
divBy2
21
divBy2
23
divBy2
25
divBy2
27
divBy2
29
30
31
32
...
And that seemed right. Let me know if this solves it for you.
One option is to make your subscribers to be observable as well. So what these subscribers does is if that they don't handle the value then they emit it through their observable interface and then the last subscriber (that handle all not used values) will be a single ton object that subscribes to each of the observable interface of the other subscribers. Something like:
public class MyObserver : IObserver<string>, IObservable<string>
{
Subject<string> s = new Subject<string>();
public MyObserver(IObserver<string> obs)
{
s.Subscribe(obs);
}
public void OnCompleted()
{ }
public void OnError(Exception error)
{ }
public void OnNext(string value)
{
//If condition matches then else dont do on next
s.OnNext(value);
}
public IDisposable Subscribe(IObserver<string> observer)
{
return s.Subscribe(observer);
}
}
public class LastObserver : IObserver<string>
{
public void OnCompleted()
{ }
public void OnError(Exception error)
{ }
public void OnNext(string value)
{ //Do something with not catched value
}
}
static LastObserver obs = new LastObserver();
static void Main()
{
var timer = Observable.Interval(TimeSpan.FromSeconds(1)).Select(i => i.ToString());
timer.Subscribe(new MyObserver(obs));
timer.Subscribe(new MyObserver(obs));
timer.Subscribe(new MyObserver(obs));
}
I don't know of any out of the box way to do this but I would do it as under
class ConditionAction
{
public Predicate<string> Condition {get; set; }
public Action<string> Action {get; set; }
}
var conditions = new ConditionAction[]{action1, action2, action3};
foreach (var condition in conditions)
observable.Where(condition.Condition).Subscribe(condition.Action);
.....
observable.Where(s=>!conditions.Any(c=>c.Condition(s))).Subscribe(...);
I'm using some functional stuff in C# and keep getting stuck on the fact that List.Add doesn't return the updated list.
In general, I'd like to call a function on an object and then return the updated object.
For example it would be great if C# had a comma operator:
((accum, data) => accum.Add(data), accum)
I could write my own "comma operator" like this:
static T comma(Action a, Func<T> result) {
a();
return result();
}
It looks like it would work but the call site would ugly. My first example would be something like:
((accum, data) => comma(accum.Add(data), ()=>accum))
Enough examples! What's the cleanest way to do this without another developer coming along later and wrinkling his or her nose at the code smell?
I know this as Fluent.
A Fluent example of a List.Add using Extension Methods
static List<T> MyAdd<T>(this List<T> list, T element)
{
list.Add(element);
return list;
}
I know that this thread is very old, but I want to append the following information for future users:
There isn't currently such an operator. During the C# 6 development cycle a semicolon operator was added, as:
int square = (int x = int.Parse(Console.ReadLine()); Console.WriteLine(x - 2); x * x);
which can be translated as follows:
int square = compiler_generated_Function();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int compiler_generated_Function()
{
int x = int.Parse(Console.ReadLine());
Console.WriteLine(x - 2);
return x * x;
}
However, this feature was dropped before the final C# release.
You can do almost exactly the first example naturally using code blocks in C# 3.0.
((accum, data) => { accum.Add(data); return accum; })
This is what Concat http://msdn.microsoft.com/en-us/library/vstudio/bb302894%28v=vs.100%29.aspx is for. Just wrap a single item in an array. Functional code should not mutate the original data. If performance is a concern, and this isn't good enough, then you'll no longer be using the functional paradigm.
((accum, data) => accum.Concat(new[]{data}))
Another technique, straight from functional programming, is as follows. Define an IO struct like this:
/// <summary>TODO</summary>
public struct IO<TSource> : IEquatable<IO<TSource>> {
/// <summary>Create a new instance of the class.</summary>
public IO(Func<TSource> functor) : this() { _functor = functor; }
/// <summary>Invokes the internal functor, returning the result.</summary>
public TSource Invoke() => (_functor | Default)();
/// <summary>Returns true exactly when the contained functor is not null.</summary>
public bool HasValue => _functor != null;
X<Func<TSource>> _functor { get; }
static Func<TSource> Default => null;
}
and make it a LINQ-able monad with these extension methods:
[SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces")]
public static class IO {
public static IO<TSource> ToIO<TSource>( this Func<TSource> source) {
source.ContractedNotNull(nameof(source));
return new IO<TSource>(source);
}
public static IO<TResult> Select<TSource,TResult>(this IO<TSource> #this,
Func<TSource,TResult> projector
) =>
#this.HasValue && projector!=null
? New(() => projector(#this.Invoke()))
: Null<TResult>();
public static IO<TResult> SelectMany<TSource,TResult>(this IO<TSource> #this,
Func<TSource,IO<TResult>> selector
) =>
#this.HasValue && selector!=null
? New(() => selector(#this.Invoke()).Invoke())
: Null<TResult>();
public static IO<TResult> SelectMany<TSource,T,TResult>(this IO<TSource> #this,
Func<TSource, IO<T>> selector,
Func<TSource,T,TResult> projector
) =>
#this.HasValue && selector!=null && projector!=null
? New(() => { var s = #this.Invoke(); return projector(s, selector(s).Invoke()); } )
: Null<TResult>();
public static IO<TResult> New<TResult> (Func<TResult> functor) => new IO<TResult>(functor);
private static IO<TResult> Null<TResult>() => new IO<TResult>(null);
}
and now you can use the LINQ comprehensive syntax thus:
using Xunit;
[Fact]
public static void IOTest() {
bool isExecuted1 = false;
bool isExecuted2 = false;
bool isExecuted3 = false;
bool isExecuted4 = false;
IO<int> one = new IO<int>( () => { isExecuted1 = true; return 1; });
IO<int> two = new IO<int>( () => { isExecuted2 = true; return 2; });
Func<int, IO<int>> addOne = x => { isExecuted3 = true; return (x + 1).ToIO(); };
Func<int, Func<int, IO<int>>> add = x => y => { isExecuted4 = true; return (x + y).ToIO(); };
var query1 = ( from x in one
from y in two
from z in addOne(y)
from _ in "abc".ToIO()
let addOne2 = add(x)
select addOne2(z)
);
Assert.False(isExecuted1); // Laziness.
Assert.False(isExecuted2); // Laziness.
Assert.False(isExecuted3); // Laziness.
Assert.False(isExecuted4); // Laziness.
int lhs = 1 + 2 + 1;
int rhs = query1.Invoke().Invoke();
Assert.Equal(lhs, rhs); // Execution.
Assert.True(isExecuted1);
Assert.True(isExecuted2);
Assert.True(isExecuted3);
Assert.True(isExecuted4);
}
When one desires an IO monad that composes but returns only void, define this struct and dependent methods:
public struct Unit : IEquatable<Unit>, IComparable<Unit> {
[CLSCompliant(false)]
public static Unit _ { get { return _this; } } static Unit _this = new Unit();
}
public static IO<Unit> ConsoleWrite(object arg) =>
ReturnIOUnit(() => Write(arg));
public static IO<Unit> ConsoleWriteLine(string value) =>
ReturnIOUnit(() => WriteLine(value));
public static IO<ConsoleKeyInfo> ConsoleReadKey() => new IO<ConsoleKeyInfo>(() => ReadKey());
which readily allow the writing of code fragments like this:
from pass in Enumerable.Range(0, int.MaxValue)
let counter = Readers.Counter(0)
select ( from state in gcdStartStates
where _predicate(pass, counter())
select state )
into enumerable
where ( from _ in Gcd.Run(enumerable.ToList()).ToIO()
from __ in ConsoleWrite(Prompt(mode))
from c in ConsoleReadKey()
from ___ in ConsoleWriteLine()
select c.KeyChar.ToUpper() == 'Q'
).Invoke()
select 0;
where the old C comma operator is readily recognized for what it is: a monadic compose operation.
The true merit of the comprehension syntax is apparent when one attempts to write that fragment in the flunt style:
( Enumerable.Range(0,int.MaxValue)
.Select(pass => new {pass, counter = Readers.Counter(0)})
.Select(_ => gcdStartStates.Where(state => _predicate(_.pass,_.counter()))
.Select(state => state)
)
).Where(enumerable =>
( (Gcd.Run(enumerable.ToList()) ).ToIO()
.SelectMany(_ => ConsoleWrite(Prompt(mode)),(_,__) => new {})
.SelectMany(_ => ConsoleReadKey(), (_, c) => new {c})
.SelectMany(_ => ConsoleWriteLine(), (_,__) => _.c.KeyChar.ToUpper() == 'Q')
).Invoke()
).Select(list => 0);
The extension method is arguably the best solution, but for completeness' sake, don't forget the obvious alternative: a wrapper class.
public class FList<T> : List<T>
{
public new FList<T> Add(T item)
{
base.Add(item);
return this;
}
public new FList<T> RemoveAt(int index)
{
base.RemoveAt(index);
return this;
}
// etc...
}
{
var list = new FList<string>();
list.Add("foo").Add("remove me").Add("bar").RemoveAt(1);
}
I thought it would be interesting to make a version of my wrapper class answer that doesn't require you write the wrapper methods.
public class FList<T> : List<T>
{
public FList<T> Do(string method, params object[] args)
{
var methodInfo = GetType().GetMethod(method);
if (methodInfo == null)
throw new InvalidOperationException("I have no " + method + " method.");
if (methodInfo.ReturnType != typeof(void))
throw new InvalidOperationException("I'm only meant for void methods.");
methodInfo.Invoke(this, args);
return this;
}
}
{
var list = new FList<string>();
list.Do("Add", "foo")
.Do("Add", "remove me")
.Do("Add", "bar")
.Do("RemoveAt", 1)
.Do("Insert", 1, "replacement");
foreach (var item in list)
Console.WriteLine(item);
}
Output:
foo
replacement
bar
EDIT
You can slim down the syntax by exploiting C# indexed properties.
Simply add this method:
public FList<T> this[string method, params object[] args]
{
get { return Do(method, args); }
}
And the call now looks like:
list = list["Add", "foo"]
["Add", "remove me"]
["Add", "bar"]
["RemoveAt", 1]
["Insert", 1, "replacement"];
With the linebreaks being optional, of course.
Just a bit of fun hacking the syntax.
I'd like to declare an "empty" lambda expression that does, well, nothing.
Is there a way to do something like this without needing the DoNothing() method?
public MyViewModel()
{
SomeMenuCommand = new RelayCommand(
x => DoNothing(),
x => CanSomeMenuCommandExecute());
}
private void DoNothing()
{
}
private bool CanSomeMenuCommandExecute()
{
// this depends on my mood
}
My intent in doing this is only control the enabled/disabled state of my WPF command, but that's an aside. Maybe it's just too early in the morning for me, but I imagine there must be a way to just declare the x => DoNothing() lambda expression in some way like this to accomplish the same thing:
SomeMenuCommand = new RelayCommand(
x => (),
x => CanSomeMenuCommandExecute());
Is there some way to do this? It just seems unnecessary to need a do-nothing method.
Action doNothing = () => { };
I thought I would add some code that I've found useful for this type of situation. I have an Actions static class and a Functions static class with some basic functions in them:
public static class Actions
{
public static void Empty() { }
public static void Empty<T>(T value) { }
public static void Empty<T1, T2>(T1 value1, T2 value2) { }
/* Put as many overloads as you want */
}
public static class Functions
{
public static T Identity<T>(T value) { return value; }
public static T0 Default<T0>() { return default(T0); }
public static T0 Default<T1, T0>(T1 value1) { return default(T0); }
/* Put as many overloads as you want */
/* Some other potential methods */
public static bool IsNull<T>(T entity) where T : class { return entity == null; }
public static bool IsNonNull<T>(T entity) where T : class { return entity != null; }
/* Put as many overloads for True and False as you want */
public static bool True<T>(T entity) { return true; }
public static bool False<T>(T entity) { return false; }
}
I believe this helps improve readability just a tiny bit:
SomeMenuCommand = new RelayCommand(
Actions.Empty,
x => CanSomeMenuCommandExecute());
// Another example:
var lOrderedStrings = GetCollectionOfStrings().OrderBy(Functions.Identity);
This should work:
SomeMenuCommand = new RelayCommand(
x => {},
x => CanSomeMenuCommandExecute());
Assuming you only need a delegate (rather than an expression tree) then this should work:
SomeMenuCommand = new RelayCommand(
x => {},
x => CanSomeMenuCommandExecute());
(That won't work with expression trees as it's got a statement body. See section 4.6 of the C# 3.0 spec for more details.)
I don't fully understand why do you need a DoNothing method.
Can't you just do:
SomeMenuCommand = new RelayCommand(
null,
x => CanSomeMenuCommandExecute());
Action DoNothing = delegate { };
Action DoNothing2 = () => {};
I used to initialize Events to a do nothing action so it was not null and if it was called without subscription it would default to the 'do nothing function' instead of a null-pointer exception.
public event EventHandler<MyHandlerInfo> MyHandlerInfo = delegate { };
Starting with C# 9.0 you can specify discards _ for required parameters. Example:
Action<int, string, DateTime> action = (_, _, _) => { };