软件架构风格 仓库风格_功能风格–第5部分

软件架构风格 仓库风格

高阶函数I:函数组成和Monad模式。

什么是高阶函数?

在上一篇文章中,我们看到了一些作为一等公民的函数的示例以及它们可以用于的各种用途。 回顾一下,当函数本身是一个值时,它就是一等公民,并且可以像其他任何类型的值一样在程序中传递。

现在,当一个函数接受另一个函数作为其参数,或者当它产生另一个函数作为其返回值(或两者兼有)时,该函数被称为高阶函数 。 如果您回想一下Eratosthenes练习筛网,它实际上具有以下功能,我们实际上已经在上一篇文章中看到了一个示例:

private Predicate<Integer> notInNonPrimesUpTo(int limit) {
    var sieve = new HashSet<Integer>();
    for (var n = 2; n <= (limit / 2); n++)
        for (var nonPrime = (n * 2); nonPrime <= limit; nonPrime += n)
            sieve.add(nonPrime);
    return candidate -> !sieve.contains(candidate);
}

该函数返回Predicate 。 谓词是产生布尔值的函数。 这意味着notInNonPrimesUpTo是一个高阶函数:它将构建筛子并产生一个测试数字是否在筛子中的函数。

我们也看到了其他示例。 您还记得第三部分的map吗? 它接受一个函数并将其应用于数组中的所有元素,从而产生另一个数组。 map是高阶函数。 filter也是这样,因为它需要一个谓词,然后在数组的每个元素上对其进行测试,然后使用谓词的结果来决定是保留还是丢弃该元素。 qsort也是一个高阶函数,因为它使用比较器函数并使用它来确定数组中任何两个元素的顺序,而无需知道元素的类型。 因此,上一篇文章充斥着高阶函数,您不应被这个术语所吓倒。 这并不意味着任何珍贵或崇高的东西。 几乎可以肯定,您在工作中经常使用某种高阶函数。 实际上,如果没有高阶函数将它们传递进来或从中返回,则一等函数是无用的。

功能组成。

在函数式编程世界中,您会听到很多有关此的信息。 组成两个函数意味着将它们排列成一个函数的结果直接用作另一个函数的输入。 您的代码可能充满了这样的示例,但是如果代码的结构没有突出显示这一事实,那么您可能不会总是注意到。 函数式编程人员始终会警惕以这种方式安排函数的时间,因为这允许某些编程结构的可能性,我们将在稍后讨论。 精于功能风格的程序员通常会发现,将两个组合功能本身视为第三个功能很有用。 让我解释一下我的意思。

假设您有一个函数f,该函数将值x作为参数并返回值y:

f(x)= y

并且您还有另一个函数g,该函数将y作为其参数并返回z:

g(y)= z

显然,您可以将g应用于f的输出,如下所示:

g(f(x))= z

因此,这意味着存在第三个函数h,它将x直接映射到z:

h(x)= z

函数式程序员会说h是函数f和g的组成。 在Haskell中,定义如下:

h = g . f

在Haskell中,极简主义被视为一种美德。 在Clojure中,更为冗长,它的定义如下:

(def h (comp f g))

函数式编程的奉献者倾向于以这种方式查看函数的组成。 就我个人而言,我没有发现显式命名诸如此类的组合函数的做法特别有用。 特别是我看不出上述Clojure与以下代码之间有任何区别:

(defn h [arg] (g (f arg)))

除此之外,第一个示例更为简洁。 FP的奉献者喜欢对功能组合的功能进行抒情处理,而我自己的观点则比较平淡。

功能组成为管道。

将功能组合在一起的想法并不新颖。 1964年,道格·麦克罗伊(Doug McIlroy)在一份备忘录中写道:

我们应该有一些耦合程序的方式,例如花园软管-当有必要以其他方式处理数据时,请拧入另一段。

Doug提出的想法后来在Unix中通过管道实现,这可能是使Unix Shell脚本如此强大的单一功能。 Unix管道是一个进程间通信的系统。 它们可以由系统通过系统调用直接创建和使用,但是也可以通过使用|在shell中创建它们。 符号,如下所示:

program1 | program2

效果是创建一个管道,该管道读取由program1写入标准输出的所有内容,并通过其标准输入将其逐字提供给program2 。 这意味着您可以像构建块一样将程序链接在一起,以完成程序本身无法完成的任务。 例如,如果我想按代码行在目录中找到前3大Java程序,则可以这样做:

wc -l *.java | grep \.java | so
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值