为什么80%的码农都做不了架构师?>>>   

##Io简介 大多数的Io社区都致力于将Io作为带有微型虚拟机和丰富并发特性的可嵌入语言来推广。
Io的核心优势是拥有大量可定制的语法和函数,以及强有力的并发模型。
在Io中,万事万物皆为消息,且每条消息都灰返回另一接受消息的对象。Io这门语言没有关键字,有的只是少量在行为上接近于关键字的字符。

##对象、原型和继承 Io是一门原型语言,所有的对象都有原型,对象还带有槽(slot,相当于类的域和方法??)。
槽的相关操作

  1. :=当槽不存在,Io会创建一个槽,然后赋值
  2. =给槽赋值,如果槽不存在,抛出异常
  3. ::=新建槽
  4. type 任何对象都有type这个槽,返回对象的原型
  5. slotNames返回对象的槽名列表
  6. getSlot(name)获取槽的内容,如果槽不存在会获取父对象的槽

Io的类型是一个非常好的机制。从惯用的角度说,以大写开开头的对象时类型,因此Io会对它设置type槽。而类型的复制品若以小写开头则会调用它父对象的type槽。

##方法 方法是槽的一种?
方法也是对象,和其它类型的对象一样,你可以获取它的类型。

Io>method() type
==>Block

Lobby是主命名空间(相当于浏览器中javascript的window?),包含所有已命名的对象。

Io> LobbyProtos           = Object_0x1dac868_                = Object_0x1dac8c8exit             = method(...)forward          = method(...)set_             = method(...)
  1. 所有事物都是对象;
  2. 所有与对象的交互都是消息
  3. 你要做的不是实例化类,而是复制那些叫做原型的对象
  4. 对象会记住它的原型
  5. 对象有槽
  6. 槽包含对象(包括方法对象)
  7. 消息返回槽中的值,或调用槽中的方法
  8. 如果对象无法响应某消息,它则会把消息发送给自己的原型

###单例 true、false和nil都是单例(singleton),对它们进行复制,返回的只是单例对象的值。构建单例只需重定义clone方法,让它返回单例对象自身即可。

##第一天自习

  1. 对1+1求值,然后对1+"one"求值。Io是强类型还是弱类型?用代码证实你的答案。

     Io> 1+1==> 2Io> 1+"one"Exception: argument 0 to method '+' must be a Number, not a 'Sequence'---------message '+' in 'Command Line' on line 1Io> "1"+"one"Exception: Io Assertion 'operation not valid on non-number encodings'---------message '+' in 'Command Line' on line 1Io> "1" .. "one"==> 1oneIo> 1 .. "one"==> 1one
    
  2. 0是true还是false?空字符串是true还是false?nil是true还是false?用代码证实你的答案。

    Io> if( 0 , true println,false println)
    true
    ==> true
    Io> if( "" , true println,false println)
    true
    ==> true
    Io> if( nil , true println,false println)
    false
    ==> false
    
  3. 如何知道某个原型具有哪些槽?

     Io> Sequence slotNames foreach(println)loglinePrintbeforeSeqpathComponenturlDecodedremoveSeqbitwiseAndremoveOddIndexesuppercasefindSeqreplaceSeqcPrintlogicalOr...
    
  4. =、:=、::=之间有什么区别?你会在什么时候使用它们?

     Io> OperatorTable==> OperatorTable_0x951180:Operators0   ? @ @@...Assign Operators::= newSlot:=  setSlot=   updateSlot
    

    实际测试没有发现::=与:=的区别。

  5. 从文件中运行Io程序。

     D:\IoCodes>cat sum.iosum := 0for(i,1,100,sum = sum + i)sum printlnD:\IoCodes>io sum.io5050
    

##运算符

Io> OperatorTable addOperator("xor",11)
==> OperatorTable_0x1d61180:
Operators...10  && and11  or xor ||12  ..13  %= &= *= += -= /= <<= >>= ^= |=14  returnAssign Operators::= newSlot:=  setSlot=   updateSlotTo add a new operator: OperatorTable addOperator("+", 4) and implement the + message.
To add a new assign operator: OperatorTable addAssignOperator("=", "updateSlot") and implement the updateSlot  message.Io> true xor := method(bool,if(bool,false,true))
==> method(bool,if(bool, false, true)
)
Io> false xor := method(bool,if(bool,true,false))
==> method(bool,if(bool, true, false)
)
Io> true xor false
==> true

