Icon (编程语言)
✍ dations ◷ 2025-02-27 12:31:16 #动态类型编程语言,模式匹配编程语言,公有领域软件,面向文本编程语言,1977年建立的编程语言
Icon是一门非常高级编程语言,有着“目的(goal)导向执行”特征和管理字符串和文本模式的很多设施。它与SNOBOL和SL5字符串处理语言有关。Icon不是面向对象的,但在1996年开发了叫做Idol的面向对象扩展并最终变成了Unicon。
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,在其中任何模式匹配和/或替换操作,都可以跟随着成功和/或失败子句,它指定在这个必备条件下要分支到一个语句标签。在这种目的导向分支模型下,一个简单的比较如if a < b
不意味着:“如果对右侧的操作运算的求值为真”,就像在多数语言中那样;转而它的意味更像是:“如果对右侧的操作运算成功了”。在这种情况下, <
算子成功,如果这个比较为真,所以结束结果是相同的。此外, <
算子如果成功返回它的第二个实际参数,允许像if a < b < c
这样的事情,在多数语言中平常类型的比较下必须写为两个不等式的结合比如if (a < b) && (b < c)
。
Icon对所有流程控制使用成功或失败,所以如下这个简单代码:
if a := read() then write(a)
将复制一行标准输入到标准输入。即使read()
导致一个错误它都会工作,例如,如果文件不存在。在这种情况下语句a := read()
会失败,而写操作简单的不调用。
成功和失败将通过函数“向上”传递,意味着在嵌套函数(英语:nested function)内的失败将导致调用它的函数也失败。例如,下面是复制整个文件的一个程序:
while write(read())
在read()
命令失败的时候,比如在文件结束之处,失败将沿着调用链上传,而write()
也会失败。while
作为一个控制结构,在失败时停止。类型的例子可以用伪代码写成(使用类似Java的语法):
try { while ((a = read()) != EOF) { write(a); } } catch (Exception e) { // do nothing, exit the loop }
这种情况需要两个比较:一个用于文件结束(EOF)而另一个用于所有其他错误。因为Java不允许异常作为逻辑元素来比较,就像Icon中那样,转而必须使用冗长的try/catch
语法。try
块还强加了性能上的惩罚,即使没有异常抛出,Icon避免了这种分配的代价。
Icon称谓这个概念为“目的导向执行”,指称这种只要某个目的达到执行就继续的方式。在上面的例子中目的是读整个文件;读命令在有信息读到的时候成功,而在没有的时候失败。目的因此直接编码于语言中,不用再去检查返回码或类似的构造。
在Icon中表达式经常返回一个单一的值,例如x < 5
,将求值并且如果x
的值小于5
则成功,否则失败。但是,很多表达式在返回值的同时,不“立即”返回成功或失败。下面用every
和to
来驱动例子;every
导致to
继续返回值,直到失败。
这是Icon中的一个关键概念,叫做生成器。生成器驱动了在语言中多数的循环功能,但是不需要在每次迭代都显式循环比较值。
在Icon的用语中,一个表达式活函数的求值产生一个“结果序列”。结果序列包含这个表达式或函数生成的所有可能的值。在结果序列被耗尽的时候,这个表达式或函数失败。完成在结果序列上的迭代,要么隐式的通过Icon的目的导向求值,要么显式的通过every
子句。
Icon包括一些生成器建造器。“轮选器”(alternator)语法允许一系列项目被生成于一个序列中,直到其中一个失败:
1 | "hello" | x < 5
可以生成1
、hello
和5
如果x
小于5
的话。轮选器在很多情况下可以读作“或”,例如:
if y < (x | 5) then write("y=", y)
将写出y
的值,如果它小于x
或5
。Icon在内部从左至右的检查所有的值,直到一个成功,或列表成空从而它返回一个失败。函数将不被调用,除非求值它们的形式参数成功,所以这个例子可以简写成:
write("y=", (x | 5) > y)
另一个简单的生成器是to
,它生成整数的列表;every write(1 to 10)
将调用write()
10
次。“叹号语法”生成一个列表的所有项目;every write(!aString)
将输出aString
的每个字符于一个新行上。
这个概念对于字符串操作是很强大的。多数语言包含一个函数叫做find
或indexOf
,返回一个字符串在另一个字符串中的位置。例如:
s = "All the world's a stage. And all the men and women merely players"; i = indexOf("the", s)
这将返回4
,这是单词"the"
的首次出现位置(假定索引起始于0
)。要得到"the"
的下一个实例,必须使用替代的形式:
i = indexOf("the", s, 5)
在结束处的5
应当从位置5
可是查找。所以要提取出"the"
的所有出现,必须使用循环:
s = "All the world's a stage. And all the men and women merely players"; i = indexOf("the", s) while i != -1 { write(i); i = indexOf("the", s, i+1); }
在Icon中,find
函数是个生成器,在每次被恢复(resume)的时候,它将返回这个字符串的下一个实例,直到它达到字符串结束处而失败。相同的代码可以写为:
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
放置到这个比较的右手侧是重要的。如果写成了:
write(find("the", s) > 5)
则写出来的是5
而不是find
的结果。
Icon增加了一些循环经过生成器的控制结构。every
类似于while
,循环经过一个生成器的所有项目,在失败时退出:
every k := i to j do write(someFunction(k))
while
重新求值第一个结果,而every
产生所有结果。every
语法实际上以类似于在Smalltalk下的块的风格,将值注入函数中。例如,上面的循环可以用这种方式重新写为:
every write(someFunction(i to j))
生成器可以定义为使用suspend
关键字的过程:
procedure findOnlyOdd(pattern, theString) every i := find(pattern, theString) do if i % 2 = 1 then suspend i end
这个例子在theString
上循环,使用find
来查找pattern
。当找到一个位置并且它是奇数的时候,用suspend
从这个函数返回这个位置。不同于return
,suspend
记住这个生成器的状态,允许在下次迭代时在上次中止的地方恢复。
Icon有个特征使得处理字符串更加容易。“扫描”系统重复的在一个字符串上调用函数:
s ? write(find("the"))
是前面例子的简短形式。在这个情况下,find
函数的“主语”被放置在形式参数之外,就是问号之前。Icon函数签名标识主语形式参数,所以它可以用这种方式提升起来。
子字符串可以使用在方括号内的一个范围规定从字符串中提取出来。范围规定可以返回到一个单一字符的一个点,或字符串的一个分片(slice)。字符串可以从左或从右索引。在一个字符串内的位置被定义为在字符之间:1A2B3C4
,也可以从右规定:−3A−2B−1C0
。例如:
"Wikipedia" == "W" "Wikipedia" == "k" "Wikipedia" == "a" "Wikipedia" == "Wi" "Wikipedia" == "ia" "Wikipedia" == "iki"
这里的最后的例子展示了使用长度而非结束位置。
子字符串规定可以用作字符串内的左值。这可以被用来把字符串插入到另一个字符串,或删除字符串的某部分。例如:
s := "abc" s := "123" #s现在的值是"a123c" s := "abcdefg" s := "ABCD" #s现在的值是"abABCDefg" s := "abcdefg" s := "" #s现在的值是"abefg"
Icon的下标索引是在元素之间的。给定字符串s := "ABCDEFG"
,索引是1A2B3C4D5E6F7G8
。分片s
是在索引3
和5
之间的字符串,它是字符串"CD"
。
Icon还有建造列表(或数组)的结构:
aCat :=
在列表内的项目可以具有任何类型,包括其他结构。为了建造更大的列表,Icon包括了list
生成器;i := list(10, "word")
生成包含"wold"
的10
个复本的一个列表。
就像其他语言中的数组,Icon允许项目按位置来查找,比如weight := aCat
。就像字符串那样,索引是在元素之间的,可以通过指定范围来获得列表的分片,比如aCat
产生列表
。不同于字符串,列表的分片不是左值。
“叹号语法”列举一个范围。例如every write(!aCat)
将打印出4行,每行一个元素。
Icon包括堆栈类函数,push
和pop
允许用数组形成堆栈和队列的基础。
Icon还通过“表格”包括了集合和关联数组的功能:
symbols := table(0) symbols := 1 symbols := 2
这个代码建立使用的0
作为任何未知键的缺省值的一个table
。接着向它增加了两个项目,具有键"there"
和"here"
,和分别的值1
和2
。
Icon的强力特征之一是字符串扫描。扫描算子?
,保存当前的字符串扫描环境并建立一个新的字符串扫描环境。字符串扫描环境构成自两个关键字变量,&subject
和&pos
,这里的&subject
是要扫描的字符串,而&pos
是在这个主语字符串内的“游标”或当前位置。例如:
s := "this is a string" s ? write("subject= pos=")
将产生:
subject= pos=
内建和用户定义的函数可以被用来在要扫描的字符串上移动起来。很多内建函数缺省采用&subject
和&pos
(例如find
函数)。下列例子将写出在一个字符串内所有空白界定出的word
:
s := "this is a string" s ? { # 建立字符串扫描环境 while not pos(0) do { # 测试字串结束 tab(many(' ')) # 跃过任何空白 word := tab(upto(' ') | 0) # 下一个word是直到下一个空白或行结束 write(word) # 写这个word } }
一个更复杂的例子演示了在这个语言内生成器和字符串扫描的集成:
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 := dates := } 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
惯用法expr1 & expr2 & expr3
返回最后的表达式的值。
相关
- 戊二醛戊二醛,结构式OHC(CH2)3CHO。无色透明有刺鼻气味的油状液体。不易溶于水,与热水互溶,易溶于乙醇和乙醚等有机溶剂。易聚合,必要时可加甲醇或脂肪醇聚乙二醇醚型非离子型表面活性
- 巴西-印度巴西-印度关系指的是巴西联邦共和国与印度共和国之间的双边外交关系。巴西和印度两国都曾为葡萄牙帝国的殖民地,故此两国在很早以前就建立了关系。巴西与印度在国际贸易、气候
- 2004 XR190425–850 km (albedo 0.16-0.04)
335–530 km (albedo 0.25-0.10)2004 XR190(也可以写成2004 XR190)是一颗位于离散盘的外海王星天体。它是由英国哥伦比亚大学的天文学家 L
- Nasub2/subHsub2/subPsub2/subOsub7/sub>酸式焦磷酸钠,化学式Na2H2P2O7。酸式焦磷酸钠是一种白色单斜结晶性粉末或熔融状固体,溶于水,不溶于乙醇。稍有吸湿性,吸水后形成六水合物。水溶液用稀酸加热则水解成磷酸。加热
- San Antonio, Texas圣安东尼奥(英语:San Antonio)位于美国得克萨斯州中南部,是美国得克萨斯州人口第二多的城市(排在休斯敦之后),同时也是美国人口第七多的城市。据2005年美国人口普查局估计,圣安东尼
- 老板键老板键(英语:Boss key),是一种电脑的热键或热键组合,用于快速隐藏游戏或其他无关工作的程序,并让显示器呈现正常工作时的画面,藉以欺瞒老板、上司和同事,使之以为上班时间进行娱乐的
- 黑马羚黑马羚(学名:)是生活在东非大草原的肯尼亚和南非的一种羚羊。包括三个亚种:黑马羚肩高120-140厘米,体重200-270千克,雄性体型大于雌性。雌性黑马羚的体色为栗色或深褐色,雄性则为黑
- 量能器 (粒子物理)在粒子物理中,量能器是一种测量粒子能量的实验装置。在粒子加速器中,大多数粒子最终进入量能器并放出粒子簇射,粒子的能量会在量能器释放、被收集然后被测量。能以一种连续的材
- 本·扬斯本·扬斯(英语:Ben Youngs;1989年9月5日-)是一位英格兰橄榄球运动员。他是英格兰国家橄榄球队的一员,代表英格兰参加了2015年世界杯橄榄球赛。
- Music Macro LanguageMusic Macro Language是电脑上所使用表示乐谱的语言之一,它以循序的方式来表示乐谱。它有可能会和以XML技术发展的Music Markup Language搞混,因两者缩写皆为MML,且HTML与XML都