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

第五章 过程

5.1 过程调用

过程调用的形式是:

    expr0 ( expr1 , expr2 , ..., exprn )

• 表达式 expr0 的值为一个过程值。

• 最常见的是,expr0是一个全局名称,该名称由过程声明或作为内置函数的名称

• 表达式 expr0 可能是一个求值或生成过程的表达式,例如,(F|G)(x,y) 将调用 F(x,y),然后如果回溯,将调用 G(x,y)。

• 实际参数列表,expr 1, expr2,…, expr n,可以为空。

• 实际提供的参数数量可以大于或小于过程声明中指定的参数数量。额外的参数将被忽略。缺失的参数被赋值为&null。

• 表达式可以从实际参数列表中省略,例如F(, 2, , 4)。缺失的参数被赋值为&null。

• 数按值传递。如果参数列表中有变量,则将其值传递给过程。但是,Icon会一直等到调用时才获取变量的当前值。例如

    write(x:=1," ",x+:=1," ",x+:=1)

会输出

    3 3 3

因为每个赋值返回变量x,而 write 在调用前完成其中表达式的求值。

• 参数从左到右求值。所有这些都必须在调用过程之前成功地给出一个值。

• 只要控制回溯到该过程,它就会为参数生成的每组值调用该过程。

• 过程本身可能失败,可能返回一个值,或者可能生成一个值序列。

• 该过程可以返回或生成可以赋值的变量。

5.2 过程声明

过程声明的形式是

    procedure name (formal1 , formal2 ,..., formaln )

        declarations

        initial_expression_option

        expression_sequence

    end

• 过程声明创建了一个过程值。

• 过程的名称成为一个全局变量,并初始化为该过程值。

• 过程值可以赋值给其他变量并放入数据结构中。

• 列表 formal 1, formal 2,..., formal n 是一个由逗号分隔的零个或多个标识符的列表。它们是过程的形式参数。

• 每个形式参数被赋值为相应的实际参数的值。由于可变对象是通过指针访问的,因此指针被复制到形式参数上,形式参数和实际参数都指向同一个对象,这类似于按引用调用。

• 如果实际参数多于形式参数,则多余的实际参数将被忽略。

• 如果实际参数少于形式参数,则额外的形式参数将被赋值为初始值 &null。

• 你可以通过在最后一个形式参数 formal n 后面加一对括号 [] 来编写一个接受可变数量参数的过程。从 n 开始的所有实际参数将被放入一个列表中,并赋值给 formal n。(列表的内容在第9章讨论。)

• 允许的声明有局部和静态声明。请参见第2.3节

• 初始表达式是可选的。它在第5.7节

• expression_sequence 类似于大括号 {...} 中的表达式序列——表达式按顺序求值,每个表达式产生一个单一值或失败。每个表达式都是有界的:一旦产生了值,就不会回溯进入该表达式。

• 如果完成了表达式序列的执行并到达末尾,过程调用失败。

例13 八进制的位位置

    procedure oct(i)

        return if i = 0 then "0" else oct(i / 8) || i % 8

    end


    procedure main()

        i := 1

        while x:= read() do

        {

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

            i +:= i

        }

    end

5.3 参数的默认值

参数的默认值如下:

    / parameter_name := default_value

如果调用者没有提供实际参数,Icon提供&null。“/”将测试参数的值,只有当参数为&null时才会成功。&null被替换为默认值。

5.4 Return

过程通过执行“return 表达式”来返回一个值。

    return e

    return

返回的行为如下:

• 如果return后无表达式e,则过程返回&null。

• 如果return后有表达式e,则过程将e的值返回给调用者。

• 如果return后有表达式e,并且表达式e失败,则过程调用失败,导致调用方进行回溯。

• return不创建生成器,过程不会暂停。不能重新输入以生成另一个值。最多返回一个值。

• 如果e是一个变量,但不是声明为局部或静态的变量,则从过程返回该变量。也就是说,您可以为过程返回的内容赋值。您可以在“:=”的左侧使用过程调用。无法返回局部变量,因为它在过程返回后不再存在。

下面的过程,它将返回两个数字中的最大值:

例14 两个数字中的最大值

    procedure max2(x,y)

        x <:= y

        return x

    end

5.5 Fail

fail表达式

    fail

导致此过程的调用失败。失败将使调用者导致回溯。

5.6 Suspend

使用suspend将过程转换为生成器。挂起的行为类似于返回,除了它将过程作为生成器离开,准备被恢复以尝试生成更多的值。格式见下:

    suspend e1 do e2

    suspend e1

    suspend

suspend 有以下行为:

