跳转到内容

Io 编程

50% developed
来自维基教科书,开放世界中的开放书籍

Io 初学者指南

  1. 关于 Io 和本书
  2. 入门
  3. 您的第一个程序
  4. Io 程序的基本组成部分
  5. 对象

加载项和您

压缩

加密

网络

服务器

Io 语言页面

关于此维基

此作品在 GNU FDL、CC BY SA 和 Io 的许可下分离许可。

本教程的作者是

  • Daniel Ehrenberg (LittleDan)
  • Samuel A. Falvo II
  • Olle Jonsson(关于字符串连接的说明)

以及许多希望保持匿名的其他人。

你好世界

在学习编程时,通常学习的第一件事是如何编写一个将“Hello, world!”打印到控制台的程序。它让程序员了解简单程序的结构。Io 有很多方法可以将内容写入控制台,因此有时在使用哪一种方面可能会令人困惑。最常用的方法是 write 函数。输入 Io 的交互式解释器(在控制台中输入io)并键入以下内容

write("Hello, world!\n")

使用交互式解释器,这应该看起来像

user@computer:~$ io
Io> write("Hello, world!\n")
Hello, world!
==> nil

另一种方法是

"Hello, world!\n" print

其中一些是有道理的。看起来write正在告诉 Io 将某些内容写入控制台,特别是它后面的内容。它后面的内容在引号中,所以它是一些文本,它将被打印。但是为什么那里有括号,结尾处的\n是什么,为什么在引号文本后面有一个箭头呢?

括号告诉write使用括号内的内容,这被称为参数write被称为函数(还记得数学中的函数吗?)。在括号内可能有多个参数,用逗号隔开,在一个函数中。write的第一个也是唯一的参数,即"Hello, world!\n",是一个字符串(因为它是一串字母)。

字符串末尾的\n是一个转义序列。您可以通过它以反斜杠开头来判断。此特定转义序列表示换行符,相当于按回车键。如果您在字符串中间(或者至少是这种类型的字符串——稍后我们会介绍)按下了回车键,它会使 Io 混乱。

带有箭头和write函数参数的字符串的地方是write返回的值。每个函数都会返回值。对于某些函数,返回一些内容是有意义的(例如,用于将两个数字相加的函数),但对于其他函数,它只是返回使用参数完成的一些简单内容。在本例中,write返回特殊值nil,表示它没有要返回的内容。

连接字符串

使用双点运算符连接字符串。或者,您可以使用字符串插值,如下所示。

假设olle是一个Person实例,它既有名字也有姓氏

Io> olle
==> Object_0080B818 do(
  appendProto(Object_00806B58)
  lastname := "Jonsson"
  title := "Developer"
  firstname := "Olle"
)

我们希望有一个方法可以在名字和姓氏之间添加一个空格来显示它们

Io> olle fullname := method(firstname .. " " .. lastname)
==> method(firstname ..(" ") ..(lastname))

或者,使用字符串插值

Io> olle fullname := method("#{firstname} #{lastname}" interpolate)
==> method("#{firstname} #{lastname}" interpolate)

现在,调用olle fullname将产生"Olle Jonsson"。查看返回的方法对象,我们可以看到 Io 解释器是如何为..()方法创建常规消息调用的(括号)。

所以,这是新的olle实例

Io> olle
==> Object_0080B818 do(
  appendProto(Object_00806B58)
  fullname := Block_007B5030
  lastname := "Jonsson"
  title := "Developer"
  firstname := "Olle"
)

(注意:只有此实例具有fullname方法。您可以将fullname方法添加到Person中,这将通过olle的原型Person使它对olle可用。此外,firstname、lastname 和 title 也可以移到 Person 中。但这只是示例代码片段的方式。)

简单算术