##消息 在Io中,几乎一切都是消息。一个消息由三部分组成:发送者(sender)、目标(target)、参数(arguments)。你可以用call方法访问任何消息的元信息。

//msg.io
MsgReceiver := Object clone
MsgReceiver receive := method("message name is : " printcall message name println"sender is :" printlncall sender  println"target is :" printlncall target  println"arguments is :" printlncall message arguments  println"arguments[0] is : " printcall message argAt(0)  println"arguments[0] is : " printcall argAt(0)  type println"arguments[0] is : " printcall evalArgAt(0)  type println
)MsgSender := Object clone
MsgSender send := method("message name is : " printcall message name println"sender is :" printlncall sender  println"target is :" printlncall target  printlnreceiver := MsgReceiver clonereceiver receive("hollo world!")
)sender := MsgSender clone
sender send//result:
message name is : send
sender is :Object_0x44c890:Lobby            = Object_0x44c890MsgReceiver      = MsgReceiver_0x2171178MsgSender        = MsgSender_0x2171238Protos           = Object_0x44c830_                = nilexit             = method(...)forward          = method(...)sender           = MsgSender_0x21712c8set_             = method(...)target is :MsgSender_0x21712c8:message name is : receive
sender is :MsgSender_0x21712c8:target is :MsgReceiver_0x217c368:arguments is :
list("hollo world!")
arguments[0] is : "hollo world!"
arguments[0] is : Message
arguments[0] is : Sequence
[Finished in 0.2s]

可以看到,send方法的发送者是全局对象Lobby。 evalArgAt和argAt是两者间的区别:

evalArgAt(argNumber)
Evaluates the specified argument of the Call’s message in the context of it’s sender.

argAt(argNumber)
Returns the message’s argNumber arg. Shorthand for same as call message argAt(argNumber).

大多数语言都将参数作为栈上的值传递,但是Io不是这样。Io传递的是消息本身和上下文,在由接受者对消息求值。实际上你可以用消息实现控制结构。

##反射 在Io中,处理反射分为两个部分。在邮局那个例子中,是消息反射。对象反射是处理对象和对象的槽。

Object ancestors := method(prototype := self protoif(prototype !=Object,writeln("Slots of ",prototype type,"\n---------------------")prototype slotNames foreach(slotName, writeln(slotName))writelnprototype ancestors))Animal := Object clone
Animal speak := method("ambigulous animal noise" println
)Duck := Animal clone
Duck speak := method("quack" println
)Duck walk := method("waddle" println
)disco := Duck clone
disco ancestorsdisco walkdisco speak***************output:*******************
Slots of Duck
---------------------
walk
speak
typeSlots of Animal
---------------------
speak
typewaddle
quack

