Skip to content

Instantly share code, notes, and snippets.

@daxfohl
Created October 18, 2011 22:46
Show Gist options
  • Save daxfohl/1296973 to your computer and use it in GitHub Desktop.
Save daxfohl/1296973 to your computer and use it in GitHub Desktop.
Purely Functional Events
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