🧩 附章 函数式语言是怎样工作的
📄 一句话概括

partial 固定一个参数、pipe 把多个函数串起来,两种都不写新函数体(0 行);组合的意思是拿现成的小东西拼,而不是为每种拼法造新函数。

📝 本节和前面几节的关系

A.5 说函数是值,这一节说能当值就能拼。

一、实测:两种组合

固定参数(partial):add5 = partial(add, 5),新函数体 0 行。 串成管道(pipe):pipe(f, g, h)(3) 依次跑三步,新函数体 0 行。 手写对照版:固定参数要写 1 行函数体,手写管道要写 3 个函数。 两版结果完全一致(8 与 8、49 与 49)。

二、组合省的是什么

省的不是行数,是【不新增概念】。 每造一个新函数,就多一个名字要记、多一个地方要维护。 组合只声明【怎么拼】,拼出来的东西可以不留名字(就地传出去)。

三、代价:调试变难

栈里全是匿名函数,出错时得一层层拆开看。 所以组合适合【步骤短、每步都很纯】的场合。 步骤一长就该拆回来命名——命名不是落后,是给人看的。

四、动手 Demo:特征4:可以灵活组合函数和参数

用 partial 固定一个参数,用 pipe 串三步。 各写一版手写对照,比函数体行数。

import functools

def add(a, b):
    return a + b

def add5_manual(x):
    return add(5, x)

add5 = functools.partial(add, 5)

def pipe(*fns):
    def run(x):
        for f in fns:
            x = f(x)
        return x
    return run

steps = pipe(lambda n: n * 2, lambda n: n + 1, lambda n: n * n)
print(add5(3), add5_manual(3))   # 8 8
print(steps(3), (3 * 2 + 1) ** 2)  # 49 49

实跑输出:

--------------------------------------------------------------------
特征4:可以灵活组合函数和参数
--------------------------------------------------------------------

  固定一个参数、串起多个函数,**这两种组合各能省多少行:**

  做法             写法                       要新写的函数体     结果
  --------------------------------------------------------------------
  手写固定参数     add5_manual(x)             1                  8
  partial          add5 = partial(add, 5)     0                  8
  手写管道         三步各写一次               3                  49
  pipe 组合        pipe(f, g, h)              0                  49

      两种等价写法结果一致        True
      组合出来的新函数            0 行新函数体
      可组合的基本动作            2 种(固定参数/串成管道)

  **注意第 4 行:`steps(3)` 走了三步(×2、+1、平方),**一行新函数都没写。**
  **这就是组合的意思:**拿现成的小东西拼,而不是为每种拼法造一个新函数。
  **代价是调试**:出错时得一层层拆开看,**栈里全是匿名函数。**

实测:partial 与 pipe 都不写新函数体(0 行),结果和手写版完全一致。 组合省的不是行数,是不新增概念——每造一个函数就多一个名字要管。 代价是调试难:栈里全是匿名函数,步骤一长就该拆回来命名。

30 秒实验

  1. 把你代码里三个连续的清洗步骤(去空、转小写、去重)串成一条 pipe。
  2. 再判断:这条 pipe 出错时,你能一眼看出是哪一步的问题吗?

常见误区

  1. 以为组合一定比命名清楚。组合一长,读的人就迷路了。
  2. 为了组合而组合,把两行的逻辑拆成五个 lambda。那是自找麻烦。
自测三问(点开对答案) 1. 两种组合方式是什么? —— 固定一个参数(partial)和串成管道(pipe)。 2. 组合省的是什么? —— 不新增概念、不多一个要维护的名字,而不是省行数。 3. 组合的代价? —— 调试变难,栈里全是匿名函数。

相关笔记