Hi,
After some reading through the sources of Sodium (mainly C# (but I guess it's same as Java), TypeScript (the one with different approach in this area) and Haskell), I still haven't got a clear picture of what are the main issues when it comes to managing memory and dependencies and what are the means to mitigate them. Let's follow couple of examples:
StreamSink<int> s = new StreamSink<int>();
Stream<string> m = s.Map(x => (x + 2).ToString());
List<string> @out = new List<string>();
using (m.Listen(@out.Add))
{
s.Send(5);
}
In this case, the method Listen
essentially just return a function that can be used to unlisten (here, it takes a form of IDisposable
). But what happens if I don't dispose it, and instead clear the reference to to s, effectively losing a way to push an event into the system? Does WeakReference machinery helps here, and what's the situation in TypeScript version?
Cell<A> a1 = ...;
Cell<A> a2 = ...;
Stream<Unit> sChange = ...;
Cell<A> a = Cell.switchC(sChange.map(u -> a2).hold(a1));
(this is the example from https://github.com/SodiumFRP/sodium/issues/85#issuecomment-191948042)
In that comment, it's mentioned that "In this example we'd need to make sure the lambda u -> a2 kept a2
(which could be a whole chain of FRP logic) alive.", but later on, it's also mentioned that a2
is kept alive by the fact the closure u -> a2
is kept alive by the map operation. So I'm not sure what's the goal here - is it the need to keep something alive that would normally be garbage collected (but why), or is the goal here as usual, to not keep something alive more than it should...and how it's achieved (in both, C#/Java and TypeScript version)?
Thanks in advance, I hope to make this discussion clean and concise to avoid hand wavy descriptions and instead focus on simple examples, or maybe even references for such future discussions.