gpt4 book ai didi

oop - 向面向对象的程序员和技术含量较低的人解释函数式编程

转载 作者:行者123 更新时间:2023-12-03 11:32:04 25 4
gpt4 key购买 nike

有哪些很好的例子可以用来解释函数式编程?

受众可能是编程经验很少的人,或者只有面向对象经验的人。

最佳答案

The audience would be people with little programming experience,



是否真的可以向没有太多编程经验的人解释函数式编程,更不用说 OO 或过程或任何编程范式?

or people who only have object-oriented experience.



最好的例子可能是将已知的设计模式转换为它们的等效功能。让我们以将整数列表转换为字符串列表的规范示例为例:
using System;

namespace Juliet
{
interface IConvertor<T, U>
{
U Convert(T value);
}

class Program
{
static U[] Convert<T, U>(T[] input, IConvertor<T, U> convertor)
{
U[] res = new U[input.Length];
for (int i = 0; i < input.Length; i++)
{
res[i] = convertor.Convert(input[i]);
}
return res;
}

class SquareInt : IConvertor<int, string>
{
public string Convert(int i)
{
return (i * i).ToString();
}
}

class ScaleInt : IConvertor<int, string>
{
readonly int Scale;

public ScaleInt(int scale)
{
this.Scale = scale;
}

public string Convert(int i)
{
return (i * Scale).ToString();
}
}

static void Main(string[] args)
{
int[] nums = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

string[] squared = Convert<int, string>(nums, new SquareInt());
string[] tripled = Convert<int, string>(nums, new ScaleInt(3));
}
}
}

它简单、易读、面向对象,甚至是通用的,所以它适用于任意类型,那么问题是什么?首先,它很臃肿:我有一个接口(interface)定义和两个接口(interface)实现。如果我需要另一个转换怎么办?好吧,我需要另一个接口(interface)实现——它很快就会失控。

仔细想想, IConvertor<T, U>类只是一个名为 Convert 的函数的包装器。 -- 这个类确实存在帮助我们通过 Convert到其他功能。如果你能理解这么多,那么你已经理解了函数作为一等值背后的基本原理——函数式编程就是将函数传递给其他函数,就像传递一个人、一个 int 或一个字符串一样。

人们通常更喜欢函数式编程,因为它可以帮助他们避免单一方法的接口(interface)和实现。我们不传递一个类,而是通过名称或匿名传递一个函数:
using System;

namespace Juliet
{
class Program
{
static U[] Convert<T, U>(T[] input, Func<T, U> convertor)
{
U[] res = new U[input.Length];
for (int i = 0; i < input.Length; i++)
{
res[i] = convertor(input[i]);
}
return res;
}

static string SquareInt(int i)
{
return (i * i).ToString();
}

static void Main(string[] args)
{
int[] nums = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

string[] squared = Convert<int, string>(nums, SquareInt); // pass function by name
string[] tripled = Convert<int, string>(nums, i => (i * 3).ToString()); // or pass anonymously
}
}
}

好的,所以现在我们用更少的代码行拥有完全相同的程序,它的可读性和它的作用非常明显。

现在有人可能会说“这是一个巧妙的技巧,但我什么时候可以使用它”——在很多情况下,您都希望像这样传递函数。它为您提供了更多以新颖的方式抽象程序控制流的能力。改编自示例 here ,考虑一个处理文件的类:
class FileFunctions
{
internal void SaveFile()
{
SaveFileDialog fileDialog = new SaveFileDialog();
fileDialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
if (fileDialog.ShowDialog() == DialogResult.OK)
{
File.AppendAllText(fileDialog.FileName, MyDocument.Data);
}
}

internal void WriteFile()
{
OpenFileDialog fileDialog = new OpenFileDialog();
fileDialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
if (fileDialog.ShowDialog() == DialogResult.OK)
{
MyDocument.Data = File.ReadAllText(fileDialog.FileName);
}
}
}

呸。代码是重复的,但它在不同的类上执行操作并调用不同的方法。您将如何抽象出 OO 世界中的重复代码?在函数式编程中,这很简单:
class FileFunctions
{
internal void ShowDialogThen(FileDialog dialog, Action<FileDialog> f)
{
dialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
if (dialog.ShowDialog() == DialogResult.OK)
{
f(dialog);
}
}

internal void SaveFile()
{
ShowDialogThen(
new SaveFileDialog(),
dialog => File.AppendAllText(dialog.FileName, MyDocument.Data));
}

internal void WriteFile()
{
ShowDialogThen(
new OpenFileDialog(),
dialog => { MyDocument.Data = File.ReadAllText(dialog.FileName); });
}
}

惊人的。

关于oop - 向面向对象的程序员和技术含量较低的人解释函数式编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2294053/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com