函数式操作
函数式操作
f[x] + f[1 - x] /. f -> gp1 = p2;p1[x, y]pf[f_, x_] := f[x] + f[1 - x]给出 Log 用作函数名称:
pf[Log, q]普通的 Wolfram 语言函数(如 Log 或 Integrate)通常操作的是数字和代数表达式等数据,而代表函数式操作的 Wolfram 语言函数不仅可以对普通数据进行操作,还可以对函数本身进行操作. 例如,函数式操作InverseFunction 以 Wolfram 语言函数名称作为参数,来表示该函数的反函数.
InverseFunction 是一个函数式操作:将 Wolfram 语言函数作为参数,返回该函数的反函数.
InverseFunction[ArcSin]由 InverseFunction 获得的结果也是一个函数,可以应用于数据:
%[x]还可以以纯符号方式使用 InverseFunction:
InverseFunction[f][x]Nest[f, x, 4]NestList[f, x, 4]recip[x_] := 1 / (1 + x)可以使用 Nest 迭代该函数:
Nest[recip, x, 3]| FixedPoint[f,x] | 重复应用函数 f 直到结果不再更改 |
| FixedPointList[f,x] | 生成列表 {x,f[x],f[f[x]],…},当元素不再更改时停止 |
newton3[x_] := N[1 / 2 (x + 3 / x)]NestList[newton3, 1.0, 5]FixedPoint[newton3, 1.0]FixedPointList[newton3, 1.0]| NestWhile[f,x,test] | |
| NestWhileList[f,x,test] | |
| NestWhile[f,x,test,m]
,
NestWhileList[f,x,test,m] | |
提供 m 个最新结果作为每一步 test 的参数 | |
| NestWhile[f,x,test,All]
,
NestWhileList[f,x,test,All] | |
提供现有的所有结果作为 test 的参数 | |
divide2[n_] := n / 2NestWhileList[divide2, 123456, EvenQ]NestWhileList[newton3, 1.0, Unequal, 2]NestWhileList[Mod[5#, 7]&, 1, Unequal, All]| FoldList[f,x,{a,b,…}] | 创建列表 {x,f[x,a],f[f[x,a],b],…} |
| Fold[f,x,{a,b,…}] | 给出由 FoldList[f,x,{a,b,…}] 生成的列表的最后一个元素 |
FoldList 的用法示例:
FoldList[f, x, {a, b, c}]Fold[f, x, {a, b, c}]FoldList[Plus, 0, {a, b, c}]使用 Fold 和 FoldList 可以在 Wolfram 语言中编写许多优雅高效的程序. 在某些情况下,将 Fold 和 FoldList 视为由第二个参数索引的一组函数的简单嵌套可能会有所帮助.
nextdigit[a_, b_] := 10 a + b以下函数与内置函数 FromDigits 的作用一样:
fromdigits[digits_] := Fold[nextdigit, 0, digits]fromdigits[{1, 3, 7, 2, 9, 1}]Apply[f, {a, b, c}]给出了 Times[a,b,c],生成列表中元素的乘积:
Apply[Times, {a, b, c}]geom[list_] := Apply[Times, list] ^ (1 / Length[list])| Apply[f,{a,b,…}] | 将 f 应用于列表,给出 f[a,b,…] |
| Apply[f,expr] or f@@expr | 将 f 应用于表达式的顶层 |
| MapApply[f,expr] or f@@@expr | 将 f 应用于表达式的第一层 |
| Apply[f,expr,{1}] | 等价于 f@@@expr |
| Apply[f,expr,lev] | 将 f 应用于表达式的指定层 |
Apply[List, a + b + c]m = {{a, b, c}, {b, c, d}}Apply[f, m]Apply[f, m, {1}]MapApply[f, m]Apply[f, m, {0, 1}]如果有一个元素列表,将函数分别应用于列表中每个元素通常很重要. 在 Wolfram 语言中这可以使用 Map 完成.
Map[f, {a, b, c}]take2[list_] := Take[list, 2]Map[take2, {{1, 3, 4}, {5, 6, 7}, {2, 1, 6, 6}}]| Map[f,{a,b,…}] | 将 f 应用于列表的每个元素,给出 {f[a],f[b],…} |
Map[f, a + b + c]Map[Sqrt, g[x ^ 2, x ^ 3]]m = {{a, b}, {c, d}}Map[f, m]MapAll[f, m]Map[f, m, {2}]Map[f, m, Heads -> True]| Map[f,expr] 或 f/@expr | 将 f 应用于 expr 的第一层部分 |
| MapAll[f,expr] 或 f//@expr | 将 f 应用于 expr 的所有部分 |
| Map[f,expr,lev] | 在由 lev 指定的层上将 f 应用于 expr 的各个部分 |
可以通过指定层的方法用 Map 将函数作用于表达式的一些项上. 通过指定层次可以使函数作用于表达式的某些项上,用MapAt 可以通过列出元素标号使函数作用于表达式的某些项上,请参见 "表达式的部分".
mm = {{a, b, c}, {b, c, d}}MapAt[f, mm, {{1, 2}, {2, 3}}]Position[mm, b]MapAt[f, mm, %]MapAt[f, {a, b, c, d}, {{2}, {3}}]| MapAt[f,expr,{part1,part2,…}] | 将 f 作用于 expr 中指定的项 |
t = 1 + (3 + x) ^ 2 / xFullForm[t]MapAt 可用在任何表达式中. 注意,其中指定项的索引是基于表达式的完全格式:
MapAt[f, t, {{2, 1, 1}, {2, 2}}]| MapIndexed[f,expr] | 将 f 作用于表达式的元素,f 的第二个变量给出表达式的每个元素项的位置 |
| MapIndexed[f,expr,lev] | 将 f 作用于表达式指定层的元素,f 的第二个变量给出表达式中每项的指标号 |
MapIndexed[f, {a, b, c}]MapIndexed[f, {{a, b}, {c, d}}, 2]| MapThread[f,{expr1,expr2,…}] | 将 f 作用于每个表达式 expri 中对应的项 |
| MapThread[f,{expr1,expr2,…},lev] | 将 f 作用于 expri 的指定层 |
MapThread[f, {{a, b, c}, {ap, bp, cp}}]MapThread 可对结构相同的任意长度的表达式进行操作:
MapThread[f, {{a, b}, {ap, bp}, {app, bpp}}]Map 等函数可以通过项的修改产生表达式,但有时不需要产生新的表达式,仅需要查看某些表达式,或者仅对表达式中的某些项进行运算. 一个典型的情况是当你所运用的函数具有某些 “副作用” 时,如进行赋值或产生输出时.
Map[f, {a, b, c}]Scan 计算将函数作用于每一个元素的结果,但不产生新的表达式:
Scan[Print, {a, b, c}]Scan 从最低层开始访问表达式中的所有项:
Scan[Print, 1 + x ^ 2, Infinity]h[x_] := f[x] + g[x]Map[h, {a, b, c}]Map[f[#] + g[#]&, {a, b, c}]Function[x, x ^ 2]%[n]在 Map 中使用纯函数:
Map[Function[x, x ^ 2], a + b + c]在嵌套 Nest 中用纯函数:
Nest[Function[q, 1 / (1 + q)], x, 3]Function[{x, y}, x ^ 2 + y ^ 3][a, b]正如如果你不想再次提到该函数的话,函数名是无关的,因此同样地,一个纯函数中的变量名也是无关的. Wolfram 语言允许用户不使用纯函数变量的显式名字,另一方面,我们可以通过给出“位置数字” #n 来指明变量. 在一个 Wolfram 语言纯函数中,#n 表示所提供的第 n 个变量. # 表示第一个变量.
Map[# ^ 2&, a + b + c]Map[Take[#, 2]&, {{2, 1, 7}, {4, 1, 5}, {3, 1, 2}}]fromdigits[digits_] := Fold[(10#1 + #2)&, 0, digits]在纯函数中使用 & 符号时,要注意 & 的优先级很低,必要时要用括号,如“运算符的输入形式”中讨论的. 这意味着,你可以不用括号输入形如 #1+#2& 的表达式. 另一方面,如果你愿意对纯函数设置选项话,必须使用括号. 例如,option->(fun&).
f[##, ##]&[x, y]Apply[f[##2, #1]&, {{a, b, c}, {ap, bp}}, {1}]| Array[f,n] | 产生形如 {f[1],f[2],…} 的长度为 n 的列表 |
| Array[f,{n1,n2,…}] | 产生 n1×n2×… 的嵌套列表,每个元素是 f 作用于其标号上得到的 |
| NestList[f,x,n] | 产生形如 {x,f[x],f[f[x]],…} 的列表,其中 f 迭代 n 次为止 |
| FoldList[f,x,{a,b,…}] | 产生列表 {x,f[x,a],f[f[x,a],b],…} |
| ComposeList[{f1,f2,…},x] | 产生列表 {x,f1[x],f2[f1[x]],…} |
Array[p, 5]Table[p[i], {i, 5}]Array[# + # ^ 2&, 5]Array[m, {2, 3}]Array[Plus[##] ^ 2&, {3, 3}]NestList[D[#, x]&, x ^ n, 3]"处理列表元素" 介绍了如何根据 位置 在列表中选取元素. 经常也需要根据内容来选取元素,而不是根据位置选取.
选取令纯函数生成 True 的列表元素,即数值大于4:
Select[{2, 15, 1, a, 16, 17}, # > 4&]可以使用 Select 选取任意表达式的项,不仅仅局限于列表的元素.
t = Expand[(x + y + z) ^ 2]Select[t, FreeQ[#, x]&]Select[{-1, 3, 10, 12, 14}, # > 3&, 1]f[3][x, y](a + b)[x]头部为 Function[x,x^2] 的表达式的值是其变量的平方:
Function[x, x ^ 2][a + b]| Function[vars,body][args] | 纯函数 |
| InterpolatingFunction[data][args] | 由 Interpolation 和 NDSolve 产生的近似数值函数 |
| CompiledFunction[data][args] | 由 Compile 产生的编译数值函数 |
| LinearSolveFunction[data][vec] | 由 LinearSolve 产生的矩阵解函数 |
NDSolve[{y''[x] == y[x], y[0] == y'[0] == 1}, y, {x, 0, 5}]y /. First[%]%[3.8]考虑一个求导运算的例子,在 "导数的表示" 节将要讨论的表达式 f' 求函数 f 的导数,在 Wolfram 语言中 f' 用 Derivative[1][f] 表示,“函数操作符” Derivative[1] 作用于 f 后给出另一个函数 f'.
f'[x]//FullForm% /. f' -> fp| Composition[f,g,…] | 函数 f,g,… 的复合 |
| RightComposition[f,g,…] | f,g,… 的右侧的复合 |
| InverseFunction[f] | f的反函数 |
| Identity | 恒等函数 |
Composition[f, g, h]InverseFunction[Composition[%, q]]%[x]f @* g @* hRightComposition 按想法顺序进行复合:
RightComposition[f, g, h]f /* g /* h(f + g)[x]Through 可以使上面的表达式更加明确:
Through[%, Plus]Identity + (D[#, x]&)%[x ^ 2]用 Through 去作用这一算子:
Through[%, Plus]| Identity[expr] | 恒等函数 |
| Through[p[f1,f2][x],q] | 当 p 与 q 相同时给出 p[f1[x], f2[x]] |
| Operate[p,f[x]] | 得到 p[f][x] |
| Operate[p,f[x],n] | 在 f 的第 n 层运用 p |
| MapAll[p,expr,Heads->True] | 将 p 作用于 expr 的头部和所有项 |
t = ((1 + a)(1 + b))[x]像 Expand 这样的函数不会自动作用于表达式的头部:
Expand[%]MapAll[Expand, t, Heads -> True]t /. a -> 1可以用 Operate 将某一函数作用于表达式的头部:
Operate[p, t]我们描述各种对表达式进行的操作. "属性" 介绍一些操作如何自动在所有具有特定头部并且该头部被赋以适合的属性的表达式上进行.
Wolfram 语言函数 Sort[expr] 不仅排列列表元素,也对具有任意头部的表达式排序. 用这种方式,我们可以对任意函数实现结合特性或对称性.
Sort 将函数的变量按序排列:
Sort[f[c, a, b]]| Sort[expr] | 按照一种标准顺序对列表或表达式的元素分类 |
| Sort[expr,pred] | 用 pred 函数决定是否按顺序排列 |
| Ordering[expr] | 当排好序时,给出元素的顺序 |
| Ordering[expr,n] | 当排好序时,给出前 n 个元素的顺序 |
| Ordering[expr,n,pred] | 使用函数 pred 来决定是否每对都是排好序的 |
| OrderedQ[expr] | |
| Order[expr1,expr2] | 当 expr1 按标准顺序出现在 expr2 前时取值 1,相反时取值 -1 |
Sort 的第二个变量是用于决定是否每对都是排好序的函数. 排序按递减顺序进行:
Sort[{5, 1, 8, 2}, (#2 < #1)&]Sort[{x ^ 2, y, x + y, y - 2}, FreeQ[#1, x]&]| Flatten[expr] | 压平与 expr 具有相同头部的嵌套函数 |
| Flatten[expr,n] | 最多取消 n 次嵌套 |
| Flatten[expr,n,h] | 撤销以 h 为头部的函数的结构 |
| FlattenAt[expr,i] | 撤销表达式 expr 中的第 i 层结构 |
Flatten 压平函数嵌套:
Flatten[f[a, f[b, c], f[f[d]]]]Flatten[{a, f[b, c], f[a, b, d]}, 1, f]| Distribute[f[a+b+…,…]] | 将 f 分配到和式去得到 f[a,…]+f[b,…]+… |
| Distribute[f[args],g] | 将 f 分配到头部为 g 的变量 |
| Distribute[expr,g,f] | 当头部为 f 时分配 |
| Distribute[expr,g,f,gp,fp] | 将 f 分配到 g,并分别用 fp 和 gp 代替 |
Distribute[f[a + b]]Distribute[f[a + b, c + d]]一般地,f 分配到和式 Plus 时,是将如 f[a+b] 的表达式 “展开” 为 f[a]+f[b]. 函数 Expand 对标准的代数乘法如 Times 进行类似的分配展开. Distribute 可对任意运算进行类似的分配展开.
Expand[(a + b) (c + d)]Distribute[f[{a, b}, {c, d}], List]Distribute[f[{a, b}, {c, d}], List, f]Distribute[f[{a, b}, {c, d}], List, f, gp, fp]| Thread[f[{a1,a2},{b1,b2}]] | 将 f 线性作用于列表给出 {f[a1,b1],f[a2,b2]} |
| Thread[f[args],g] | 将 f 线性作用于头部为 g 的变量 args 上 |
f[{a1, a2}, {b1, b2}]Thread 线性作用于列表的元素:
Thread[%]Thread[f[{a1, a2}, {b1, b2}, c, d]]内置函数,比如 Log 是可列表的,因此可以自动逐项作用于列表:
Log[{a, b, c}]但 Log 不能自动对方程进行线性作用:
Log[x == y]可以用 Thread 使函数作用于方程两端:
Thread[%, Equal]Outer[f, {a, b}, {1, 2, 3}]Outer 产生一个下三角 Boolean 矩阵:
Outer[Greater, {1, 2, 3}, {1, 2, 3}]Outer 可用于任何头部相同的表达式:
Outer[g, f[a, b], f[c, d]]由 Inner 形成的结构:
Inner[f, {a, b}, {c, d}, g]Inner[Times, {a, b}, {c, d}, Plus]函数 Flatten 撤销所有的子列表:
Flatten[{a, {b, c}, {d, e}}]FlattenAt 撤销指定的子列表结构:
FlattenAt[{a, {b, c}, {d, e}}, 2]Sequence 序列对象中的元素自动进行拼接,而不要求任何显式的压平操作:
{a, Sequence[b, c], Sequence[d, e]}| Sequence[e1,e2,…] | 序列的元素自动拼接到函数 |
Sequence 用于各种函数:
f[Sequence[a, b], c]a == Sequence[b, c]Sequence 的常用方式:
{a, b, f[x, y], g[w], f[z, y]} /. f -> Sequence相关指南
-
▪
- 函数式编程