【问题标题】:Functional Programming printing numbers divisible by 2函数式编程打印可被 2 整除的数字
【发布时间】:2019-07-21 11:37:34
【问题描述】:

我正在尝试学习函数式编程并且我正在编写一个打印可除数 2 的函数。我知道在函数式编程中它应该避免循环并且应该具有引用透明性,因此变量应该是不可变的。这是我写的函数,符合函数式编程范式吗?

public static void evenNumbers(int start, int end)
{

    if (start <= 20)
    {
        if (start % 2 == 0)
        {
            System.Console.WriteLine(start);
        }
        evenNumbers(start + 1, end);
    }
} 

编辑我对代码做了一些修改

public static void evenNumbers(int start, int end)
    {

        if (start <= 20)
        {
            if (start % 2 == 0)
            {
                return start;
            }
            evenNumbers(start + 1, end);
        }
    } 

【问题讨论】:

  • 如果你想学习函数式编程,那么为什么不使用函数式语言,比如 F#?
  • question1 是如何定义的?一种功能性方法是返回一系列匹配的数字,而不是执行副作用(如Console.WriteLine)作为过程的一部分。
  • 我相信在里面调用 Console.WriteLine 已经破坏了这个函数的功能性质。
  • 为了适应 F​​P,你的函数应该返回列表,而不是打印它。
  • 如果我将 System.Console.WriteLine(start) 更改为返回 start 会起作用吗?

标签: c# functional-programming


【解决方案1】:

如果你想在 C# 中编写“功能性”代码 - 使用 LINQ 扩展方法

var valuesToPrint = 
    Enumerable.Range(start, end - start)
              .Where(value => number % 2 == 0)
              .Select(value => value.ToString());
var output = String.Join(Environment.NewLine, valuesToPrint)

// Console is external resource (aka global state)
Console.WriteLine(output);

如果你是 LINQ 的忠实粉丝,你可以使用 .Aggregate 扩展方法构建输出

var output = 
    Enumerable.Range(start, end - start)
              .Where(value => number % 2 == 0)
              .Aggregate(new StringBuilder(),
                         (builder, value) => builder.AppendLine(value),
                         builder => builder.ToString());

Console.Write(output);

有些人会争论 AggregateStringBuilder 不是纯函数式的,因为我们更新了 StringBuilder 的同一实例的内部状态。

【讨论】:

  • 如果列表不大,我们可以考虑用.Aggregate((a, x) =&gt; a + ", " + x)替换String.Join
  • @Matt.G,我建议使用AggregateStringBuilder,那么这种方法也适用于更大尺寸的集合。
猜你喜欢
  • 1970-01-01
  • 2021-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-01
  • 2022-10-05
  • 1970-01-01
相关资源
最近更新 更多