ElvisLives / morelinq

Automatically exported from code.google.com/p/morelinq
Apache License 2.0
0 stars 0 forks source link

New method: Sequence.Traverse #14

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Sequence.Generate is able to traverse linked lists of reference types, but
it produces an infinite list and also doesn't check for null (nor
should/could it, generally speaking).

So it has to be used in a boilerplate idiom where it is combined with
TakeWhile, e.g.

Exception innermost = Sequence.Generate(caught, e =>
e.InnerException).While(e => e != null).Last();

The name Generate then becomes a little misleading, as we are not
generating a new list but traversing an existing list.

Also it is a bit counter-intuitive to have the check for null termination
appearing after the Generate call - perfectly safe due to the laziness, but
it looks dodgy.

Given the usefulness of this pattern, and the fact that we are not really
generating anything, it might make sense to make it a separate method
called Traverse, limited of course to reference types:

public static IEnumerable<TResult> Traverse<TResult>(TResult initial,
Func<TResult, TResult> generator) where TResult : class
{
    for (TResult current = initial; current != null; current =
generator(current))
        yield return current;
}

Original issue reported on code.google.com by daniel.e...@gmail.com on 10 Mar 2009 at 11:18

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
About to delete my previous comment, which was unnecessarily wordy...

A few notes...

1) There is a concept from functional programming called an "unfold", which is 
the
projection of a single entity into a collection via a repeated or recursive
operation.  Our Generate method in its current form is a special case of the 
"unfold"
operation.  It supports value-based unfolding well, but when you start working 
with
more complex objects, usability breaks down.

2) An "unfold" on complex objects is much more of a graph transformation 
operation
than a querying/filtering operation.  So far, LINQ itself as well as MoreLinq 
have
been focused on querying and filtering.  It may be that the more general 
"unfold" is
useful, but more appropriately bundled with similar functionality.  FWIW, I 
would
argue that querying/filtering is a special case of graph transformation, and a
querying/filtering DSL (even up to and including SQL itself) could benefit 
greatly
from access to more general graph transformation operations.  But MoreLinq may 
not be
the place to start providing this.

3) The "Generate" name pairs up well with its inverse operation provided in the 
.NET
Framework v3.5: "Aggregate".  Were we working in a functional environment 
rather than
procedural, these would probably be called "Unfold" and "Fold", respectively.  
But
since we can't change "Aggregate", I'm in favor of keeping the "Generate" name 
or
something similarly untuitively connected to "Aggregate".

Original comment by CAmmerman@gmail.com on 10 Mar 2009 at 11:49

GoogleCodeExporter commented 9 years ago
No problem. I only just noticed Jared Parson has put together a lot of his 
excellent work on 
functional/immutable coding as a library called BclExtras on the MSDN code 
gallery. It has a lot of interesting 
stuff and looks a little closer to what I was looking for - it sounds like you 
have a specific plan for what MoreLinq 
will cover.

Original comment by daniel.e...@gmail.com on 21 Mar 2009 at 9:54

GoogleCodeExporter commented 9 years ago

Original comment by azizatif on 4 Apr 2009 at 7:28