##第二天自习

  1. 计算斐波那契数列的递归和循环两种方法:

    fib := method(n,if(n ==1 or n == 2) then(return 1) else (return (fib(n-1) + fib(n-2)))
    )fib2 := method(n,if(n == 1) then (return 1) else (prv1 := 1prv2 := 0cur := 0for(i,2,n,cur = prv1 + prv2prv2 = prv1prv1 = cur)return cur)
    )
    
  2. 在分母为0的情况下如何让运算符/返回0?

    Number setSlot("coreDivision", Number getSlot("/"))Number / = method(n,if(n==0) then(return 0)else(return (self coreDivision(n)))
    )(4/0) println(8/4) println(16/8) println(16 / -8) println
    
  3. 写一个程序,把二维数组的所有数相加
    Io中没有Array这个原型,所以用List代替数组

    sum := method(arr,if(arr type != "List") then(return 0)sum := 0arr foreach(e,if(e type != "List") then(continue)if(e size < 2) then(continue)sum = sum + e at(0)sum = sum + e at(1))return sum
    )sum(list(list(3,4),list(5))) println
    sum(list(7,8)) println************output*************
    7
    0
    
  4. 对列表增加一个名为myAverage的槽,以计算所有数字的平均值。

    List myAverage := method(if(self isEmpty) then( return 0 )sum := 0self foreach(e,if(e type != "Number") then(Exception raise("List member is not a number") )sum = sum + e)avg := sum / self size
    )list() myAverage println
    list(3,4,5,1.2) myAverage println
    
  5. 对二维矩阵写一个原型。该原型dim的方法可为一个包含y个列表的列表分配内存,其中每个列表有x个元素,set(x,y) 方法可以设置类别中的值,get(x,y)方法可返回列表中的值。

    TwoDArray := Object clone
    TwoDArray dim := method(x,y,self data := list()for(i,0,x-1,innerList := list()for(j,0,y-1,innerList append(nil))data append(innerList))
    )TwoDArray set := method(x,y,e,outterList := self dataif(x > outterList size, return)innerList := outterList at(x)if(y > innerList size, return)innerList atPut(y,e)
    )TwoDArray get := method(x,y,outterList := self dataif(x > outterList size, return nil)innerList := outterList at(x)if(y > innerList size, return nil)innerList at(y)
    )arr2 := TwoDArray clone
    arr2 dim(3,4)
    arr2 set(1,2,3)
    arr2 set(1,10,3)
    arr2 get(1,2) println
    arr2 get(1,10) println
    

    dim(x,y)分配了包含x个列表的列表,每个子列表有y个元素,与题目有点不同,但觉得这样更好理解。 代码没有对数组下标越界抛出异常,抛出异常应该更好。

  6. 写一个转置方法,是原列表上的matrix get(x,y)与转置后的列表(new_matrix get(y,x))相等。

    TwoDArray transpose := method(outterList := self datay := outterList sizeinnerList := outterList at(0)x := innerList sizeret := TwoDArray cloneret dim(x, y)for(i,0,x-1,for(j,0,y-1,ret set(i, j, self get(j, i))))return ret
    )arr2 := TwoDArray clone
    arr2 dim(3,4)
    arr2 set(1,2,3)
    arr2 set(1,10,3)
    arr2 get(1,2) println
    arr2 get(1,10) println
    "-----------" println
    arr3 := arr2 transpose
    arr3 get(2,1) println
    arr3 get(10,1) println
    
  7. 将文件写入矩阵,并从文件读取矩阵

    TwoDArray writeMatrix := method(filePath,f := File with(filePath)f removef openForUpdatingoutterList := self datax := outterList sizey := outterList at(0) sizef write((x .. "," .. y .. "\n"))outterList foreach(e,line := ""e foreach(e2,line = line .. e2 .. ",")f write(line exSlice(0,-1),"\n"))f close
    )TwoDArray readMatrix := method(filePath,f := File with(filePath)f openForReadingline := f readLined := line split(",")x := d at(0) asNumbery := d at(1) asNumberret := TwoDArray cloneret dim(x,y)writeln("x=",x,", y=",y)i := 0j := 0f readLines foreach(line,list := line split(",")j = 0list foreach(e,writeln(i,"x",j,"=",e)if(e != "nil",ret set(i,j,e))j = j + 1)i = i +1)f closereturn ret
    )TwoDArray writeMatrix2 := method(filePath,f := File with(filePath)f removef openForUpdatingf write(self serialized())f close
    )TwoDArray readMatrix2 := method(filePath,ret := doFile(filePath)return ret
    )arr2 := TwoDArray clone
    arr2 dim(3,4)
    arr2 set(1,2,3)
    arr2 set(1,10,3)
    arr2 get(1,2) println
    arr2 get(1,10) println
    "-----------" println
    arr3 := arr2 transpose
    arr3 get(2,1) println
    arr3 get(10,1) printlnarr3 writeMatrix("./test.dt")arr4 := TwoDArray readMatrix("./test.dt")arr4 println
    arr4 get(2,1) println
    arr4 get(10,1) printlnarr3 writeMatrix2("./test2.dt")arr5 := TwoDArray readMatrix2("./test2.dt")arr5 println
    arr5 get(2,1) println
    arr5 get(10,1) println
    
  8. 写一个程序,提供10次尝试机会,猜一个1~100之间的随机数。如果

    GuessNumGame := Object clone
    GuessNumGame init := method(self secretNum := Random value(1,101) floorself guessTimes := 0self lowBoundry := 0self highBoundry := 100secretNum println
    )GuessNumGame guess := method(x,guessTimes printlnif(guessTimes > 10) then("You had guess over 10 times! Game over!" printlnreturn)if(x < secretNum) then(if(x > lowBoundry,lowBoundry = x)writeln("You guess lowwer. You can guess between ",lowBoundry," to ",highBoundry)) elseif(x == self secretNum) then(writeln("Congratulations! You got the right number!")) else(if(x < highBoundry, highBoundry = x)writeln("You guess higher. You can guess between ",lowBoundry," to ",highBoundry))guessTimes = guessTimes + 1
    )game := GuessNumGame clone
    game guess(10)
    game guess(50)
    

