Created
October 18, 2011 22:46
-
-
Save daxfohl/1296973 to your computer and use it in GitHub Desktop.
Purely Functional Events
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace SubjWorldValue { | |
class Program { | |
static void Main() { | |
var uim = new UIM(); | |
//var uim2 = uim.AddListenerx(w => w.BPM, (w, i) => w.Set(w1 => w1.Resp, i)); | |
var uim2 = uim.AddBPMListener((w, i) => w.SetResp(i)); | |
var uim3 = uim2.Set(w => w.BPM, 5); | |
var uim4 = uim.Set(w => w.BPM, 5); | |
Console.WriteLine(uim3.Resp.Value); | |
Console.WriteLine(uim4.Resp.Value); | |
} | |
} | |
public class UIM { | |
public readonly Subj<UIM, int> BPM; | |
public readonly Subj<UIM, int> Resp; | |
public UIM() { | |
BPM = new Subj<UIM, int>(0, (bpm, uim) => new UIM(bpm, Resp)); | |
Resp = new Subj<UIM, int>(0, (resp, uim) => new UIM(BPM, resp)); | |
} | |
UIM(Subj<UIM, int> bpm, Subj<UIM, int> resp) { | |
BPM = bpm; | |
Resp = resp; | |
} | |
public UIM AddBPMListener(Func<UIM, int, UIM> setter) { | |
return BPM.AddListener(uim => setter(uim, uim.BPM.Value), this); | |
} | |
public UIM SetResp(int i) { | |
return Resp.SetValue(i, this); | |
} | |
} | |
public static class WorldEx { | |
public static TWorld Set<TWorld, TValue>(this TWorld world, Func<TWorld, Subj<TWorld, TValue>> fSubj, TValue value) { | |
return fSubj(world).SetValue(value, world); | |
} | |
public static TWorld AddListenerx<TWorld, TValue>(this TWorld world, Func<TWorld, Subj<TWorld, TValue>> fSubj, Func<TWorld, TWorld> listener) { | |
return fSubj(world).AddListener(listener, world); | |
} | |
public static TWorld AddListenerx<TWorld, TValue>(this TWorld world, Func<TWorld, Subj<TWorld, TValue>> fSubj, Func<TWorld, TValue, TWorld> setter) { | |
return world.AddListenerx(fSubj, w => setter(w, fSubj(w).Value)); | |
} | |
} | |
public class Subj<TWorld, TValue> { | |
public readonly TValue Value; | |
readonly IEnumerable<Func<TWorld, TWorld>> _listeners; | |
readonly Func<Subj<TWorld, TValue>, TWorld, TWorld> _updater; | |
public Subj(TValue value, IEnumerable<Func<TWorld, TWorld>> listeners, Func<Subj<TWorld, TValue>, TWorld, TWorld> updater) { | |
Value = value; | |
_updater = updater; | |
_listeners = listeners; | |
} | |
public Subj(TValue value, Func<Subj<TWorld, TValue>, TWorld, TWorld> updater) | |
: this(value, Enumerable.Empty<Func<TWorld, TWorld>>(), updater) { } | |
public TWorld SetValue(TValue value, TWorld world) { | |
return _listeners.Aggregate(_updater(new Subj<TWorld, TValue>(value, _listeners, _updater), world), (world1, listener) => listener(world1)); | |
} | |
public TWorld AddListener(Func<TWorld, TWorld> listener, TWorld world) { | |
return _updater(new Subj<TWorld, TValue>(Value, _listeners.Concat(new[] { listener }), _updater), world); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment