Icon编程语言手册 简略翻译版 第四章

第4章 控制结构

4.1 {e1; e2; ; en }

大括号用于包围表达式序列。除最后一个表达式外,每个表达式都按顺序求值,以产生最多一个值。无论成功还是失败,都将继续并计算序列中的下一个表达式。最后一个表达式en将生成周围上下文允许的尽可能多的值。例如:

    every {writes(" ",1 to 5);writes(" ",6 to 10)}

会输出

    1 6 7 8 9 10

大括号中表达式序列用的分号分隔,也可换成换行,比如上面的可改写成:

    every

    {

        writes(" ",1 to 5)

        writes(" ",6 to 10)

    }

4.2 every do

我们已经看过了every表达式的简单形式:

    every e1

另一种形式是:

    every e1 do e2

也就是说对于e1的每一个值,求e2的值。

• e1生成它能生成的所有值。

• 每次e1生成一个值,就去计算e2。

• 表达式e2可能成功也可能失败。

• 每次计算e2时最多生成一个值。

• 当e1失败时,every-do表达式失败。

它看起来更像是带有do的传统语言中的循环,它更直观。对于break和next表达式,它的行为是不同的,见第4.11节和第4.12节讨论。

“Every-expressions”是表达式,可以放在其他表达式中。这个表达式不产生返回值。和&fail一样,它是终止于失败而不返回值。但是,如果它们由break表达式退出,则可以返回值。参见4.11节

4.3 if then else

写成多行形式:

    if e1

    then

        e2

    else

        e3

if表达式的行为与传统语言中的if语句非常相似,但有以下区别:

• 评估表达式e1以确定其成功或失败。如果e1成功,if表达式的行为类似于e2;如果e1失败,它的行为就像e3一样。

• 表达式e1是生成器的话,e1最多只能生成一个值用于if判断后就终止了。

• e2或e3可以根据上下文的需要生成任意多的值。

与其他语言一样,有一种版本省略了else表达式:

    if e1 then e2

如果省略else子句并且e1失败,则整个if表达式失败。

4.4 目标导向的评估

看下面的程序,求某个直角三角形的边长,其边长之和不小于1000且不大于2000个单位

例8 求一个直角三角形

    procedure main()

        local i,j,m,n

        if

            i:=1 to 2000 &

            j:=i to 2000 &

            n:=i*i+j*j &

            m:=integer(sqrt(n)) &

            m*m = n &

            1000 <= i+j+m <= 2000

        then

            write(i," ",j," ",m)

    end

这是一个以目标为导向的求值示例。目标用测试m*m = n & 1000 <= i+j+m <= 2000表示。计算可以被看作是试图生成达到目标的边i和边j。

在其他编程语言中,您可能必须编写几个嵌套循环才能找到这样的三角形。(顺便说一下,它找到的边是33,544和545。)一旦找到了它,就必须跳出多重循环终止查找。

4.5 case of { }

case表达式的行为类似于其他编程语言中的case或switch语句。一般形式:

    case e1 of {

        e2 : e3

        e4 : e5

        ...

        e2n : e2n+1

        default : e2n+2

    }

等价于

    {

        (tmp := e1)\1 &

        if tmp===(e2) then e3

        else if tmp===(e4) then e5

        ...

        else if tmp===(e2n) then e2n+1

        else e2n+2

    }

相等比较的比较运算符是全称相等检验===。如果给定两个数字,则执行数值检验;如果两个字符串,一个字符串测试。对于其他类型的对象,它测试它们是否为相同的对象。

4.6 while do

一般形式:

    while e1 do e2

while表达式类似于其他编程语言中的while语句。它与every表达式的不同之处在于,它每次迭代最多从e1生成一个值。

简单的来说:

• 计算e1

• 如果e1成功,则计算e2

• e2可能成功也可能失败

• 每次迭代最多从e1生成一个值,最多从e2生成一个值

• 一旦e2被求值,它将重新开始对e1求值

• e1失败则while do表达式失败

有一个没有do子句的版本:

    while e

它从一开始就重复计算e,直到失败。