##领域特定语言 几乎每一个研究过Io语言的人,都会对它在DSL方面的强大赞不绝口。下面实现一种有趣的电话号码语法的API。
比如:

{"Bob smith":"5195551212","Mary Walsh":"4162223434"
}

解决这一个问题的办法:

OperatorTable addAssignOperator(":","atPutNumber")
curlyBrackets := method(r := Map clonecall message arguments foreach(arg,r doMessage(arg))r
)Map atPutNumber := method(self atPut(call evalArgAt(0) asMutable removePrefix("\"") removeSuffix("\""),call evalArgAt(1))
)s := File with("phonebook.txt") openForReading contents
phoneNumbers := doString(s)  //doString把电话号码簿求值为Io代码
phoneNumbers keys println
phoneNumbers values println

##Io的method_messing 就像Ruby的method_missing那样,你也可以用Io的forward消息做到同样的事,但是这样做的风险会高一些。Io没有类,所以改变forward也将改变从Object获得的基本行为方式。
XML是对数据进行结构化的绝妙方式,但是却有着令人作呕的语法。为了摆脱这语法,你可以写一个程序,用Io代码来表示XML数据。 假如你想把下面的数据:

<body>
<p>
This is a simple paragraph.
</p>
</body>

表示成:

body(p("This is a simple paragraph.")
)

我们把这种新语言称作LispML。我们将用Io的forward处理这门语言,就像处理不存在的方法一样(missing_method)。

Builder := Object clone
Builder forward := method(writeln("<",call message name,">")call message arguments foreach(arg,content := self doMessage(arg)if(content type == "Sequence", writeln(content)))writeln("</",call message name,">")
)Builder ul(li("IO"),li("Lua"),li("Javascript")
)

##并发 Io有非常出色的并发库,其主要组成部分包括协程、actor和future。 ###1.协程 协程是并发的基础。它提供了进程自动挂起和恢复执行的机制。你可以把协程想象成有多个入口和出口的函数。每次yield都会自动挂起当前进程,并把控制转到另一个进程中。 通过在消息前加上@或@@,你可以异步触发消息,前者将返回future,后者会返回nil,并在其自身线程中触发消息。

vizzini := Object clone
vizzini talk := method("Fezzik, are there rooks ahead?" printlnyield"No more rhymes now, I mean it." printlnyield
)fezzik := Object clone
fezzik rhyme := method(yield"If there are, we'll all be dead." printlnyield"Anybody want a peanut?" println
)vizzini @@talk
fezzik @@rhymeCoroutine currentCoroutine pause

协程是组成更高级抽象概念(如actor)的基本元素。你可以把actor想象成通用的并发原语,它可以发送消息、处理消息以及创建其它actor。actor接收到的消息是并发的。在Io中,actor把新到达的消息放到队列上,并用协程处理队列中的各个消息。

###2.Actor 和线程相比,actor有巨大的理论优势。一个actor可以改变其自身状态,并且通过严格控制的队列接触其它actor。而多个线程可以不受限制地改变状态。线程容易接受到被称为竞争条件的并发影响。在这种问题中,如果两个线程同时存取资源,可能导致不可预测的后果。
Io的动人之处就在于此,发送异步消息给任何对象就是actor,就这么简单。举一个例子:

slower := Object clone
faster := Object cloneslower start := method(wait(2)writeln("slowly")
)faster start := method(wait(1)writeln("quickly")
)slower start
faster start
"======================" println
slower @@start
faster @@start
Coroutine currentCoroutine pause

###3.future 在Io中,future并不是代理实现。future会阻塞到可获得结果为止。future的值一开始是个future对象,但等到结果产生之后,所有future值的实例都会指向结果对象。

futureResult := URL with("http://google.com/") @fetch
writeln("doing other thing ...")
wait(2)
writeln("fetched," futureResult size," bytes")

在windows下运行上面代码出现Exception: Object does not respond to 'URL'异常,google了一下,未能解决,望高手指点。

##第三天自习

  1. 改进本节生成的XML程序,增加空格以显示缩进结构。

    Builder := Object clone
    Builder indentSize := 4
    Builder i := 0
    Builder forward := method((i * indentSize) repeat(write(" "))writeln("<",call message name,">")i = i + 1call message arguments foreach(arg,content := self doMessage(arg)if(content type == "Sequence", (i * indentSize) repeat(write(" "))writeln(content)))i = i -1(i * indentSize) repeat(write(" "))writeln("</",call message name,">")
    )Builder ul(li(p("IO")),li("Lua"),li("Javascript")
    )
    
  2. 创建一种使用括号的列表语法

    squareBrackets := method(      if(call message arguments asString containsSeq("squareBrackets") not,return call message arguments)       //如果不含子数组就直接返回参数列表,参数列表本来就是一个listlist := List clonecall message arguments foreach(arg,aArg := if(arg asString beginsWithSeq("squareBrackets"),doMessage(arg),arg)list append(aArg)// 最后一行为返回值)list
    )[] println
    [1,"kk"] println
    [1,["kk",10.5]] println
    
  3. 改进本节生成xml程序,使其可以处理属性:如果第一个参数时映射(用大括号语法),则为xml添加属性。例如:
    book({"author":"Tate"}...) 将打印出<book author="Tate">

    OperatorTable addAssignOperator(":","addAttribute")Builder := Object cloneBuilder addAttribute := method(call message arguments printlnwrite(call evalArgAt(0))write("=\"",call evalArgAt(1),"\"")
    )Builder curlyBrackets := method(call message arguments foreach(arg,self doMessage(arg))
    )Builder indentSize := 4
    Builder i := 0
    Builder forward := method((i * indentSize) repeat(write(" "))write("<",call message name)i = i + 1args :=call message arguments arg1 := args at(0)if( arg1 asString beginsWithSeq("curlyBrackets"),//arg1 printlnself doMessage(arg1)args remove(arg1))writeln(">")args foreach(arg,content := self doMessage(arg)if(content type == "Sequence", (i * indentSize) repeat(write(" "))writeln(content)))i = i -1(i * indentSize) repeat(write(" "))writeln("</",call message name,">")
    )Builder ul({"class" : "foo","id" : "language"},li("Io")
    )
    

上面代码会出现异常,不知道如何解决。

    <ulException: Sequence does not respond to ':'---------Sequence :                           builder.io 50Builder curlyBrackets                builder.io 50Builder ul                           builder.io 49CLI doFile                           Z_CLI.io 140CLI run

转载于:https://my.oschina.net/Chigo/blog/144161

七周七语言之IO学习笔记相关推荐

  1. 《Go语言圣经》学习笔记 第七章 接口

    <Go语言圣经>学习笔记 第七章 接口 目录 接口是合约 接口类型 实现接口的条件 flag.Value接口 接口值 sort.Interface接口 http.Handle接口 erro ...

  2. 图书封面的故事之——“巴别塔”选自《七周七语言:理解多种编程范型》

    我认为,图书的封面很重要,因为首先映入读者眼帘的就是封面,他可以诱发潜在的读者去注意图书,图书的封面可以显示出很多信息,例如书名.推荐语.评价.出版单位等,最重要的还是要给图书起一个好的名字,一本好书 ...

  3. 七周七并发模型与七周七语言

    借助Java.Go等多种语言的特长,深度剖析所有主流并发编程模型 基于锁和线程的并发模型是目前最常用的一种并发模型,但是并发编程模型不仅仅只有这一种,本书几乎涵盖了目前所有的并发编程模型.了解和熟悉各 ...

  4. 《七周七并发模型》笔记

    <七周七并发模型>笔记 1 概述 1.1 并发并行 1.2 并行架构 1.3 并发:不只是多核 并发的世界,并发的软件 分布式的世界,分布式的软件 不可预测的世界,容错性强的软件 复杂的世 ...

  5. 《七周七语言:理解多种编程范型》书评整理

    任何一个想在程序开发这条路上走远点的人都应当多了解几门语言,多接触一些编程泛型,才能打开眼界,提高自己. 国内绝大多数程序员可能就知道个OOP,借着javascript的兴起可能有小部分人能够对原型有 ...

  6. 七周七语言:Scala Day 3

    这一天的内容还是比较丰富的,不仅介绍了Scala中的对于XML的处理.正则,更有比较重要的"并发". Scala支持并发的方式代表了并行编程领域的一次重大进步.actor模型和线程 ...

  7. 高中生学python培养思维能力_python学习(七周七第二章结构化思维及如何学习)...

    20180908星期六 总结中,为没有华丽的语句感到烦恼.是因为自己忘记初衷,如果是学习就记录今天学习内容.感想.问题:如果是工作就记录今天最优成就的一件事.今天遇见的问题:如果是生活就记录今天最开心 ...

  8. 【14天鸿蒙设备开发实战-第七章 设备联网上云 学习笔记】

    14天鸿蒙设备开发实战-第七章 设备联网上云 学习笔记 一.开发环境.平台与硬件需求 二.华为IoT平台API 2.1 初始化 2.1.1 设备信息初始化 2.1.2 华为IoT平台 初始化 2.1. ...

  9. 《Go语言圣经》学习笔记 第五章函数

    <Go语言圣经>学习笔记 第五章 函数 目录 函数声明 递归 多返回值 匿名函数 可变参数 Deferred函数 Panic异常 Recover捕获异常 注:学习<Go语言圣经> ...

最新文章

  1. Python sorted() 函数
  2. MapReduce工作原理图文详解
  3. 【Unity3D自学记录】判断物体是否在镜头内
  4. 第一章 docker 镜像,容器,仓库基本命令(二)
  5. mysql安装显示3534_MySQL安装成功之后启动错误 3534、28000和简单使用
  6. 【个人笔记】OpenCV4 C++ 快速入门 11课
  7. CAPL学习之路-关键字
  8. Magisk Magisk Manager 下载
  9. Flask 使用abort方法返回http错误码、http错误响应信息
  10. 终结者2018java游戏_如何评价电影《终结者 2018》?
  11. 蹩脚的程序员们,我们来谈谈你的未来!
  12. java中判断字符是否为英文字母、中文汉字或者数字
  13. 天翼云,不要来,千万不要来!开始统计工时,安装监控软件,减少福利!
  14. IBM Storwize V5000资源管理柜
  15. Linux 批量修改文件名和后缀
  16. ajax参数xhrfields,使用xhrFields可以将进度功能添加到jQuery.ajax()中吗?
  17. EasyUI 搭建后台登录界面和管理系统主界面
  18. Markdown中Latex公式编辑
  19. 在CorelDraw中,VBA宏调用是如何执行的?
  20. 股票数据接口是怎么开发的?

热门文章

  1. 竣达技术丨适用于“科士达”智能精密空调网络监控
  2. DEEP GRAPH INFOMAX
  3. 阿里云机器上执行 locusts 命令出现 OSError: [Errno 97] Address family not supported by protocol...
  4. 九毛九,患了太二依赖症
  5. [GKCTF2021]babycat
  6. ZYJ7道岔控制电路图【铁路信号技术专栏】--转自微信公众号铁路信号技术交流
  7. IPFS(星际文件系统)-初步接触
  8. 优傲机器人UR Robots官方发布ROS2驱动
  9. HDU 2104 hide handkerchief
  10. 郑州计算机专业机构学校,河南哪些大学里有计算机专业