Skip to content

Instantly share code, notes, and snippets.

@ZacharyPatten
Last active October 6, 2019 13:38
Show Gist options
  • Save ZacharyPatten/aa5f923c383334b76a43c94fc530ec87 to your computer and use it in GitHub Desktop.
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.
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