Mathematica学习笔记(5)——Functional Programming
本文最后更新于555 天前,其中的信息可能已经过时,如有错误请发送邮件到lysun26@163.com

mathematica编程最重要的特点就是函数式编程。其特点是函数可以作为数据和函数,函数可以像其他数据一样被操控,包括可以作为参数和返回值。理解了函数式编程,可以给编程带来极大的便捷。可以根据下面的用法来感受一下。

对于一个函数f[x],函数名本身也是一个表达式,可以像对待其他表达式一样对待。例如:

使用转换规则替换函数名称:

f[x] + f[1 - x] /. f -> g
out:g[1 - x] + g[x]

函数名可以通过赋值进行改变:

f = g;
f[x]
out:g[x]

函数名作为函数的参数,并调用:

g[f_, x_] := f[x] + f[1 - x]
g[Log, a]
out:Log[1 - a] + Log[a]

mathematica中有许多函数操作式函数,不仅仅可以对普通数据进行操作,还可以对函数进行操作,这也是最开始提到的函数可以作为数据进行操作。

InverseFunction求反函数:

InverseFunction[ArcSin]
out:Sin

其返回参数也是一个函数,可以进行调用:

%@Pi/2
out:0

同时,这些函数还可以对纯符号形式使用:

InverseFunction[f]
out:f^-1
(*对输出进行调用:*)
InverseFunction[f][x]
out:f^-1[x]

函数定义

函数定义包括两种,一种是对某个函数名进行定义,另一种是纯函数,也成为匿名函数,它不包含具体的函数名。

第一种方法常常用于程序中常常需要调用此函数的时候,而纯函数常用于只需要使用一次这个函数。

指定函数名的函数定义

使用模式和延迟赋值可以定义函数,例如:

f[x_] := x^2

这样定义后,之后就可以使用函数名 f 进行各种操作。

f里面的内容为一个模式,因此,可以利用模式里的内容给自变量加条件,例如:

f[x_Integer?Positive] := x^2

Mathematica中的赋值有两种方式,分别为立即赋值和延迟赋值,延迟赋值为":="。可以通过一段代码来感受一下区别。

立即赋值:

a = 1; b = 2;
c = a + b;
c
a = 2; b = 3;
c

延迟赋值:

a = 1; b = 2;
c := a + b;
c
a = 2; b = 3;
c

如果为立即赋值,两个输出均为3,也就是使用c=a+b,c赋值为3,后续当a和b更改时,c的值并不会发生变化。而对于延迟赋值的情况,输出为3和5,也就是当每次调用c的时候,都会进行a+b的运算。可以发现,这个延迟赋值的模式和函数很像,因此,函数定义的时候使用延迟赋值。延迟赋值的应用不仅仅是函数,还可以利用它的特点写出很多高效的程序。对于规则来说,也有延迟的说法,也就是":->",思想和延迟赋值是一样的。

纯函数

纯函数的定义不指定函数名,使用函数Function进行定义,也可以使用其简写形式——&。

Function用法:

Function[x,body] 单变量

Function[{x1,x2,…},body] 多变量

例如:

Function[x, x^2]

简写形式

类似于λ表达式,自变量定义如下:

  • # 纯函数中的第一个变量
  • #n 纯函数中的第n个变量
  • ## 纯函数的所有变量列表
  • ##n 纯函数中从n个变量开始的变量列

例如:

#^2 &

注意:在纯函数中使用 & 符号时,要注意 & 的优先级很低,必要时要用括号

多行函数的定义

上面仅仅提到了单行函数,而更多复杂的函数需要使用Module。

Module[{x,y,…},expr]

Module[{x=x0,…},expr]

其中x,y等为局部变量。例如:

f[x0_] := Module[{x = x0},
  While[x > 0, x = Log[x]];
  x]
f[10] // N
out:-0.181483

对列表和其他表达式应用函数

在之前的笔记里提到过,在mathematica中列表和表达式是几乎一样的,无非就是头的不同。将函数应用于列表和表达式是一样的。例如:

#^2 & /@ {a, b, c}
out:{a^2, b^2, c^2}
#^2 & /@ (a + b + c)
out:a^2 + b^2 + c^2

Apply(@@)——换头

Apply[f,{a,b,…}] 将 f 应用于列表,给出 f[a,b,…]

Apply[f,expr] or f@@exprf 应用于表达式的顶层

Apply[f,expr,{1}] or f@@@exprf 应用于表达式的第一层

Apply[f,expr,lev] 将 f 应用于表达式的指定层

如果不指定层数,其实就是将列表或表达式的头换成指定的函数f。在前面的表达式章节里也提过。

Map(/@)

Map[f,{a,b,…}] 将 f 应用于列表的每个元素,给出 {f[a],f[b],…}

Map[f,expr] 或 f/@exprf 应用于 expr 的第一层部分

MapAll[f,expr] 或 f//@exprf 应用于 expr 的所有部分

Map[f,expr,lev] 在由 lev 指定的层上将 f 应用于 expr 的各个部分