例如,这里有一个文件复制程序。它把输入复制到输出。如果您从键盘上运行它,它会回写您键入的每一行。

例9 文件复制

    procedure main( )

        while write(read( ))

    end

read过程每次读取一行输入,并在输入完成时失败。

文件副本不能使用every表达式。读取过程不是生成器。当控制向前移动时,每次输入一行,它将返回一行,但在回溯过程中不能恢复;回溯将回溯过去。

这是一个小工具程序,用于在 C 中为bit位置创建定义宏。你可以输入一系列标识符,它将为每个标识符创建一行 #define。这使得每个标识符都成为一个不同的2的幂。也就是说,它将每个标识符设置为不同bit位置的掩码。

例10 定义位

    procedure main()

        i := 1

        while x := read() do

        {

            write("#define ",x," ",i)

            i := i+i

        }

    end

4.7 not

一般形式:

    not e

如果表达式e失败,“not e”将成功;如果e成功,则“not e”失败。

如果“not e”成功(e失败),它将返回“&null”。

因为not是一元操作符,所以它的优先级比任何二元操作符都高。您几乎总是需要将其操作数用圆括号括起来。

4.8 全真逻辑用全否形式写出来

Icon对表达式进行评估,试图找到一些方法使它们成功。成功意味着至少有一种方法可以使它成功。例如,假设我们想知道列表L中是否有两个元素相等。我们可以这样写:

    i:=1 to *L-1 & j:=i+1 to *L & L[i]===L[j]

有时候你想知道某件事是否对所有人都成立,而不是对某个人成立。没有办法直接在Icon中编写。你不得不求助于双重否定。

某事物对所有人都为真,当且仅当没有人对它不为真。

假设我们希望找出一个列表中的所有元素是否都相等。如果所有元素彼此相等,它们就等于第一个元素,所以如果有任何元素不等于第一个元素,那么它们就不都相等。我们可以把测试写成

    not (i:=2 to *L & L[1]~===L[i])

4.9 until do

一般形式:

    until e1 do e2

until表达式的行为类似于

    while not ( e1 ) do e2

简单的来说:

• 计算e1

• 如果e1失败,则计算e2

• e2可能成功也可能失败

• 每次迭代最多从e2生成一个值

• 一旦e2被求值,它将重新开始对e1求值

• 它最多从e1生成一个值,因为一旦e1成功,它就会失败

有一个没有do子句的版本:

    until e

它从一开始就反复求值,直到成功为止。

例如,考虑下面的程序来生成最多100,000的斐波那契数。斐波那契数的序列定义如下:前两个斐波那契数为1;后面的每一个数字都是前面两个斐波那契数的和。

例11 使用until编写斐波那契数

    procedure main()

        local i,j

        i:=1

        j:=1

        until i>100000 do

        {

            write(i)

            i+:=j

            i:=:j

        }

    end

4.10 repeat

一般形式:

    repeat e

将反复计算表达式e。除非通过break、return、suspend或fail等显式退出,否则它永远不会终止。

4.11 break

break表达式用于退出任何类型的循环(every、while、until、repeat)。break有两种形式,单独break和包含表达式的break,如下:

    break

    break expression

对于简单的break,会直接退出当前循环。与循环失败退出不同的是,使用break退出会成功返回表达式的值。如果表达式不存在,则返回&null。

你可以这样写:

    if every {... break ...}

    then exited_by_break()

    else exited_normally()

"break expression"形式会退出循环,并返回表达式生成的值。实际上,表达式会表现得好像不在循环中。如果表达式包含break或next,它们会应用于包含该循环的下一层循环。

例12 使用repeat编写斐波那契数

    procedure main()

        local i,j

        i:=1

        j:=1

        repeat

        {

            write(i)

            i+:=j

            i:=:j

            if i>100000 then break

        }

    end

4.12 next

一般形式:

    next

表达式next使它所在的循环开始下一次迭代。

如果它在every表达式中

    every e1 do e2

它立即导致回溯到表达式e1。

如果它在“while”或“until”之内

    while e1 do e2

    until e1 do e2

会再次计算表达式e1。

如果它在“重复”范围内

    repeat e1

它又开始计算e1。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容