New type: Iterator - a safe IEnumerator #1431
louthy
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Language-ext gained
Iterable
a few months back, which is a functional wrapper forIEnumerable
. We now haveIterator
, which is a more functional wrapper forIEnumerator
.IEnumerator
is particularly problematic due to its mutable nature. It makes it impossible to share or leverage safely within other immutable types.For any type where you could previously call
GetEnumerator()
, it is now possible to callGetIterator()
.Iterator
is pattern-matchable, so you can use the standard FP sequence processing technique:Or, bog standard imperative processing:
You need to be a little careful when processing large lists or infinite streams..
Iterator<A>
usesIterator<A>.Cons
andIterator<A>.Nil
types to describe a linked-list of values. That linked-list requires an allocated object per item. That is not really a problem for most of us that want correctness over outright performance, it is a small overhead. But, the other side-effect of this is that if you hold a reference to the head item of a sequence and you're processing an infinite sequence, then those temporary objects won't be freed by the GC. Causing a space leak.This will cause a space-leak:
first
references the firstIterator<A>.Cons
and every subsequent item via theTail
.This (below) is OK because the
iter
reference keeps being overwritten, which means nothing is holding on theHead
item in the sequence:This type is probably more useful for me when implementing the various core types of language-ext, but I can't be the only person who's struggled with
IEnumerator
and its horrendous design.A good example of where I am personally already seeing the benefits is
IO<A>.RetryUntil
.This is the original version:
Notice the
foreach
in there and the manual running of the item to retry withRunAsync
. This has to go all imperative because there previously was no way to safely get theIEnumerator
ofSchedule.Run()
and pass it around.This is what
RetryUntil
looks like now:Entirely functional, no imperative anything, and even (potentially) infinitely recursive depending on the
Schedule
. There's also no manual running of theIO
monad withRunAsync
, which means we benefit from all of the DSL work on optimising away theasync/await
machinery.Future:
Iterator
inStreamT
Iterator
in PipesIteratorT
(although this would likely just beStreamT
, so maybe a renaming)This discussion was created from the release New type: Iterator - a safe IEnumerator.
Beta Was this translation helpful? Give feedback.
All reactions