循环控制结构

Wolfram 语言程序的执行涉及到一系列表达式的计算. 在简单程序中,由;分开的表达式将逐个计算,但在一些循环中,某些表达式可能被计算多次.

Do[expr,{i,imax}]i,增量为 ,重复计算 expr
Do[expr,{i,imin,imax,di}]i,增量为 di,重复计算 expr
Do[expr,{i,list}]i 取值于 list,计算 expr
Do[expr,{n}]计算 expr n

简单循环结构.

计算 Print[i^2].
,增量为 ,对 进行赋值.
In[2]:=
Click for copyable input
Out[2]=

Do 中定义的循环方式和函数 TableSum 中的相同. 与这些函数类似,可以使用 Do 循环嵌套.

循环,对每一个 循环.

有时需要进行某一个运算多次,但还不希望改变迭代变量的值. 可以用如 Table 和其它迭代函数中使用的类似方法在 Do 循环中实现这一要求.

重复赋值 三次.
In[4]:=
Click for copyable input
Out[4]=
可以在 Do 循环中使用过程.
Nest[f,expr,n]f 作用于 expr n
FixedPoint[f,expr]expr 开始反复使用 f 直到结果不再改变
NestWhile[f,expr,test]expr 开始反复使用 f 直到 test 的值不为 True

重复使用函数.

Do 对迭代变量的不同值反复计算一个表达式,使用户能进行重复运算. 但用 "函数的重复调用" 节介绍的函数编程结构能编写出更有效的程序. Nest[f,x,n] 等可以对一个表达式反复运用函数.

这里函数 迭代三次.
In[6]:=
Click for copyable input
Out[6]=
对纯函数迭代,也能得出前面使用 Do 的例子中的结果.
In[7]:=
Click for copyable input
Out[7]=

Nest 可以重复运用函数若干次,用时要反复使用函数直到结果不再改变为止,这可以用 FixedPoint[f,x] 来实现.

FixedPoint 重复使用函数直到结果不再改变为止.
In[8]:=
Click for copyable input
Out[8]=

FixedPoint 可用来模仿 Wolfram 语言的计算过程或 等函数运算. FixedPoint 一直重复执行到相继两个结果不再变化为止. 而 NestWhile 一直重复执行到任一个函数不再产生 True 为止.

Catch[expr]计算 expr 直到遇见 Throw[value],返回值为 value
Catch[expr,form]计算 expr 直到 Throw[value,tag] 出现,其中 formtag 匹配
Catch[expr,form,f]返回值为 而不是 value

计算的非局部控制.

遇到 Throw 时停止计算,Catch 的返回值是 的当前值.
In[9]:=
Click for copyable input
Out[9]=

ThrowCatch 提供了在 Wolfram 语言中计算控制的又一方式. 当遇到 Throw 后计算过程停止,Wolfram 语言就返回到最近的一个 Catch.

Scan 使用 Print 函数在每个元素上,最后返回值为 Null.
遇到 ThrowScan 的计算结束,所含的 Catch 返回值是 Throw 变量的值.
In[11]:=
Click for copyable input
Out[11]=
Map 也可以得到同样的结果,当计算过程不是遇到 Throw 时结束,Map 的返回值是一个集合.
In[12]:=
Click for copyable input
Out[12]=

ThrowCatch 可以改变函数的编程结构,使得计算过程到一定条件出现时结束. 注意,用 Throw 结束的计算的结果可能和计算全部完成得到的结果不一样.

反复使用一个函数得到的集合.
In[13]:=
Click for copyable input
Out[13]=
由于没有遇到 Throw,所有结果与前面相同.
In[14]:=
Click for copyable input
Out[14]=
现在 NestList 的计算被改变,显示的是 Throw 变量的返回值.
In[15]:=
Click for copyable input
Out[15]=

ThrowCatch 完全以一种全局的方式运行,不管哪儿或怎样出现 Throw,它都使计算停止,回到所包含的 Catch.

Throw 停止 计算,使 Catch 的返回值为 没有任何信息留下.
In[16]:=
Click for copyable input
Out[16]=
这里定义一个当其自变量的值大于10时就产生 Throw 函数.
In[17]:=
Click for copyable input
此处没有出现 Throw.
In[18]:=
Click for copyable input
Out[18]=
但这里在 的计算过程中产生的 Throw 返回到了所包含的 Catch.
In[19]:=
Click for copyable input
Out[19]=

在小的程序中,用 Throw[value]Catch[expr] 的最简单形式是合适的. 但在包含许多块的程序中,最好用Throw[value,tag]Catch[expr,form]. 通过保持表达式 tagform 在程序的某一块中,就可以保证 ThrowCatch 也在这一块中运行.

