5.5 函数值

5.5 函数值

我们已经看到过一个作为值使用的函数的示例(第 3 章),当时,写过一个函数,汇总列表元素,使用另一个函数作为参数值。以这种方式,我们能够使用相同的聚合,用于不同的目的:我们先用它来计算列表中的所有元素的总和,后面用来发现集合中最大元素。

使用数据的集合可能是最佳方式,显示为什么函数作为值使用是重要的。话虽如此,这远不是唯一情况,这个概念非常有用,在这本书的其余部分你将会看到。让我们首先来看一个命令式代码的示例,从给定集合中选出偶数,返回到另一个集合中:

var numbers = new [] {3,9,1,8,4};
var evens = new List();
foreach(var n in numbers)
if (n%2 == 0)
evens.Add(n);
return evens;

想象一下,如果要以不同的方式筛选这个集合,哪些行代码不需要修改,例如,返回所有的正数。所示的 4 行中有 3 行

(不算第一行,初始化数据,最后一行,返回结果)都是样板代码,将保持不变(代码变化的部分以粗体突出显示)。通过使用函数作为值,并把它作为参数接受,我们可以提取代码的公用部分,作为一个可重复使用的方法。然后,调用代码必须指定参数值,描述不同筛选器变化的部分:谓词应用于每个元素。

事实上,很多的标准函数,如筛选,在 F # 中已经存在,并在 .NET 3.5 LINQ 添加了几乎相同的功能,来处理集合。有一些以不同的方式来命名。在 F# 中,函数取一个谓词,并执行筛选被称为 filter(筛选器),而在 LINQ 中叫 Where(类似于 SQL 中的 WHERE 子句)。清单 5.14 显示了前面的使用这些函数的示例的一个实现。

Listing 5.14 Filtering using a predicate

// C# version
using System.Linq;

var nums = new [] {4,9,1,8,6};
var evens = nums.Where(n => n%2 == 0);
PrintNumbers(evens);

// F# version with output from F# Interactive
> let nums = [ 4; 9; 1; 8; 6 ];;
val nums : int list

> let evens = List.filter (fun n -> n%2 = 0) nums;;
val evens : int list = [ 4; 8; 6 ]

如果我们必须把谓语写成一种正常的 C# 中的方法 或 F# 中的函数(使用 let),它不会有比前面的版本更短的任何代码。使代码更简单的关键功能是能够写这个函数(这里的谓语)内嵌直接,当调用 Where 方法或 filter 函数。

在 C# 中,这种符号被称为 lambda 表达式,在 F# 中叫 lambda 函数。因为本书的大部分是关于 F#,我们会保持统一使用 F# 的命名。在两种情况下,lambda 一词是指希腊字母,来自于 lambda 演算,我们在第 2 章中提到过。

函数值是什么?

在函数编程语言中,函数存在动机是函数的数学概念。在许多方面,这与有命令式背景的程序员直觉认为函数的方式不同。在命令式编程中,函数是一段程序,取参数,执行代码,返回结果。在这个意义上的函数,可以做任何事情。最重要的是,它可以使用和修改全局状态,所以,调用同一函数,有相同的参数,但结果可能不同。这方面最明显的例子,可能是伪随机数发生器——如果它始终返回相同的结果,就不是很随意!

在数学上,函数更多的是参数值与结果之间的关系。这意为着,数学函数如果给相同参数值,始终返回相同的结果。显然,这就是我们前面示例中谓词的工作的方式。对于相同的参数值,它始终返回相同的结果(偶数为真,奇数为假)。

以这样数学方式表现的函数称为纯函数(pure functions)。我们写的大多数的函数都是纯函数,但在下一章结束时,我们会看到此规则有趣且有用的例外。你可能会想数学的伪随机数字生成器函数看起来应该是什么样子。

对于那些来自面向对象技术背景的人,有另一个途径看函数:可以把函数值看作对象,实现真正简单的接口,有单一方法。使用这种理解,来自前面示例中的谓语对应于以下接口:

interface Function_Int_Bool {
bool Execute(int arg);
}

在 C# 中,委派有点类似于函数,C# 3.0 使它们非常接近这个简单的概念。然而,函数的概念就像它在 F# 中使用的一样,函数式编程主要基于数学概念。在这个意义上讲,F# 函数比接口或委派简单得多——它们只是函数。

在前面的示例中,我们已经看到 lambda 函数是一个关键因素,使简洁的函数编程风格成为可能。我们会在全书中都使用,因此,让我们仔细地看看 lambda 函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值