在 Io 中,您可以使用算术表达式,它们将正常工作。Io 中的算术就像函数一样,只是它使用对象来帮助。对象使得您不必键入类似 +(1, 2) 的内容,而是可以键入 1+2。稍后会详细介绍对象。+ 仍然是一个函数,因此它返回一个值。这非常有用;它使您可以将 Io 用作简单的计算器。关于它正在做什么的说明放在两个斜杠后面(就像这样://)。

Io> 1+2 //addition
==> 3

Io> 4-5 //subtraction
==> -1

Io> 7*3 //multiplication
==> 21

Io> 3/6 //division
==> 0.50000

Io> 2**3 //exponents
==> 8

Io> 7%2 //remainder of 7/2 (technically, 7 mod 2)
==> 1

这遵循正常的运算顺序(称为优先级),可以使用括号。正如您所预期的那样,您可以在数字上使用write,但不会包含换行符。您必须使用write的多参数来打印多个内容,然后它将返回所有这些内容组合在一起。因此,要打印(1/3)**2,您将编写

write((1/3)**2, "\n")

正如您所预期的那样,这将打印 0.11111。它返回字符串 "0.11111\n",因为使用write函数时,多个参数将转换为字符串并连接在一起。然后该值被打印并返回。

变量

变量基本上是一个代表值的单词。它们有点像数学中的变量,只是在数学中,变量只能是数字,并且它们只有一个字母长。在编程中,函数、对象、字符串和数字都是变量类型,但我们还没有定义任何变量。许多变量,例如 write、3 和 "Hello, world!" 已经可以使用,但其中只有一部分可以更改。您可以使用 = 和 := 创建自己的变量。以下是创建和使用变量的一些示例

x := 3
line := "\n"
write(x, line)

您能说出发生了什么吗?变量 x 被设置为 3,变量 line 被设置为 "\n",它等效于换行符。然后,x 和 line 的内容被写入控制台。由于 x 是 3 并且 line 是一个换行符,因此这将打印 3 然后转到控制台的下一行。该函数返回 "3\n"。

在 Io 中,创建和更改变量的值之间存在差异。如果变量尚不存在,您必须使用 :=,但如果您已经使用 := 为其赋予了初始值,则可以使用 = 用于后续定义。以下是一个示例

x := 1
incrementor := 2
write("x is ", x, "\n")
x = x + incrementor
write("but when we added ", incrementor, " to it, it became ", x, "\n")

有时我们使用 :=,有时我们使用 = 可能令人困惑,但您会习惯的。如果您愿意,您可以始终使用 :=,但当我们稍后进入对象时,一直使用 := 会很不方便,因此您应该在适当的时候开始使用 =。

程序

到目前为止,您一直只是在使用 Io 的交互式解释器。这会阻止您创建更大的应用程序或为他人编写内容。如果您想编写要重用的代码,只需将其放在一个文本文件中,并使用io <filename>运行它,其中<filename>是您使用的文件名称。以下是在 Linux 上使用文件存储程序的示例

user@computer:~$ cat > incrementor.io
x := 1
incrementor := 2
writeln("x is ", x)
x = x + incrementor
writeln("but when we added ", incrementor, " to it, it became ", x)
user@computer:~$ io incrementor.io
x is 1
but when we added 2 to it, it became 3
user@computer:~$

这是我们刚刚做的最后一个示例。如果您注意到,我使用了 .io 文件扩展名。这在任何情况下都不是强制性的,这只是一种约定。如果您注意到,这次发生的事情与我们从文件中执行时有所不同。与以前不同的是,我们没有看到每个函数返回的内容。相反,我们只看到了由write显式输出的内容。

如果您使用的是 Linux 或类似系统(如 Unix、Mac OS X 或 Cygwin),您可以使其能够通过键入./yourProgram.io(其中 yourProgram.io 是您的程序名称)来运行,而无需在前面加上io。这可以通过在程序开头添加一行代码,然后赋予其可执行权限来实现。在 Linux 上,该代码为

#! /usr/bin/env io

对于其他系统,它可能会有所不同。要赋予它可执行权限,只需键入以下内容

chmod +x yourProgram.io

同样,这在不同的系统上可能有所不同。完成此操作后,代码的实际执行不会发生任何变化,但您可以例如双击 GUI 中的源代码文件,它将运行。

编写函数

正如我之前所说,函数只是另一种类型的变量,因此您可以使用 := 创建它们,并使用 = 更改它们。函数本身是由一个名为method的函数创建的。以下是一个函数示例

add := method(a, b, //function to add 2 numbers
  a + b
)
writeln(add(1, 2)) //writes 3
x := 1
writeln(add(3, x)) //writes 4
x = add(4, 5) //9
writeln(x) //writes 9
x = add(x, 1) //in effect increment x by 1
writeln(x) //writes 10

函数 add 接收两个参数,a 和 b,然后返回 a + b。如果我们使用变量名 'this' 和 'that' 代替 a 和 b,在 a 和 b 使用的任何地方,它将执行完全相同的事情。在这种情况下,该函数将被写成

add := method(this, that,
  this + that
)

函数的实际作用是接收一个参数列表,然后将这些参数分配给定义函数时指定的 *局部变量*。局部变量只存在于你正在操作的函数中,你无法在函数外部访问它们。在最近的案例中,这些局部变量是 'this' 和 'that',因此变量 'this' 将获取第一个参数,变量 'that' 将获取第二个参数。然后执行函数的剩余部分并返回结果。函数可以包含多行代码,最后一行将是返回的值。以下是一个示例

examineArgs := method(this, that,
  writeln("This is ", this, ".")
  writeln("That is ", that, ".")
)
// usage:
examineArgs(3, 5)
/* writes:
This is 3.
That is 5. */
x := examineArgs("hi", "bye")
/* writes:
This is hi.
That is bye. */
write(x)
/* writes:
That is bye. */

为什么 x 被设置为 "That is bye.\n"?因为这是 examineArgs 返回的值。它返回最后一行代码的值,即 write("That is ", that, ".\n") 的值。该值被设置为 "bye",因此它打印字符串 "That is bye.\n" 并返回相同的字符串。

如果你想要在函数结束之前返回某些内容,可以使用 return 函数。与大多数函数不同,你不需要在调用 return 函数时在参数周围加括号。以下是一个使用示例

returning := method(this, that,
  writeln(this)
  return this
  writeln(that)
)
x := returning(1, 2)
//writes "1\n"
write(x) //writes 1 with no newline

如你所见,return 之后的代码完全没有被使用。目前这看起来并没有什么用,但稍后在学习到流程控制时,它将被频繁使用。

条件语句

Io 中的条件语句使用 if 函数创建

if(a == 1) then(
  writeln("a is one")
) else(
  writeln("a is not one")
)

然而,更推荐的写法是(不需要 then() 和 else() 消息,因此速度更快)

if(a == 1, writeln("a is one"), writeln("a is not one"))
华夏公益教科书