• suspend 计算其包含的表达式e1,并将e1生成的每个值传递给调用者。它类似于返回,但是过程在返回一个值后不会消失。

• 当调用者返回到过程调用时,控制返回到过程,如果存在则执行e2,并返回到表达式e1以生成下一个值。

• 当表达式e1无法生成更多的值时,就从suspend中退出,就像从every中退出一样。如果它未能生成任何值,则控制继续移动,而不为suspend的调用者提供任何值。

• suspend 后面无表达式e1时,suspend将&null返回给调用者。

• 如果e1是变量,但不是局部声明的变量,则从过程返回该变量。也就是说,您可以为过程生成的变量赋值。您可以在“:=”的左侧使用过程调用。

例15 suspend演示

    procedure G()

        suspend |writes(" e1")\3 do writes(" e2")

        write()

        suspend |writes(" e3")\2

        write()

    end


    procedure main()

        every G() do writes(" e4")

    end

会输出

    e1 e4 e2 e1 e4 e2 e1 e4 e2 e3 e4 e3 e4

5.7 Initial

静态声明声明过程中的变量,在调用之间保留它们的值。当然,问题出现在第一次调用过程时:变量没有以前的值。Icon通过初始声明提供了一种解决此问题的方法:

    initial e

它出现在过程开始时的声明之后,在作为过程主体的表达式序列之前。

所包含的表达式e只在第一次调用过程时执行一次。

初始表达式用于初始化过程中声明的静态变量。它还用于初始化过程集合共享的一些全局变量。

假设您有两个过程,enqueue(x)和dequeue(),它们用于将项放入共享队列(实现为列表)中并从中移除项。它们需要初始化该列表,因此可以这样写(省略实际代码):

例16 使用initial

    procedure enqueue(x)

        initial /queue:=list()

        ...

    end

    procedure dequeue()

        initial /queue:=list()

        ...

    end

它们都检查队列是否已经初始化,如果还没有初始化,则对其进行初始化。通过使用初始表达式,他们避免了每次检查。

5.8 字符串调用

可以通过在字符串中提供过程名来调用过程。例如,如果声明了一个过程f,就可以调用它:

    "f"(x)

然而,最近Icon已经被优化以节省空间,所以你必须告诉它保留你希望通过它们的名字调用的函数的名字。你可以用两种方式来做:

1) 编译命令的参数

    icont -fs ...

用 -fs 指定保留函数的名称。

2) 为您可以通过字符串名称调用的每个过程用invocable声明下,例如:

    invocable "f"

在程序中与全局声明处于同一级别,即外部过程。请确保将过程名称用引号括起来。

或使所有过程都可调用,用

    invocable all

5.9 将过程应用于列表

假设您希望过程P用放在列表L中元素做参数。使用中缀运算符“!”:

    P ! L

    P ! [a,b]

5.10 适用于过程的函数

有几个内置函数可以处理过程对象。函数args报告一个过程所需的参数数量。函数proc将返回以字符串命名的过程。对于过程的字符串调用来说,这似乎没什么用,但它也将给出与操作符对应的过程,并允许您在一元和二元,或二元和三元之间进行选择。此外,在Icon程序库中还有两个有用的程序。prockind将告诉您过程对象是哪种过程。procname将返回一个过程的名称。

args(p)  #返回过程p所需的参数数。如果p是具有可变参数数量的用户过程,args(p)返回声明p时使用的参数数量的负数。如果p是具有可变数量参数的内置过程,则args(p)返回-1。

proc(s)  #s是字符串表示的一个过程名,返回此过程。比如:proc("max2") ! [2,3]。但需要先invocable "max2"

proc(s,i)  #返回名称为字符串s的操作符的过程,该操作符接受i个参数,例如:

proc("*",1)(x) *x

proc("*",2)(x,y) x*y

proc("[]",2)(x,y) x[y]

proc("[:]",3)(x,y,z) x[y:z]

proc("...",2)(x,y) x to y

proc("...",3)(x,y,z) x to y by z

prockind(x)  #如果x不是以下类型,则失败。否则,如果x是记录构造函数,则返回“c”;如果x是内置函数,则返回“f”;如果x是操作符,则返回“o”;如果x是用户定义过程,则返回“p”。

procname(x)  #返回过程值x的名称(也可以是记录构造函数或运算符),如果x不是过程则失败。如果x是一个操作符,则其名称的右边会加上它的形参数,例如:

    procname(write) yields "write"

    procname(proc("...",3)) yields "...3"

type(p)  #这是获取类型函数。p是一个过程的话,返回字符串"procedure"

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容