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(...);
Related
I'm working on some old code that does not have IAsyncEnumerable, so I was trying to mimic IAsyncEnumerable behavior with IObservable. The issue is that IObservable is push-based and is giving results in random order.
Here is a very simplified version of what I want to achieve
public static class Program
{
public static void Main()
{
Test().Wait();
Console.ReadLine();
}
private static async Task Test()
{
var l = await GetFirstObservable()
.SelectMany(i =>
{
return GetSecondObservable()
.Select(s => Tuple.Create(i, s));
})
.Take(3)
.ToList();
foreach (var item in l)
{
Console.WriteLine(item);
}
}
private static async Task<T> Echo<T>(T value)
{
Console.WriteLine(value);
await Task.Delay(1);
return value;
}
private static IObservable<int> GetFirstObservable()
{
return Observable.Create(async (IObserver<int> observer, CancellationToken cancellationToken) =>
{
foreach (var i in new [] {1, 2, 3})
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
var e = await Echo(i);
if (cancellationToken.IsCancellationRequested)
{
return;
}
observer.OnNext(e);
}
});
}
private static IObservable<string> GetSecondObservable()
{
return Observable.Create(async (IObserver<string> observer, CancellationToken cancellationToken) =>
{
foreach (var i in new[] { "A", "B" })
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
var e = await Echo(i);
if (cancellationToken.IsCancellationRequested)
{
return;
}
observer.OnNext(i);
}
});
}
}
I want the following results to be in console:
1
A
B
2
A
(1, A)
(1, B)
(2, A)
Instead, the first observable does not wait for the second observable to complete, and I get random results like:
1
A
2
A
3
B
A
B
(1, A)
(2, A)
(1, B)
Is it even possible to achieve this pull-like behavior, or should I just look for something else?
How I can write this code with a single line?
public class RadGridColumnObservable
{
public RadGridColumnObservable(RadGridView grid, IMessageBus messageBus)
{
this.grid = grid;
this.messageBus = messageBus;
}
public IDisposable Initialize()
{
CreateStates();
return Observable
.Interval(TimeSpan.FromSeconds(1))
.Subscribe(_ => CheckUp());
}
//
private readonly RadGridView grid;
private readonly IMessageBus messageBus;
private readonly List<bool> states = new List<bool>();
//
private void CreateStates()
{
states.Clear();
states.AddRange(grid.Columns.Select(it => it.IsVisible));
}
private void CheckUp()
{
if (states.SequenceEqual(grid.Columns.Select(it => it.IsVisible))) return;
CreateStates();
messageBus.Publish(new NotifyMessage(MessageTypes.HistoryColumnsChanged));
}
}
The idea is: I want to check if the IsVisible property is changed.
I don't like to use this line:
private readonly List<bool> states = new List<bool>();
You could get your IsVisible values with something like this:
private IObservable<List<bool>> CreateStatesObservable()
{
return Observable.Interval(TimeSpan.FromSeconds(1))
.Select(_ => grid.Columns.Select(it => it.IsVisible));
}
And then use Scan to keep track of your previous value:
public void Initialize()
{
var observable =
CreateStatesObservable()
.Scan(
(prev: default(List<bool>), actual: default(List<bool>)),
(acc, c) => (acc.actual, current))
.Where(values => !values.actual.SequenceEqual(values.prev))
.Select(_ => true);
}
Or you could use Defer and do something like this:
public void Initialize2()
{
var observable = CreateStatesObservable();
var deferred =
Observable.Defer(
() =>
{
List<bool> previous = null;
return observable.Select(
values =>
{
if (previous is null)
{
previous = values;
return false;
}
if (!values.SequenceEqual(previous))
{
previous = values;
return true;
}
return false;
});
})
.Where(value => value);
}
Both options should give you an observable which only produces a value when one of the columns IsVisible has changed. (That value just being a true)
Edit:
You can also use DistinctUntilChanged() with your own IEqualityComparer like this:
class ListComparer : IEqualityComparer<List<bool>>
{
bool IEqualityComparer<List<bool>>.Equals(List<bool>? a, List<bool>? b)
{
if (a is null && b is null)
{
return true;
}
if (a is null || b is null)
{
return false;
}
return a.SequenceEqual(b);
}
int IEqualityComparer<List<bool>>.GetHashCode(List<bool> obj)
{
return obj.GetHashCode();
}
}
And then use it like this:
public void Initialize()
{
var observable =
CreateStatesObservable()
.DistinctUntilChanged(new ListComparer())
.Select(_ => true);
}
I think you can adjust your Initialize() to something like this:
public IDisposable Initialize()
{
return Observable
.Interval(TimeSpan.FromSeconds(1))
.Select(v => grid.Columns.Select(it => it.IsVisible).ToList())
.Scan((prev: new List<bool>(), actual: new List<bool>()),
(acc, c) => (acc.actual, c))
.Where(it => !it.actual.SequenceEqual(it.prev))
.Subscribe(_ => messageBus.Publish(new NotifyMessage(MessageTypes.HistoryColumnsChanged)));
}
This should give you the same result and you only need SequenceEqual() once. The scan is just there so you have the "current" and the "previous" value. You don't really need to do a check inside it in your case.
I use now something like this:
public class RadGridColumnObservable
{
public RadGridColumnObservable(RadGridView grid, IMessageBus messageBus)
{
this.grid = grid;
this.messageBus = messageBus;
}
public IDisposable Initialize()
{
return Observable
.Interval(TimeSpan.FromSeconds(1))
.Scan((prev: grid.Columns.Select(it => it.IsVisible).ToList(), actual: grid.Columns.Select(it => it.IsVisible).ToList()),
(acc, c) =>
{
if (!acc.prev.SequenceEqual(acc.actual))
acc.prev = acc.actual;
acc.actual = grid.Columns.Select(it => it.IsVisible).ToList();
return acc;
})
.Where(it => !it.prev.SequenceEqual(it.actual))
.Subscribe(it => messageBus.Publish(new NotifyMessage(MessageTypes.HistoryColumnsChanged)));
}
//
private readonly RadGridView grid;
private readonly IMessageBus messageBus;
}
but i don't like because i use 2nd time "SequenceEqual".
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);
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'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.