Bry*_*her 15 c# ienumerable functional-programming
作为编写流畅API的实践,我想我会进行以下编译和运行:
static void Main(string[] args)
{
Enumerable.Range(1, 100)
.When(i => i % 3 == 0).Then(i => Console.WriteLine("fizz"))
.When(i => i % 5 == 0).Then(i => Console.WriteLine("buzz"))
.Otherwise(i => Console.WriteLine(i))
.Run();
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
这个想法.When将测试枚举中的每个元素,如果它通过谓词,则运行该动作.如果谓词失败,则项目沿着链传递.
我想出的图是:
public static class EnumerableExtensions
{
public static IConditionalEnumerable<T> When<T>(this IEnumerable<T> items, Predicate<T> test, Action<T> action)
{
}
public static IResolvedEnumerable<T> Then<T>(this IConditionalEnumerable<T> items, Predicate<T> test, Action<T> action)
{
}
public static void Run<T>(this IEnumerable<T> items)
{
foreach (var item in items) ;
}
}
public interface IConditionalEnumerable<T> : IEnumerable<T>
{
IResolvedEnumerable<T> Then<T>(IConditionalEnumerable<T> items, Action<T> action);
}
public interface IResolvedEnumerable<T> : IEnumerable<T>
{
IEnumerable<T> Otherwise(Action<T> behavior);
}
Run Code Online (Sandbox Code Playgroud)
我遇到了一个问题 - When不能foreach / yield return在其中,因为返回类型不是直接的IEnumerable<T>(尽管它继承了它).这给齿轮带来了精神上的冲击.扩展方法的实现会是什么样的?
Eri*_*ert 13
不要担心序列.只是在价值观上做.
您可以使用扩展方法完全执行此操作.这是事情:
Otherwise需要知道以前是否有任何Then执行.When需要知道以前是否每次都Then执Then需要知道前一个When是真还是假.这是骨架:
static class X
{
public enum WhenState { DoIt, DoNot }
public enum ThenState { DidIt, DidNot }
public static (T, ThenState) Begin<T>(this T item) { ... }
public static (T, WhenState, ThenState) When<T>(
this (T item, ThenState then) tuple,
Func<T, bool> p) { ... }
public static (T, ThenState) Then<T>(
this (T item, WhenState when, ThenState then) tuple,
Action<T> a) { ... }
public static void Otherwise<T>(
this (T item, ThenState then) tuple,
Action<T> a) { ... }
Run Code Online (Sandbox Code Playgroud)
实现这些扩展方法后,您可以执行以下操作:
3.Begin().When(x => x % 3 == 0).Then( ... )
Run Code Online (Sandbox Code Playgroud)
等等.
一旦实现了这一点,就很容易将操作提升到序列.我们有一个将价值观转化为行动的装置; 什么是将一系列值转换为一系列动作的设备?它内置于语言中:foreach(var item in items) item.Begin()....
同样,很容易将操作提升到任何其他monad.说,可以为空.我们有一个将值转化为行动的设备.什么是将可以为空的值转换为动作或无动作的设备?它内置于语言中: x?.Begin()...
假设您希望将您的操作应用于Task<int>; 什么是将未来价值转化为未来行动的设备?async Task DoIt(Task<T> task) { (await task).Begin()....
等等.在价值上实施您的操作,而不是在提升的价值上实施 ; 使用语言的内置提升操作将您的操作应用于提升值以产生提升动作.
| 归档时间: |
|
| 查看次数: |
378 次 |
| 最近记录: |