美文网首页码农
Icon编程语言手册 简略翻译版 第四章

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

作者: FSS_Sosei | 来源:发表于2024-11-06 13:43 被阅读0次

    第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。

    相关文章

      网友评论

        本文标题:Icon编程语言手册 简略翻译版 第四章

        本文链接:https://www.haomeiwen.com/subject/uipadjtx.html