如果需要指定将f应用于指定的项上,需要使用MapAt。例如:

MapAt[f, {{a, b, c}, {d, e, f}}, {{1, 2}, {2, 1}}]
out:{{a, f[b], c}, {f[d], e, f}}

为了避免混淆,即使在仅有一个下标时,也应该以列表的形式指定每一项:

MapAt[f, {a, b, c, d}, {{2}, {3}}]
out:{a, f[b], f[c], d}

Map 把一元函数作用于一个表达式的项上;MapThread 将多元函数作用于多个表达式.

MapThread[f,{expr1,expr2,…}] 将 f 作用于每个表达式 expri 中对应的项

MapThread[f,{expr1,expr2,…},lev] 将 f 作用于 expri 的指定层

MapThread[f, {{a, b}, {ap, bp}, {app, bpp}}]
out:{f[a, ap, app], f[b, bp, bpp]}

Map等函数可以通过项的修改产生表达式,但有时不需要产生新的表达式,仅需要查看某些表达式,或者仅对表达式中的某些项进行运算。这是需要用到Scan,其语法与Map相同。

重复应用函数(迭代)

对单一参数的函数

许多程序会涉及多次迭代的操作, NestNestList 是执行此操作的强大结构。

Nest[f,x,n] 将嵌套 n 次的函数 f 应用于 x

NestList[f,x,n] 生成列表 {x,f[x],f[f[x]],…},其中 f 的嵌套层深为 n

示例:

Nest[f, x, 4]
out:f[f[f[f[x]]]]
NestList[f, x, 4]
out:{x, f[x], f[f[x]], f[f[f[x]]], f[f[f[f[x]]]]}

如果我们不想指定重复几次,而是指定一个Boolean条件,则要使用NestWhile。

NestWhile[f,x,test] 重复应用函数 f,直到对结果应用 test 不再产生True

当然也有显示每步的输出结果的NestWhileList。

示例:

NestWhileList[Most, {a, b, c}, # != {} &]
out:{{a, b, c}, {a, b}, {a}, {}}
NestWhile[(#/2) &, 123456, EvenQ]
out:1929    

还有一种循环条件的判定,就是将函数应用到函数值不再改变位置,即FixedPoint。

FixedPoint[f,x] 重复应用函数 f 直到结果不再更改

FixedPointList[f,x] 生成列表 {x,f[x],f[f[x]],…},当元素不再更改时停止

这个对于一些收敛问题十分常用。

二元函数的重复

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[Plus, 0, {a, b, c}]
out:{0, a, a + b, a + b + c}

使用Fold和FoldList可以在 Wolfram 语言中编写许多优雅高效的程序,例如实现FromDigits函数的功能:

digit[a_, b_] := 10 a + b;
fromdigits[digits_] := Fold[digit, 0, digits];
fromdigits[{1, 3, 5, 4, 6}]
out:13546
(*使用纯函数*)
Fold[10 #1 + #2 &, 0, #] &@{1, 3, 5, 4, 6}
out:13546

从上例中不难看出,使用纯函数能够写出高效简洁的函数。

有问题可以留言哦~ 觉得有帮助也可以投喂一下博主,感谢~
文章链接:https://www.corrain.top/mathematica-5/
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明文章地址及作者
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
( ゜- ゜)つロ
_(:з」∠)_
(⌒▽⌒)
( ̄▽ ̄)
(=・ω・=)
(*°▽°*)八(*°▽°*)♪
✿ヽ(°▽°)ノ✿
(¦3【▓▓】
눈_눈
(ಡωಡ)
_(≧∇≦」∠)_
━━━∑(゚□゚*川━
(`・ω・´)
( ̄3 ̄)
✧(≖ ◡ ≖✿)
(・∀・)
(〜 ̄△ ̄)〜
→_→
(°∀°)ノ
╮( ̄▽ ̄)╭
( ´_ゝ`)
←_←
(;¬_¬)
(゚Д゚≡゚д゚)!?
( ´・・)ノ(._.`)
Σ(゚д゚;)
Σ(  ̄□ ̄||)<
(´;ω;`)
(/TДT)/
(^・ω・^)
(。・ω・。)
(● ̄(エ) ̄●)
ε=ε=(ノ≧∇≦)ノ
(´・_・`)
(-_-#)
( ̄へ ̄)
( ̄ε(# ̄) Σ
(╯°口°)╯(┴—┴
ヽ(`Д´)ノ
("▔□▔)/
(º﹃º )
(๑>؂<๑)
。゚(゚´Д`)゚。
(∂ω∂)
(┯_┯)
(・ω< )★
( ๑ˊ•̥▵•)੭₎₎
¥ㄟ(´・ᴗ・`)ノ¥
Σ_(꒪ཀ꒪」∠)_
٩(๛ ˘ ³˘)۶❤
(๑‾᷅^‾᷅๑)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
小黄脸
热词系列一
tv_小电视
上一篇
下一篇