这里内部的 Catch 用到 Throw.
In[20]:=
Click for copyable input
Out[20]=
但这里仅外面的 Catch 用到了 Throw.
In[21]:=
Click for copyable input
Out[21]=
可以用模式去指定哪个 Catch 应该捕获标志.
In[22]:=
Click for copyable input
Out[22]=
这里保证标志 是局部的.
In[23]:=
Click for copyable input
Out[23]=

应该认识到当 Throw 是常数时没有必要用标志; 一般来说它可以是任何表达式.

这里内部的 Catch 用标志小于4的所有 throw,继续进行 Do 循环. 档标志达到4时,就用外面的 Catch.
In[24]:=
Click for copyable input
Out[24]=

使用 Catch[expr,form]Throw[value,tag] 时,Catch 的返回值是 Throw 中的 value. 使用Catch[expr,form,f] 时,Catch 的返回值是 .

作用于 Throw 中的 value 和 tag 上.
In[25]:=
Click for copyable input
Out[25]=
Throw 时,就不使用 .
In[26]:=
Click for copyable input
Out[26]=
While[test,body]test 值为 True 是反复计算 body
For[start,test,incr,body]计算 start,接下来反复计算 bodyincr,直到 test 的值为 False 时停止

一般的循环结构.

DoNestFixedPoint 等函数在 Wolfram 语言中用来进行循环,而 ThrowCatch 可以用来修改这种结构. 有时需要建立没有结构的循环,用 WhileFor 就能方便地做到这一点,它们反复进行运算,直到某条件不成立时停止.

While 循环一直进行到条件不成立时结束.

Wolfram 语言的 WhileFor 函数与C语言中的 控制结构类似. 但也有些重要的区别. 例如, Wolfram 语言 For 循环和C语言中的逗号和分号的位置正好相反.

这是一个常用的 For 循环. 使 增加.
这是一个更复杂的 For 循环. 当条件 不成立时结束循环.

在 Wolfram 语言中的 WhileFor 循环中,总是先测试条件是否成立,然后再进行循环的计算. 当循环测试结果不为True 时,WhileFor 循环结束. 所以,循环体仅在测试结果为 True 时计算.

循环条件不成立,故循环体没有进行计算.
In[30]:=
Click for copyable input

While 循环、For 循环以及 Wolfram 语言的过程中,Wolfram 语言表达式按确定的顺序进行计算. 可以将这种顺序看作 Wolfram 语言程序执行中的控制流.

大部分情况下应该是 Wolfram 语言程序的控制流尽可能的简单. 控制流对于执行过程中产生的值依赖越多,理解该程序运行结构就越困难.

功能编程结构涉及非常简单的控制流. 由于 WhileFor 循环中的控制流依赖于测试条件的值,它们是较复杂的. 即使在这样的循环中,控制流一般不依赖于循环体中表达式的值.

在一些情况中,Wolfram 语言程序中的控制流受一个过程执行中所产生结果的影响,或受循环体所产生结果的影响. 处理这种情况的一个方法是用 ThrowCatch. Wolfram 语言也提供了修改控制流的其它函数,这与C语言中的情况类似.

Break[]退出最接近的内循环
Continue[]进行本循环的下一步
Return[expr]返回函数中的值 expr
Goto[name]转入当前过程中的 Label[name] 元素
Throw[value]value 作为最接近的 Catch 的返回值 (非局部返回)

流程控制函数.

大于 时, Break[] 导致循环结束.
时,Continue[] 使循环跳过 继续执行.

Return[expr] 使程序退出一个函数,得到一个返回值. 可以将 Throw 看作一个非局部返回,因为它退出了整个嵌套函数列,这种特性在处理一些错误条件时非常方便.

这里提供了一个使用 Return 的例子. 在以下这个特例中,如果不使用 Return,过程也一样正常运行.
In[33]:=
Click for copyable input
当变量的值大于5时,使用第一个 Return.
In[34]:=
Click for copyable input
Out[34]=
当变量值为负时,这一函数给出 错误提示.
In[35]:=
Click for copyable input
这里没有 Throw 错误.
In[36]:=
Click for copyable input
Out[36]=
这里产生了 ThrowCatch 的返回值是 .
In[37]:=
Click for copyable input
Out[37]=

Continue[]Break[] 函数等可以使 Wolfram 语言程序转到循环开始或结束循环. 有时,还需要将程序转到过程的某一处. 如果在过程中给出作为元素的 Label,就可以使用 Goto 语句转到该处去.

循环进行到 超过 时结束.

只有在 Label 作为元素出现的同一 Wolfram 语言过程中,才能使用对这个特定 Wolfram 语言过程使用 Goto. 一般来说,使用 Goto 语句可以简化程序结构,但程序的运行过程却复杂了一些.