Io语言是一门简单小巧采用原型编程范式的弱类型动态语言。虚拟机只有10K左右。初次遇见Io,你一定会惊叹于它的简洁。从Io官网就可以看出来,作者Steve Dekorte是个极度崇尚简洁的人。
关于Io的简介和入门,参见我的另一篇文章或直接去Io官网。
在io里,一切皆对象。对象呢,其实就是槽(Slot)的容器,槽包含对象,包括方法对象。所有的动作(可以理解为方法)都是消息(消息也是对象),每个消息都会返回一个对象,类似ruby默认返回消息体中最后操作的对象。喜欢写链式代码的coder有福了~
看两个例子:
// OSC没有专门的io语言着色功能,先借用下shell的
File with("text.txt") contents // 读取文件内容 Direcotry files select(name containsSeq("bak") not) map(name) sort // 列出当前目录所有不包含bak的文件名并排序
对了,io没有关键字,像if、for、while之类的东西,其实都是消息,它们只是Object对象上的几个槽而已。也包含运算符。io里的消息可以重定义,也就是说,我们可以无条件地覆盖系统里已有的各种消息。
举个例子,“[]”在io里等价于squareBrackets,这样,我们只要定义一个squareBrackets方法就可以对[]重定义。这里,我把[]定义为一个由列表组成的多维数组。
squareBrackets := method( list := List clone if(call message arguments asString containsSeq("square") not,return call message arguments) //如果不含子数组就直接返回list call message arguments foreach(arg, aArg := if(arg asString beginsWithSeq("squareBrackets"),doMessage(arg),arg) list append(aArg)// 最后一行为返回值 ) list )
Io>[1,2,[3,4,[5,6]]]
==> list(1, 2, list(3, 4, list(5, 6)))
《7周7语言》里还有一个更好的例子,定义了curlyBrackets方法而把{}变成了读取电话本的恰当应用。当然也可以重定义像"+","-","*","/"等操作。所以使用io进行DSL编程非常的方便。
io作为一门原型语言,其对象关系模型也十分清晰。使用protos就可以查看某一个对象(需要为带有type槽的对象)的原型列表。某一个对象在收到消息时会查找自己的是否含有相应的消息槽,如果有就直接响应,如果没有就在它的原型列表上依次查找,以此类推。也可以通过appendProto(anObject)把anObject放入对象的原型列表中。
最后贴几个小例子:
# 猜数游戏 Guess := Object clone do( // 生成随机数 1~100 number := Random value(1,100) floor 10 repeat( "Please guess a number between 1 and 100:" println guessNumber := File standardInput readLine asNumber if(guessNumber > number) then("猜大了" println) elseif(guessNumber < number) then("猜小了" println) else("正确!" println;break) ) )
// 解析xml,提取文件中标签为appno的所有值,并写入appno文件 SGML // load sgml addon filename := System args at(1) // 取第一个参数为文件名 if(filename == nil , "Usage: -filename " println ;return) xml := File with(filename) openForReading contents asXML appnos := xml elementsWithName("appno") // 取标签名为appno的 appnos = appnos map(asString asMutable removePrefix("<appno>") removeSuffix("</appno>")) appnos println File with("appno") openForUpdating write(appnos asString) close
// 增强版xml生成器 Builder := Object clone // 用于缩进 tabCount := 0 Builder forward := method( tab := " " tabCount repeat(write(tab));writeln("<",call message name,">") tabCount = tabCount + 1 call message arguments foreach(arg, content := self doMessage(arg); if(content type == "Sequence",tabCount repeat(write(tab));writeln(content)) ) tabCount = tabCount - 1 tabCount repeat(write(tab));writeln("</",call message name,">") ) // Test: Builder html( head( title("This is a test for a Xml Generator By Io Language ") ) body( h1("Which Language do you like most?") ul( li("Io"),li("Java"),li("Javascript"),li("Ruby"),li("Python"), li("Scala"),li("C"),li("C++") ) ) )