fbpx
维基百科

Icon语言

Icon是一门领域特定高级编程语言,有着“目的(goal)导向执行”特征,和操纵字符串和文本模式的很多设施。它衍生自SNOBOL和SL5字符串处理语言[6]。Icon不是面向对象的,但在1996年开发了叫做Idol的面向对象扩展,它最终变成了Unicon

Icon
编程范型多范型:面向文本, 结构化, 非确定性
設計者Ralph Griswold英语Ralph Griswold
发行时间1977年,​45年前​(1977
当前版本
  • v9.5.23a (2023年8月19日)
  • 951 (2013年6月5日;穩定版本)[1]
型態系統动态
許可證公有领域
網站www.cs.arizona.edu/icon
主要實作產品
Icon, Jcon
衍生副語言
Unicon
啟發語言
SNOBOL[2], SL5[3], ALGOL
影響語言
Unicon, Python[4], Goaldi

历史 编辑

在1971年8月,SNOBOL的设计者之一Ralph Griswold英语Ralph Griswold离开了贝尔实验室,成为了亚利桑那大学的教授[7]。他那时将SNOBOL4介入为研究工具[8]

作为最初在1960年代早期开发的语言,SNOBOL的语法带有其他早期编程语言的印记,比如FORTRANCOBOL。特别是,语言是依赖列的,像很多要录入到打孔卡的语言一样,有着列布局是很自然的。此外,控制结构几乎完全基于了分支,而非使用,而块在ALGOL 60中介入之后,已经成为了必备的特征。在他迁移到亚利桑那的时候,SNOBOL4的语法已然过时了[9]

Griswold开始致力于用传统的流程控制结构如if…then,来实现SNOBOL底层的成功和失败概念。这成为了SL5,即“SNOBOL Language 5”的简写,但是结果不令人满意[9]。在1977年,他考虑设计语言的新版本。他放弃了在SL5中介入的非常强力的函数系统,介入更简单的暂停和恢复概念,并为SNOBOL4自然后继者开发了新概念,具有如下的原则[9]

  • SNOBOL4的哲学和语义基础;
  • SL5的语法基础;
  • SL5的特征,排除广义的过程机制。

新语言最初叫做SNOBOL5,但因为除了底层概念外,全都与SNOBOL有着显著的差异,最终想要一个新名字。在这个时候Xerox PARC出版了他们关于图形用户界面的工作,术语“icon”从而进入了计算机词汇中。起初确定为“icon”而最终选择了“Icon”[9]

基本语法 编辑

Icon语言衍生自ALGOL类的结构化编程语言,因而有着类似CPascal的语法。Icon最类似于Pascal的,是使用了:=语法的赋值,procedure关键字和类似的语法。在另一方面,Icon使用C风格的花括号来结构化执行分组,并且程序开始于运行叫做main的过程。

Icon还在很多方面分享了多数脚本语言(还有SNOBOL及SL5)的特征:变量不需要声明,类型是自动转换的,就说数字和字符串可以自动来回转换。另一个常见于很多而非全部的脚本语言的特征是,缺少行终止字符;在Icon中,不结束于分号的行,若其确有意义则由暗含的分号来终结。

过程是Icon程序的基本建造块。尽管它们使用Pascal名称,但工效上更像C函数并可以返回值;在Icon中没有function关键字。

procedure doSomething(aString) write(aString) end 

目的导向执行 编辑

Icon的关键概念之一就是其控制结构基于表达式的“成功”或“失败”,而非大多数其他编程语言中的布尔逻辑。这个特征直接派生自SNOBOL,在其中表达式求值、模式匹配和模式匹配连带替换,都可以跟随着成功或失败子句,用来指定在这个条件下要分支到一个语句标签。例如,下列代码打印“Hello, World!”五次[10]

* 打印Hello, World!五次的SNOBOL程序  I = 1 LOOP OUTPUT = "Hello, World!" I = I + 1 LE(I, 5) : S(LOOP) END 

要进行循环,在索引变量I之上调用内建的函数LE(小于等于),并且如果S(成功),意味着I小于等于5,它分支到命名标签LOOP并继续下去[10]

Icon保留了基于成功或失败的控制流程的基本概念,但进一步发展了语言。一个变更是将加标签的GOTO式的分支,替代为面向块的结构,符合在1960年代后期席卷计算机工业的结构化编程风格[9]。另一个变更是允许失败沿着调用链向上传递,使得整个块作为一个整体的成功或失败。这是Icon语言的关键概念。而在传统语言中,必须包括基于布尔逻辑的测试成功或失败的代码,并接着基于产出结果进行分支,这种测试和分支是固有于Icon代码的,而不需要明确的写出[11]。考虑如下复制标准输入标准输出的简单代码:

while a := read() then write(a) 

它的含义是:“只要读取不返回失败,调用写出,否则停止”[12]。在Icon中,read()函数返回一行文本或&fail&fail不是简单的Java中的特殊返回值EOF(文件结束)的类似者,因为它被语言依据上下文明确理解为意味着“停止处理”或“按失败状况处理”。这里即使read()导致一个错误它都会工作,比如说如果文件不存在。在这种情况下,语句a := read()会失败,而写操作简单的不调用。

成功和失败将沿着调用链向上传递,意味着可以将函数嵌入其他函数内,在嵌套函数英语nested function失败时,它们整体停止。例如,上面的代码可以精简为[13]

while write(read()) 

read()命令失败的时候,比如在文件结束之处,失败将沿着调用链上传,而write()也会失败。while作为一个控制结构,在失败时停止。Icon称谓这个概念为“目的导向执行”,指称这种只要某个目的达到执行就继续的方式。在上面的例子中目的是读整个文件;读命令在有信息读到的时候成功,而在没有的时候失败。目的因此直接编码于语言中,不用再去检查返回码或类似的构造。

Icon使用目的导向机制用于进行传统的布尔测试,尽管有着微妙的差异。一个简单的比较如if a < b then write("a is smaller than b"),这里的if子句,不像在多数语言中那样意味着:“如果右侧运算求值为真”;转而它的意味更像是:“如果右侧运算成功”。在这种情况下,如果这个比较为真,<算子成功。如果if子句的这个表达式成功,则调用then子句,如果它失败了,则调用else子句或下一行。结果同于在其他语言中见到的传统if…then,如果a小于bif进行then子句。微妙之处是相同的比较表达式可以放置在任何地方,例如:

write(a < b) 

另一个不同是<算子如果成功,返回它的第二个实际参数,在这个例子中,如果b大于a,则导致它的值被写出,否则什么都不写。因为并非测试本身,而是一个算符返回一个值,它们可以串联在一起,允许像if a < b < c这样的事情[13] ,在多数语言中平常类型的比较下,必须写为两个不等式的结合,比如if (a < b) && (b < c)

将成功和失败的概念与异常的概念相对比是很重要的;异常是不寻常的状况,不是预期的结果。在Icon中失败是预期的结果;到达文件的结束处是预期的状况而不是异常。Icon没有传统意义上的异常处理,尽管失败经常被用于类似异常的状况下。例如,如果要读取的文件的不存在,read失败而不指示出特殊状况[12]。在传统语言中,没有指示这些“其他状况”的自然方式,典型的异常处理是“抛出”一个值,下面是用Java处理缺失文件的例子:

try {  while ((a = read()) != EOF) {  write(a);  } } catch (Exception e) {  // 某个事情出错了,使用这个catch来退出循环 } 

这种情况需要两个比较:一个用于文件结束(EOF)而另一个用于所有其他错误。因为Java不允许异常作为逻辑元素来比较,就像Icon中那样,转而必须使用冗长的try/catch语法。try块即使没有异常抛出,也强加了性能上的惩罚,Icon避免了这种分摊成本英语Distributed cost

目的导向执行的一个关键方面,是程序可能必须在一个过程失败时倒转到以前的状态,这个任务叫做回溯。例如,考虑设置一个变量为一个开始位置,并接着进行可以改变这个值的操作,这是在字符串扫描中常见情况,这里前进游标通过它所扫描的字符串。如果这个过程失败了,任何对这个变量的后续读取都返回最初的状态,而非被内部操纵后的状态是很重要的。对于这种任务,Icon有一个“可逆赋值”算子<-,和“可逆交换”算子<->。例如,考虑如下尝试在一个更大字符串内找到一个模式字符串的代码:

{ (i := 10) & (j := (i < find(pattern, inString))) } 

这个代码开始于移动i10,这是查找的开始位置。但是,如果find失败,这个块将作为整体失败,作为一个不想要的副作用,它导致i的值留下为10。故而应将i := 10替代为i <- 10,指示i在这个块失败时应当被重置为它以前的值。这提供了执行中的原子性英语Atomic commit的类似者。

生成器 编辑

在Icon中表达式经常返回一个单一的值,例如5 > x,将求值并且如果x的值小于5则成功并返回x,否则失败。但是,Icon还包括了过程不立即返回成功或失败,转而每次调用它们之时返回一个新值的概念。这些过程叫做生成器,并且是Icon语言的关键部份。在Icon的用语中,一个表达式或函数的求值产生一个“结果序列”。结果序列包含这个表达式或函数生成的所有可能的值。在结果序列被耗尽的时候,这个表达式或函数失败。

Icon允许任何过程返回一个单一值或多个值,使用failreturnsuspend关键字来控制。缺乏任何这种关键字的过程返回&fail,它在执行进行到一个过程的end处的时候发生。例如:

procedure f(x) if x > 0 then { return 1 } end 

调用f(5)将返回1,而调用f(-1)将返回&fail。这将导致不明显的行为,比如write(f(-1))将什么都输出,因为f失败而暂停了write的操作[14]

将一个过程转换成一个生成器,要使用suspend关键字,它意味着“返回这个值,并且在再次调用时,从这一点开始执行”。例如[12]

procedure ItoJ(i, j) while i <= j do { suspend i i +:= 1 } fail end 

建立一个生成器,它返回一系列的数,开始于i并结束于j,接着在它们之后返回&fail[a]suspend i停止执行,并返回i的值,而不重置任何状态。当对相同函数做出另一次调用的时候,执行在这一点上拾起以前的值。在这种情况下,导致它进行i +:= 1,循环回到while的开始处,并接着返回下一个值并再次暂停。这将持续直到i <= j失败,在这一点上它退出这个块并调用fail。这允许轻易的构造迭代器[12]

另一种类型的生成器建造器是“交替英语Alternation (formal language theory)子”(alternator),它的感观和运算就像布尔算子or,例如:

if y < (x | 5) then write("y=", y) 

这看起来是在说“如果y小于x或者5那么...”,实际上它是生成器的一种简写形式,它返回值直到脱离于这个列表的结束处。这个列表的值被注入到运算之中,在这里是<。所以这个例子,系统首先测试y < x,如果x实际上大于y,它返回x的值,这个测试通过,而y的值在then子句中写出。然而,如果x不大于y,它失败了,交替子继续,进行y < 5。如果这个测试通过,写出y。如果y不小于x或者5,交替子用完了,测试失败,if子句失败,而不进行write。因此,y的值如果小于x5,则它将出现在控制台上,从而履行了布尔or的作用。函数不会被调用,除非求值它们的参数成功,所以这个例子可以简写为:

write("y=", (x | 5) > y) 

在内部,交替子不是简单的一个or,它还可以用来构造值的任意列表。这可以用来在任意的一组值上迭代,比如:

every i := (1|3|4|5|10|11|23) do write(i) 

every类似于while,循环经过一个生成器的返回的所有项目,在失败时退出[14]

因为整数列表在很多编程场景都是很常见的,Icon还包括了to关键字来构造“事实上的”整数生成器:

every k := i to j do write(k) 

在这种情况下,从ij的值,将注入到write并写出多行输出[14]。它可以简写为:

every write(i to j) 

Icon不是强类型的,所以交替子列表可以包含不同类型的项目:

every i := (1 | "hello" | x < 5) do write(i) 

这将依赖于x的值,写出1"hello"或可能的5

同样的“合取算符”&,以类似于布尔算符and的方式来使用[15]

every x := ItoJ(0,10) & x % 2 == 0 do write(x) 

这个代码调用ItoJ并返回一个初始值0,它被赋值给x。接着进行合取的右手端,并且因为x % 2不等于0,它写出这个值。接着再次调用ItoJ生成器,它赋值1x,这使得右手端失败而不打印任何东西。最终结果是从010的所有偶数的一个列表[15]

生成器的概念对于字符串操作是很强大的。在Icon中,find函数是个生成器。下面的例子代码,在一个字符串中找出"the"的所有出现位置:

s := "All the world's a stage. And all the men and women merely players" every write(find("the", s)) 

find在每次被every恢复的时候,将返回"the"的下一个实例的索引,最终达到字符串结束处并失败。

当然人们有时会想要找到在输入中某点之后的一个字符串,例如,扫描包含多列数据的一个文本文件。目的导向执行也能起效:

write(5 < find("the", s)) 

只返回"the"出现在位置5之后的那些位置;否则比较会失败。成功的比较返回右手侧的结果,所以把find放置到这个比较的右手侧是重要的。

搜集 编辑

Icon包括了一些搜集类型,包括列表,它还可以用作堆栈队列表格(在其他语言中也叫做映射或字典),和集合英语Set (abstract data type)等。Icon称它们为“结构”。搜集是固有的生成器,并可以使用“叹号语法”来轻易调用。例如:

lines := [] # 建立一个空列表 while line := read() do { # 循环从标准输入读取行 push(lines, line) # 使用类堆栈语法来将行压入列表 } while line := pop(lines) do { # 循环于行可以从列表弹出之时 write(line) # 将行写出 } 

使用如前面例子中见到的失败传播,可以组合测试和循环:

lines := [] # 建立空列表 while push(lines, read()) # 压入直到为空 while write(pop(lines)) # 写直到为空 

由于列表搜集是个生成器,可以使使用叹号语法进一步简化:

lines := [] every push(lines, !&input) every write(!lines) 

在这种情况下,在write内的叹号,导致Icon从数组一个接一个的返回一行文本,并且在结束处失败。&input是基于生成器的read的类似者,它从标准输入读取一行,所以!&input继续读取行直到文件结束。

因为Icon是无类型的,列表可以包含任何不同类型的值:

aCat := ["muffins", "tabby", 2002, 8] 

在列表内的项目可以包括其他结构。为了建造更大的列表,Icon包括了list生成器;i := list(10, "word")生成包含"wold"10个复本的一个列表。

就像其他语言中的数组,Icon允许项目按位置来查找,比如weight := aCat[4]。就像阵列分片英语Array slicing那样,索引是在元素之间的,可以通过指定范围来获得列表的分片,比如aCat[2:4]产生列表["tabby",2002]

表格本质上是具有任意索引键而非仅为整数的列表:

symbols := table(0) symbols["there"] := 1 symbols["here"] := 2 

这个代码建立使用的0作为任何未知键的缺省值的一个table。接着向它增加了两个项目,具有键"there""here",和分别的值12

集合也类似于列表,但是只包含任何给定值的一个单一成员。Icon包括了++来产生两个集合的并集,**用于交集,和--用于差集。Icon包括一些预定义的Cset,即包含各种字符的集合。在Icon中有四个标准Cset&ucase&lcase&letters&digits。可以通过用单引号包围字符串来建造Cset,例如vowel := 'aeiou'.

字符串 编辑

在Icon中,字符串是字符的列表。作为一个列表,它们是生成器,并可以使用“叹号语法”来迭代:

write(!"Hello, world!") 

这将在独立行上打印出字符串的每个字符。

子字符串可以使用在方括号内的一个范围规定从字符串中提取出来。范围规定可以返回到一个单一字符的一个点,或字符串的一个分片(slice)。字符串可以从左或从右索引。在一个字符串内的位置被定义为在字符之间:1A2B3C4,也可以从右规定:−3A−2B−1C0。例如:

"Wikipedia"[1] == "W" "Wikipedia"[3] == "k" "Wikipedia"[0] == "a" "Wikipedia"[1:3] == "Wi" "Wikipedia"[-2:0] == "ia" "Wikipedia"[2+:3] == "iki" 

这里最后例子采用了x1[i1+:i2] : x2表达式,产生x1i1i1 + i2之间的子字符串。

子字符串规定可以用作字符串内的左值。这可以被用来把字符串插入到另一个字符串,或删除字符串的某部份。例如:

s := "abc" s[2] := "123" # s现在的值是"a123c" s := "abcdefg" s[3:5] := "ABCD" # s现在的值是"abABCDefg" s := "abcdefg" s[3:5] := "" # s现在的值是"abefg" 

Icon的下标索引是在元素之间的。给定字符串s := "ABCDEFG",索引是1A2B3C4D5E6F7G8。分片s[3:5]是在索引35之间的字符串,它是字符串"CD"

字符串扫描 编辑

对处理字符串的进一步简化是“扫描”系统,通过?来发起,它在一个字符串上调用函数:

s ? write(find("the")) 

Icon称呼?的左手端为“主语”,并将它传递到字符串函数中。所调用的find接受两个参数,查找的文本作为参数一,而要在其中查找的字符串是参数二。使用?,第二个参数是隐含的,而不由编程者来指定。在多个函数被依次调用在一个单一字符串上的常见情况下,这种风格可以显著的所见结果代码的长度并增加清晰性。

?不是简单的一种语法糖,它还为任何随后的字符串操作,建立一个“字符串扫描环境”。这基于了两个内部变量,&subject&pos,这里的&subject是要扫描的字符串,而&pos是在这个主语字符串内的“游标”或当前位置。例如:

s := "this is a string" s ? write("subject=[",&subject,"] pos=[",&pos,"]") 

将产生:

subject=[this is a string] pos=[1] 

内建和用户定义的函数,可以被用于在要扫描的字符串上移动。所有内建函数缺省采用&subject&pos,来允许用上扫描语法。比如函数tab (i) : s,它设置扫描位置:产生&subject[&pos:i],并将i赋值到&pos。下列例子代码,写出在一个字符串内,所有空白界定出的word

s := "this is a string" s ? { # 建立字符串扫描环境 while not pos(0) do { # 测试字串结束 tab(many(' ')) # 跃过任何空白 word := tab(upto(' ') | 0) # 下一个word是直到下一个空白或行结束 write(word) # 写这个word } } 

这个例子介入了一些新函数。pos返回&pos的当前值。为何需要这个函数,而不简单的直接使用&pos的值,不是显而易见的;原因是&pos是一个变量,而不能呈现值&fail,而过程pos能。因此pos提供对&pos的轻量级包装,它允许轻易使用Icon的目的导向控制流,而不用针对&pos提供手写的布尔测试。在这种情况下,测试是“&pos是零”,在Icon的字符串位置的特异编码中,零是行结束。如果它不是零,pos返回&fail,它通过not反转而使得循环继续。

many从当前&pos开始,找到提供的Cset参数的一个或多个例子。在这种情况下,它查找空格字符,所以这个函数的结果是在&pos之后的第一个非空格字符的位置。tab移动&pos到那个位置,这种情况下再次具有潜在的&fail,例如many在字符结束处脱离。upto本质上是many的反函数;它返回紧前于提供的Cset的例子的位置,接着由另一个tab来设置&pos。这里的交替用来在行结束处也停止。

这个例子通过使用更合适的“字分隔”Cset,可以包括句号、逗号和其他标点,还有其他空白字符如tab和不换行空格,能够变得更加健壮。这个Cset可以接着用于manyupto

一个更复杂的例子演示了在这个语言内生成器和字符串扫描的集成:

procedure main() s := "Mon Dec 8" s ? write(Mdate() | "not a valid date") end # 定义一个匹配函数 # 它返回匹配day month dayofmonth的一个字符串 procedure Mdate() # 定义一些初始值 static dates static days initial { days := ["Mon","Tue","Wed","Thr","Fri","Sat","Sun"] dates := ["Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec"] } every suspend (retval <- tab(match(!days)) || # 匹配一个day =" " || # 跟随着一个空白 tab(match(!dates)) || # 跟随着一个month =" " || # 跟随着一个空白 matchdigits(2)) & # 跟随着最多2位数字 (=" " | pos(0)) & # 要么是空白要么是字符串结束 retval # 最终返回这个字符串 end # 返回最多n位数字的一个字符串的匹配函数 procedure matchdigits(n) suspend (v := tab(many(&digits)) & *v <= n) & v end 

表达式*x计算x的大小。这里介入了内建函数match (s1,s2,i1,i2) : i3,它匹配初始字符串:如果s1 == s2[i1+:*s1],产生i1 + *s1,否则失败;它设定有缺省值:s2&subject,如果s2缺省了,i1&pos,否则为1i20

参见 编辑

注解 编辑

  1. ^ fail在这种情况下是不要求的,因为它紧前于end,增加它是为了清晰性。

引用 编辑

  1. ^ Release 951. 2013年6月5日 [2023年9月19日]. 
  2. ^ Griswold, Ralph E.; Poage, J.F.; Polonsky, Ivan P. The SNOBOL 4 Programming Language 2nd. Englewood Cliffs NJ: Prentice-Hall. 1971. ISBN 0-13-815373-6. 
  3. ^ Ralph E. Griswold, David R. Hanson, "An Overview of SL5", SIGPLAN Notices 12:4:40-50 (April 1977)
  4. ^ Schemenauer, Neil; Peters, Tim; Hetland, Magnus. PEP 255 -- Simple Generators. 2001-12-21 [2008-09-05]. (原始内容于2020-06-05). 
  5. ^ v9.5.22e. [2022-11-09]. (原始内容于2022-11-11). 
  6. ^ Griswold, Ralph E.; Griswold, Madge T. History of the Icon programming language. Bergin, Thomas J.; Gibson, Richard G. (编). History of Programming Languages II. New York NY: ACM Press. 1996. 
  7. ^ Griswold 1981,第609頁.
  8. ^ Griswold 1981,第629頁.
  9. ^ 9.0 9.1 9.2 9.3 9.4 Griswold & Griswold 1993,第53頁.
  10. ^ 10.0 10.1 Lane, Rupert. . Try MTS. 26 July 2015 [2022-02-03]. (原始内容存档于2022-05-09). 
  11. ^ Tratt 2010,第73頁.
  12. ^ 12.0 12.1 12.2 12.3 Tratt 2010,第74頁.
  13. ^ 13.0 13.1 Griswold 1996,第2.1頁.
  14. ^ 14.0 14.1 14.2 Tratt 2010,第75頁.
  15. ^ 15.0 15.1 Tratt 2010,第76頁.

参考书目 编辑

  • Griswold, Ralph; Griswold, Madge. . Peer-to-Peer Communications. 2002 [2020-09-19]. ISBN 1-57398-001-3. (原始内容存档于2020-11-09). 
  • Griswold, Ralph; Griswold, Madge. History of the Icon Programming Language. Communications of the ACM. March 1993, 23 (3): 53–68. 
  • Griswold, Ralph. A History of the SNOBOL Programming Languages. Wexelblat, Richard (编). History of Programming Languages. Academic Press. 1981. 
  • Griswold, Ralph. . Department of Computer Science, The University of Arizona. 2 March 1996 [2022-02-03]. (原始内容存档于2022-04-08). 
  • Tratt, Laurence. (PDF). Proceedings of the 6th symposium on Dynamic Languages. 18 October 2010: 73–80 [2022-02-03]. doi:10.1145/1869631.1869640. (原始内容 (PDF)存档于2021-11-04). 

外部链接 编辑

  • Icon homepage(页面存档备份,存于互联网档案馆
  • Oral history interview with Stephen Wampler, Charles Babbage Institute, University of Minnesota. Wampler discusses his work on the development Icon in the late 1970s.
  • Oral history interview with Robert Goldberg, Charles Babbage Institute, University of Minnesota. Goldberg discusses his interaction with Griswold when working on Icon in the classroom at Illinois Institute of Technology.
  • Oral history interview with Kenneth Walker, Charles Babbage Institute, University of Minnesota. Walker describes the work environment of the Icon project, his interactions with Griswold, and his own work on an Icon compiler.
  • The Icon Programming Language page (页面存档备份,存于互联网档案馆) on The Rosetta Code comparative programming tasks project site

icon语言, icon是一门领域特定的高级编程语言, 有着, 目的, goal, 导向执行, 特征, 和操纵字符串和文本模式的很多设施, 它衍生自snobol和sl5字符串处理语言, icon不是面向对象的, 但在1996年开发了叫做idol的面向对象扩展, 它最终变成了unicon, icon编程范型多范型, 面向文本, 结构化, 非确定性設計者ralph, griswold, 英语, ralph, griswold, 发行时间1977年, 45年前, 1977, 当前版本v9, 2023年8月19日, 201. Icon是一门领域特定的高级编程语言 有着 目的 goal 导向执行 特征 和操纵字符串和文本模式的很多设施 它衍生自SNOBOL和SL5字符串处理语言 6 Icon不是面向对象的 但在1996年开发了叫做Idol的面向对象扩展 它最终变成了Unicon Icon编程范型多范型 面向文本 结构化 非确定性設計者Ralph Griswold 英语 Ralph Griswold 发行时间1977年 45年前 1977 当前版本v9 5 23a 2023年8月19日 951 2013年6月5日 穩定版本 1 型態系統动态許可證公有领域網站www wbr cs wbr arizona wbr edu wbr icon主要實作產品Icon Jcon衍生副語言Unicon啟發語言SNOBOL 2 SL5 3 ALGOL影響語言Unicon Python 4 Goaldi 目录 1 历史 2 基本语法 3 目的导向执行 4 生成器 5 搜集 6 字符串 7 字符串扫描 8 参见 9 注解 10 引用 11 参考书目 12 外部链接历史 编辑在1971年8月 SNOBOL的设计者之一Ralph Griswold 英语 Ralph Griswold 离开了贝尔实验室 成为了亚利桑那大学的教授 7 他那时将SNOBOL4介入为研究工具 8 作为最初在1960年代早期开发的语言 SNOBOL的语法带有其他早期编程语言的印记 比如FORTRAN和COBOL 特别是 语言是依赖列的 像很多要录入到打孔卡的语言一样 有着列布局是很自然的 此外 控制结构几乎完全基于了分支 而非使用块 而块在ALGOL 60中介入之后 已经成为了必备的特征 在他迁移到亚利桑那的时候 SNOBOL4的语法已然过时了 9 Griswold开始致力于用传统的流程控制结构如if then 来实现SNOBOL底层的成功和失败概念 这成为了SL5 即 SNOBOL Language 5 的简写 但是结果不令人满意 9 在1977年 他考虑设计语言的新版本 他放弃了在SL5中介入的非常强力的函数系统 介入更简单的暂停和恢复概念 并为SNOBOL4自然后继者开发了新概念 具有如下的原则 9 SNOBOL4的哲学和语义基础 SL5的语法基础 SL5的特征 排除广义的过程机制 新语言最初叫做SNOBOL5 但因为除了底层概念外 全都与SNOBOL有着显著的差异 最终想要一个新名字 在这个时候Xerox PARC出版了他们关于图形用户界面的工作 术语 icon 从而进入了计算机词汇中 起初确定为 icon 而最终选择了 Icon 9 基本语法 编辑Icon语言衍生自ALGOL类的结构化编程语言 因而有着类似C或Pascal的语法 Icon最类似于Pascal的 是使用了 语法的赋值 procedure关键字和类似的语法 在另一方面 Icon使用C风格的花括号来结构化执行分组 并且程序开始于运行叫做main的过程 Icon还在很多方面分享了多数脚本语言 还有SNOBOL及SL5 的特征 变量不需要声明 类型是自动转换的 就说数字和字符串可以自动来回转换 另一个常见于很多而非全部的脚本语言的特征是 缺少行终止字符 在Icon中 不结束于分号的行 若其确有意义则由暗含的分号来终结 过程是Icon程序的基本建造块 尽管它们使用Pascal名称 但工效上更像C函数并可以返回值 在Icon中没有function关键字 procedure doSomething aString write aString end目的导向执行 编辑Icon的关键概念之一就是其控制结构基于表达式的 成功 或 失败 而非大多数其他编程语言中的布尔逻辑 这个特征直接派生自SNOBOL 在其中表达式求值 模式匹配和模式匹配连带替换 都可以跟随着成功或失败子句 用来指定在这个条件下要分支到一个语句标签 例如 下列代码打印 Hello World 五次 10 打印Hello World 五次的SNOBOL程序 I 1 LOOP OUTPUT Hello World I I 1 LE I 5 S LOOP END 要进行循环 在索引变量I之上调用内建的函数LE 小于等于 并且如果S 成功 意味着I小于等于5 它分支到命名标签LOOP并继续下去 10 Icon保留了基于成功或失败的控制流程的基本概念 但进一步发展了语言 一个变更是将加标签的GOTO式的分支 替代为面向块的结构 符合在1960年代后期席卷计算机工业的结构化编程风格 9 另一个变更是允许失败沿着调用链向上传递 使得整个块作为一个整体的成功或失败 这是Icon语言的关键概念 而在传统语言中 必须包括基于布尔逻辑的测试成功或失败的代码 并接着基于产出结果进行分支 这种测试和分支是固有于Icon代码的 而不需要明确的写出 11 考虑如下复制标准输入到标准输出的简单代码 while a read then write a 它的含义是 只要读取不返回失败 调用写出 否则停止 12 在Icon中 read 函数返回一行文本或 amp fail amp fail不是简单的Java中的特殊返回值EOF 文件结束 的类似者 因为它被语言依据上下文明确理解为意味着 停止处理 或 按失败状况处理 这里即使read 导致一个错误它都会工作 比如说如果文件不存在 在这种情况下 语句a read 会失败 而写操作简单的不调用 成功和失败将沿着调用链向上传递 意味着可以将函数嵌入其他函数内 在嵌套函数 英语 nested function 失败时 它们整体停止 例如 上面的代码可以精简为 13 while write read 在read 命令失败的时候 比如在文件结束之处 失败将沿着调用链上传 而write 也会失败 while作为一个控制结构 在失败时停止 Icon称谓这个概念为 目的导向执行 指称这种只要某个目的达到执行就继续的方式 在上面的例子中目的是读整个文件 读命令在有信息读到的时候成功 而在没有的时候失败 目的因此直接编码于语言中 不用再去检查返回码或类似的构造 Icon使用目的导向机制用于进行传统的布尔测试 尽管有着微妙的差异 一个简单的比较如 span class kr if span span class n a span span class o lt span span class n b span span class kr then span span class nf write span span class p span span class s a is smaller than b span span class p span 这里的if子句 不像在多数语言中那样意味着 如果右侧运算求值为真 转而它的意味更像是 如果右侧运算成功 在这种情况下 如果这个比较为真 lt 算子成功 如果if子句的这个表达式成功 则调用then子句 如果它失败了 则调用else子句或下一行 结果同于在其他语言中见到的传统if then 如果a小于b if进行then子句 微妙之处是相同的比较表达式可以放置在任何地方 例如 write a lt b 另一个不同是 lt 算子如果成功 返回它的第二个实际参数 在这个例子中 如果b大于a 则导致它的值被写出 否则什么都不写 因为并非测试本身 而是一个算符返回一个值 它们可以串联在一起 允许像if a lt b lt c这样的事情 13 在多数语言中平常类型的比较下 必须写为两个不等式的结合 比如if a lt b amp amp b lt c 将成功和失败的概念与异常的概念相对比是很重要的 异常是不寻常的状况 不是预期的结果 在Icon中失败是预期的结果 到达文件的结束处是预期的状况而不是异常 Icon没有传统意义上的异常处理 尽管失败经常被用于类似异常的状况下 例如 如果要读取的文件的不存在 read失败而不指示出特殊状况 12 在传统语言中 没有指示这些 其他状况 的自然方式 典型的异常处理是 抛出 一个值 下面是用Java处理缺失文件的例子 try while a read EOF write a catch Exception e 某个事情出错了 使用这个catch来退出循环 这种情况需要两个比较 一个用于文件结束 EOF 而另一个用于所有其他错误 因为Java不允许异常作为逻辑元素来比较 就像Icon中那样 转而必须使用冗长的try catch语法 try块即使没有异常抛出 也强加了性能上的惩罚 Icon避免了这种分摊成本 英语 Distributed cost 目的导向执行的一个关键方面 是程序可能必须在一个过程失败时倒转到以前的状态 这个任务叫做回溯 例如 考虑设置一个变量为一个开始位置 并接着进行可以改变这个值的操作 这是在字符串扫描中常见情况 这里前进游标通过它所扫描的字符串 如果这个过程失败了 任何对这个变量的后续读取都返回最初的状态 而非被内部操纵后的状态是很重要的 对于这种任务 Icon有一个 可逆赋值 算子 lt 和 可逆交换 算子 lt gt 例如 考虑如下尝试在一个更大字符串内找到一个模式字符串的代码 i 10 amp j i lt find pattern inString 这个代码开始于移动i到10 这是查找的开始位置 但是 如果find失败 这个块将作为整体失败 作为一个不想要的副作用 它导致i的值留下为10 故而应将i 10替代为i lt 10 指示i在这个块失败时应当被重置为它以前的值 这提供了执行中的原子性 英语 Atomic commit 的类似者 生成器 编辑在Icon中表达式经常返回一个单一的值 例如5 gt x 将求值并且如果x的值小于5则成功并返回x 否则失败 但是 Icon还包括了过程不立即返回成功或失败 转而每次调用它们之时返回一个新值的概念 这些过程叫做生成器 并且是Icon语言的关键部份 在Icon的用语中 一个表达式或函数的求值产生一个 结果序列 结果序列包含这个表达式或函数生成的所有可能的值 在结果序列被耗尽的时候 这个表达式或函数失败 Icon允许任何过程返回一个单一值或多个值 使用fail return和suspend关键字来控制 缺乏任何这种关键字的过程返回 amp fail 它在执行进行到一个过程的end处的时候发生 例如 procedure f x if x gt 0 then return 1 end 调用f 5 将返回1 而调用f 1 将返回 amp fail 这将导致不明显的行为 比如write f 1 将什么都输出 因为f失败而暂停了write的操作 14 将一个过程转换成一个生成器 要使用suspend关键字 它意味着 返回这个值 并且在再次调用时 从这一点开始执行 例如 12 procedure ItoJ i j while i lt j do suspend i i 1 fail end 建立一个生成器 它返回一系列的数 开始于i并结束于j 接着在它们之后返回 amp fail a suspend i停止执行 并返回i的值 而不重置任何状态 当对相同函数做出另一次调用的时候 执行在这一点上拾起以前的值 在这种情况下 导致它进行i 1 循环回到while的开始处 并接着返回下一个值并再次暂停 这将持续直到i lt j失败 在这一点上它退出这个块并调用fail 这允许轻易的构造迭代器 12 另一种类型的生成器建造器是 交替 英语 Alternation formal language theory 子 alternator 它的感观和运算就像布尔算子or 例如 if y lt x 5 then write y y 这看起来是在说 如果y小于x或者5那么 实际上它是生成器的一种简写形式 它返回值直到脱离于这个列表的结束处 这个列表的值被注入到运算之中 在这里是 lt 所以这个例子 系统首先测试y lt x 如果x实际上大于y 它返回x的值 这个测试通过 而y的值在then子句中写出 然而 如果x不大于y 它失败了 交替子继续 进行y lt 5 如果这个测试通过 写出y 如果y不小于x或者5 交替子用完了 测试失败 if子句失败 而不进行write 因此 y的值如果小于x或5 则它将出现在控制台上 从而履行了布尔or的作用 函数不会被调用 除非求值它们的参数成功 所以这个例子可以简写为 write y x 5 gt y 在内部 交替子不是简单的一个or 它还可以用来构造值的任意列表 这可以用来在任意的一组值上迭代 比如 every i 1 3 4 5 10 11 23 do write i every类似于while 循环经过一个生成器的返回的所有项目 在失败时退出 14 因为整数列表在很多编程场景都是很常见的 Icon还包括了to关键字来构造 事实上的 整数生成器 every k i to j do write k 在这种情况下 从i到j的值 将注入到write并写出多行输出 14 它可以简写为 every write i to j Icon不是强类型的 所以交替子列表可以包含不同类型的项目 every i 1 hello x lt 5 do write i 这将依赖于x的值 写出1 hello 或可能的5 同样的 合取算符 amp 以类似于布尔算符and的方式来使用 15 every x ItoJ 0 10 amp x 2 0 do write x 这个代码调用ItoJ并返回一个初始值0 它被赋值给x 接着进行合取的右手端 并且因为x 2不等于0 它写出这个值 接着再次调用ItoJ生成器 它赋值1到x 这使得右手端失败而不打印任何东西 最终结果是从0到10的所有偶数的一个列表 15 生成器的概念对于字符串操作是很强大的 在Icon中 find函数是个生成器 下面的例子代码 在一个字符串中找出 the 的所有出现位置 s All the world s a stage And all the men and women merely players every write find the s find在每次被every恢复的时候 将返回 the 的下一个实例的索引 最终达到字符串结束处并失败 当然人们有时会想要找到在输入中某点之后的一个字符串 例如 扫描包含多列数据的一个文本文件 目的导向执行也能起效 write 5 lt find the s 只返回 the 出现在位置5之后的那些位置 否则比较会失败 成功的比较返回右手侧的结果 所以把find放置到这个比较的右手侧是重要的 搜集 编辑Icon包括了一些搜集类型 包括列表 它还可以用作堆栈和队列 表格 在其他语言中也叫做映射或字典 和集合 英语 Set abstract data type 等 Icon称它们为 结构 搜集是固有的生成器 并可以使用 叹号语法 来轻易调用 例如 lines 建立一个空列表 while line read do 循环从标准输入读取行 push lines line 使用类堆栈语法来将行压入列表 while line pop lines do 循环于行可以从列表弹出之时 write line 将行写出 使用如前面例子中见到的失败传播 可以组合测试和循环 lines 建立空列表 while push lines read 压入直到为空 while write pop lines 写直到为空 由于列表搜集是个生成器 可以使使用叹号语法进一步简化 lines every push lines amp input every write lines 在这种情况下 在write内的叹号 导致Icon从数组一个接一个的返回一行文本 并且在结束处失败 amp input是基于生成器的read的类似者 它从标准输入读取一行 所以 amp input继续读取行直到文件结束 因为Icon是无类型的 列表可以包含任何不同类型的值 aCat muffins tabby 2002 8 在列表内的项目可以包括其他结构 为了建造更大的列表 Icon包括了list生成器 i list 10 word 生成包含 wold 的10个复本的一个列表 就像其他语言中的数组 Icon允许项目按位置来查找 比如weight aCat 4 就像阵列分片 英语 Array slicing 那样 索引是在元素之间的 可以通过指定范围来获得列表的分片 比如aCat 2 4 产生列表 tabby 2002 表格本质上是具有任意索引键而非仅为整数的列表 symbols table 0 symbols there 1 symbols here 2 这个代码建立使用的0作为任何未知键的缺省值的一个table 接着向它增加了两个项目 具有键 there 和 here 和分别的值1和2 集合也类似于列表 但是只包含任何给定值的一个单一成员 Icon包括了 来产生两个集合的并集 用于交集 和 用于差集 Icon包括一些预定义的Cset 即包含各种字符的集合 在Icon中有四个标准Cset amp ucase amp lcase amp letters和 amp digits 可以通过用单引号包围字符串来建造Cset 例如vowel aeiou 字符串 编辑在Icon中 字符串是字符的列表 作为一个列表 它们是生成器 并可以使用 叹号语法 来迭代 write Hello world 这将在独立行上打印出字符串的每个字符 子字符串可以使用在方括号内的一个范围规定从字符串中提取出来 范围规定可以返回到一个单一字符的一个点 或字符串的一个分片 slice 字符串可以从左或从右索引 在一个字符串内的位置被定义为在字符之间 sub 1 sub A sub 2 sub B sub 3 sub C sub 4 sub 也可以从右规定 sub 3 sub A sub 2 sub B sub 1 sub C sub 0 sub 例如 Wikipedia 1 W Wikipedia 3 k Wikipedia 0 a Wikipedia 1 3 Wi Wikipedia 2 0 ia Wikipedia 2 3 iki 这里最后例子采用了 span class n x1 span span class p span span class n i1 span span class o span span class p span span class n i2 span span class p span span class p span span class n x2 span 表达式 产生x1在i1和i1 i2之间的子字符串 子字符串规定可以用作字符串内的左值 这可以被用来把字符串插入到另一个字符串 或删除字符串的某部份 例如 s abc s 2 123 s现在的值是 a123c s abcdefg s 3 5 ABCD s现在的值是 abABCDefg s abcdefg s 3 5 s现在的值是 abefg Icon的下标索引是在元素之间的 给定字符串s ABCDEFG 索引是 sub 1 sub A sub 2 sub B sub 3 sub C sub 4 sub D sub 5 sub E sub 6 sub F sub 7 sub G sub 8 sub 分片s 3 5 是在索引3和5之间的字符串 它是字符串 CD 字符串扫描 编辑对处理字符串的进一步简化是 扫描 系统 通过 来发起 它在一个字符串上调用函数 s write find the Icon称呼 的左手端为 主语 并将它传递到字符串函数中 所调用的find接受两个参数 查找的文本作为参数一 而要在其中查找的字符串是参数二 使用 第二个参数是隐含的 而不由编程者来指定 在多个函数被依次调用在一个单一字符串上的常见情况下 这种风格可以显著的所见结果代码的长度并增加清晰性 不是简单的一种语法糖 它还为任何随后的字符串操作 建立一个 字符串扫描环境 这基于了两个内部变量 amp subject和 amp pos 这里的 amp subject是要扫描的字符串 而 amp pos是在这个主语字符串内的 游标 或当前位置 例如 s this is a string s write subject amp subject pos amp pos 将产生 subject this is a string pos 1 内建和用户定义的函数 可以被用于在要扫描的字符串上移动 所有内建函数缺省采用 amp subject和 amp pos 来允许用上扫描语法 比如函数 span class nf tab span span class p span span class n i span span class p span span class p span span class n s span 它设置扫描位置 产生 span class kr amp subject span span class p span span class kr amp pos span span class p span span class n i span span class p span 并将i赋值到 amp pos 下列例子代码 写出在一个字符串内 所有空白界定出的word s this is a string s 建立字符串扫描环境 while not pos 0 do 测试字串结束 tab many 跃过任何空白 word tab upto 0 下一个word是直到下一个空白或行结束 write word 写这个word 这个例子介入了一些新函数 pos返回 amp pos的当前值 为何需要这个函数 而不简单的直接使用 amp pos的值 不是显而易见的 原因是 amp pos是一个变量 而不能呈现值 amp fail 而过程pos能 因此pos提供对 amp pos的轻量级包装 它允许轻易使用Icon的目的导向控制流 而不用针对 amp pos提供手写的布尔测试 在这种情况下 测试是 amp pos是零 在Icon的字符串位置的特异编码中 零是行结束 如果它不是零 pos返回 amp fail 它通过not反转而使得循环继续 many从当前 amp pos开始 找到提供的Cset参数的一个或多个例子 在这种情况下 它查找空格字符 所以这个函数的结果是在 amp pos之后的第一个非空格字符的位置 tab移动 amp pos到那个位置 这种情况下再次具有潜在的 amp fail 例如many在字符结束处脱离 upto本质上是many的反函数 它返回紧前于提供的Cset的例子的位置 接着由另一个tab来设置 amp pos 这里的交替用来在行结束处也停止 这个例子通过使用更合适的 字分隔 Cset 可以包括句号 逗号和其他标点 还有其他空白字符如tab和不换行空格 能够变得更加健壮 这个Cset可以接着用于many和upto 一个更复杂的例子演示了在这个语言内生成器和字符串扫描的集成 procedure main s Mon Dec 8 s write Mdate not a valid date end 定义一个匹配函数 它返回匹配day month dayofmonth的一个字符串 procedure Mdate 定义一些初始值 static dates static days initial days Mon Tue Wed Thr Fri Sat Sun dates Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec every suspend retval lt tab match days 匹配一个day 跟随着一个空白 tab match dates 跟随着一个month 跟随着一个空白 matchdigits 2 amp 跟随着最多2位数字 pos 0 amp 要么是空白要么是字符串结束 retval 最终返回这个字符串 end 返回最多n位数字的一个字符串的匹配函数 procedure matchdigits n suspend v tab many amp digits amp v lt n amp v end 表达式 span class o span span class n x span 计算x的大小 这里介入了内建函数 span class nf match span span class p span span class n s1 span span class p span span class n s2 span span class p span span class n i1 span span class p span span class n i2 span span class p span span class p span span class n i3 span 它匹配初始字符串 如果 span class n s1 span span class o span span class n s2 span span class p span span class n i1 span span class o span span class p span span class o span span class n s1 span span class p span 产生 span class n i1 span span class o span span class o span span class n s1 span 否则失败 它设定有缺省值 s2为 amp subject 如果s2缺省了 i1为 amp pos 否则为1 i2为0 参见 编辑协程注解 编辑 fail在这种情况下是不要求的 因为它紧前于end 增加它是为了清晰性 引用 编辑 Release 951 2013年6月5日 2023年9月19日 Griswold Ralph E Poage J F Polonsky Ivan P The SNOBOL 4 Programming Language 2nd Englewood Cliffs NJ Prentice Hall 1971 ISBN 0 13 815373 6 Ralph E Griswold David R Hanson An Overview of SL5 SIGPLAN Notices 12 4 40 50 April 1977 Schemenauer Neil Peters Tim Hetland Magnus PEP 255 Simple Generators 2001 12 21 2008 09 05 原始内容存档于2020 06 05 v9 5 22e 2022 11 09 原始内容存档于2022 11 11 Griswold Ralph E Griswold Madge T History of the Icon programming language Bergin Thomas J Gibson Richard G 编 History of Programming Languages II New York NY ACM Press 1996 Griswold 1981 第609頁 Griswold 1981 第629頁 9 0 9 1 9 2 9 3 9 4 Griswold amp Griswold 1993 第53頁 10 0 10 1 Lane Rupert SNOBOL Introduction Try MTS 26 July 2015 2022 02 03 原始内容存档于2022 05 09 Tratt 2010 第73頁 12 0 12 1 12 2 12 3 Tratt 2010 第74頁 13 0 13 1 Griswold 1996 第2 1頁 14 0 14 1 14 2 Tratt 2010 第75頁 15 0 15 1 Tratt 2010 第76頁 参考书目 编辑Griswold Ralph Griswold Madge The Icon Programming Language third edition Peer to Peer Communications 2002 2020 09 19 ISBN 1 57398 001 3 原始内容存档于2020 11 09 Griswold Ralph Griswold Madge History of the Icon Programming Language Communications of the ACM March 1993 23 3 53 68 Griswold Ralph A History of the SNOBOL Programming Languages Wexelblat Richard 编 History of Programming Languages Academic Press 1981 Griswold Ralph An Overview of the Icon Programming Language Version 9 Department of Computer Science The University of Arizona 2 March 1996 2022 02 03 原始内容存档于2022 04 08 Tratt Laurence Experiences with an Icon like expression evaluation system PDF Proceedings of the 6th symposium on Dynamic Languages 18 October 2010 73 80 2022 02 03 doi 10 1145 1869631 1869640 原始内容 PDF 存档于2021 11 04 外部链接 编辑維基教科書中的相關電子教程 en Icon ProgrammingIcon homepage 页面存档备份 存于互联网档案馆 Oral history interview with Stephen Wampler Charles Babbage Institute University of Minnesota Wampler discusses his work on the development Icon in the late 1970s Oral history interview with Robert Goldberg Charles Babbage Institute University of Minnesota Goldberg discusses his interaction with Griswold when working on Icon in the classroom at Illinois Institute of Technology Oral history interview with Kenneth Walker Charles Babbage Institute University of Minnesota Walker describes the work environment of the Icon project his interactions with Griswold and his own work on an Icon compiler The Icon Programming Language page 页面存档备份 存于互联网档案馆 on The Rosetta Code comparative programming tasks project site 取自 https zh wikipedia org w index php title Icon语言 amp oldid 79157964, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。