Last active
October 6, 2019 13:38
-
-
Save ZacharyPatten/aa5f923c383334b76a43c94fc530ec87 to your computer and use it in GitHub Desktop.
This shows an alternative methodology to System.Collections.Generic.IEnumerable<T> that uses delegates for enumeration rather than an enumerator.
This file contains hidden or 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 Towel; | |
| using static Towel.Syntax; | |
| namespace Example | |
| { | |
| class Program | |
| { | |
| static void Main(string[] args) | |
| { | |
| // This code is a snippet from the https://github.com/ZacharyPatten/Towel project. | |
| // Please check out the project if you want to see more code like it. :) | |
| /// NOTE: There are pros/cons to both the IEnumerable<T> and Stepper<T> | |
| /// methodologies. This Gist is only to demonstrate/introduce delegate | |
| /// traversals (not compare them in detail). | |
| IEnumerable<int> iEnumerable = new int[] { 1, 2, 3, }; | |
| Console.Write(" iEnumerable values:"); | |
| foreach (int value in iEnumerable) | |
| { | |
| Console.Write(" " + value); | |
| } | |
| Console.WriteLine(); | |
| Stepper<int> stepper = new int[] { 1, 2, 3, }.ToStepper(); | |
| Console.Write(" stepper values:"); | |
| stepper(value => Console.Write(" " + value)); | |
| Console.WriteLine(); | |
| /// You can "break" a foreach loop, but you cannot break a stepper traversal. | |
| /// For this, there is another type of stepper that is breakable. "Towel.StepperBreak<T>" | |
| /// is a breakable version of the stepper. | |
| StepperBreak<int> stepperBreak = new int[] { 1, 2, 3, 4, 5, 6, }.ToStepperBreak(); | |
| Console.Write(" stepperBreak values:"); | |
| stepperBreak(value => | |
| { | |
| Console.Write(" " + value); | |
| return value >= 3 ? Break : Continue; | |
| }); | |
| Console.WriteLine(); | |
| /// You cannot alter the values of an IEnumerable<T> during iteration, however, | |
| /// you can do so with a "Towel.StepperRef<T>". | |
| StepperRef<int> stepperRef = new int[] { 0, 1, 2, }.ToStepperRef(); | |
| Console.Write(" stepperRef values:"); | |
| stepperRef((ref int value) => | |
| { | |
| value++; | |
| Console.Write(" " + value); | |
| }); | |
| Console.WriteLine(); | |
| /// The "Towel.StepperRefBreak<T>" is a stepper type that allows for altering | |
| /// values and breaking iteration. | |
| StepperRefBreak<int> stepperRefBreak = new int[] { 0, 1, 2, 3, 4, 5, }.ToStepperRefBreak(); | |
| Console.Write(" stepperRefBreak values:"); | |
| stepperRefBreak((ref int value) => | |
| { | |
| value++; | |
| Console.Write(" " + value); | |
| return value >= 3 ? Break : Continue; | |
| }); | |
| Console.WriteLine(); | |
| /// Here is an example of creating a stepper from only functions (no backing | |
| /// data structure). | |
| Stepper<int> stepperFunctional = s => { s(1); s(2); s(3); }; | |
| Console.Write(" stepperFunctional values:"); | |
| stepperFunctional(value => Console.Write(" " + value)); | |
| } | |
| } | |
| } | |
| namespace Towel | |
| { | |
| public delegate void Step<T>(T x); | |
| public delegate void StepRef<T>(ref T x); | |
| public delegate StepStatus StepBreak<T>(T x); | |
| public delegate StepStatus StepRefBreak<T>(ref T x); | |
| public delegate void Stepper<T>(Step<T> step); | |
| public delegate void StepperRef<T>(StepRef<T> step); | |
| public delegate StepStatus StepperBreak<T>(StepBreak<T> step); | |
| public delegate StepStatus StepperRefBreak<T>(StepRefBreak<T> step); | |
| public enum StepStatus | |
| { | |
| Continue = 0, | |
| Break = 1, | |
| }; | |
| public static class Syntax | |
| { | |
| public const StepStatus Continue = StepStatus.Continue; | |
| public const StepStatus Break = StepStatus.Break; | |
| } | |
| public static class Stepper | |
| { | |
| public static Stepper<T> ToStepper<T>(this IEnumerable<T> iEnumerable) => | |
| step => | |
| { | |
| foreach (T value in iEnumerable) | |
| { | |
| step(value); | |
| } | |
| }; | |
| public static StepperBreak<T> ToStepperBreak<T>(this IEnumerable<T> iEnumerable) => | |
| step => | |
| { | |
| foreach (T value in iEnumerable) | |
| { | |
| if (step(value) == Break) | |
| { | |
| return Break; | |
| }; | |
| } | |
| return Continue; | |
| }; | |
| public static StepperRef<T> ToStepperRef<T>(this T[] array) => | |
| step => | |
| { | |
| for (int i = 0; i < array.Length; i++) | |
| { | |
| step(ref array[i]); | |
| } | |
| }; | |
| public static StepperRefBreak<T> ToStepperRefBreak<T>(this T[] array) => | |
| step => | |
| { | |
| for (int i = 0; i < array.Length; i++) | |
| { | |
| if (step(ref array[i]) == Break) | |
| { | |
| return Break; | |
| }; | |
| } | |
| return Continue; | |
| }; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment