本问答的目标读者是不了解 Ruby 语言、但有别的编程语言经验的人。 Ruby 语言的代码可读性是很强的。本问答只把一些语法特点、以及别的语言中可能没有或 不同的东西展现出来,目的在于让有别的编程语言经验的人能快速读懂 Ruby 代码。 注意本问答讲的是 Ruby 语言本身(基于版本 1.9) ,而不是 Ruby on Rails,后者是 Ruby 的一 种 DSL,语言面貌上和 Ruby 有一定差异。 Q:Ruby 最有特点的语法形式是什么?
或许是方法后接代码块的大量使用,以下面这行代码为例: file.each_line("x") { |line| print line } 表示在 file 对象上调用 each_line 方法(以"x"为行的分隔符) ,该方法的功能是依次得到每一 行,传递给后面的代码块,代码块把传来的行赋值给 line 变量,然后在代码块里对 line 进行 处理, 处理完毕则从代码块返回 each_line 方法, 再由它得到下一行, 再一次传递给代码块。 ——像 each_line 这样的方法,Ruby 中称之为迭代器方法(iterator) 。
又比如这个例子: open('test.txt') { |f| line_array = f.readlines } 用 open 方法打开 test.txt 文件,生成了一个 File 类的实例对象,并把这个对象传递给后面的 代码块,赋值给变量 f,然后代码块里对 f 进行操作,操作完毕后返回 open 方法,open 方 法再把 f 关闭,所以这一行代码相当于如下三行: f = open('test.txt') line_array = f.readlines f.close Ruby 风格写法的好处:一行完成,逻辑紧凑;自动关闭文件,防止忘了 f.close; 当前 scope 少创建一个变量名 f,代码块关闭后,f 就消失了 一个 Ruby 风格的完整命令就是由对象、方法(包含参数) 、代码块(包含参数)构成的。有 的方法可以不接代码块。 Q:我看到有些代码和上面提到的写法不太像,是怎么回事? 有些 DSL 看起来和 Ruby 语言本身不大像,但其实语法格局是一样的,只是通过一些设定伪 装成别的风格。
大致有四点导致这种情况:
1、隐性地调用方法,让方法看起来像函数或关键词; Ruby 中没有函数,全都是方法。方法就得在某个对象上调用,但是这个对象可以隐藏 方法不在某个对象上显式调用,那它就一定是在 self 所指的对象上调用 如 open(file)实际是 self.open(file),不过 open 是私有方法,不能显式写出对象 2、省略了括起参数的括号; 如 open('test.txt','w')可以写成 open 'test.txt', 'w' 3、代码块的{...}改成 do...end; open 'test.txt' do |line| end 就相当于 open('test.txt') {|line| }
这是很常见的,{...}和 do...end 只在优先级上有一些不同,一般都可互换 通常的风格是:代码块里的代码若只有一行,则用{},若有多行,则用 do...end 这只是风格管理,实际上即使是多行代码,你也可以用{}括起来
4、省略作为方法参数的哈希(散列)字面量的花括号。
很多方法喜欢拿一个哈希做参数, 如果哈希是方法调用的最后一个参数, 则花括号可省略 task :name => :test 相当于 task({:name => :test})
如下一段代码: HTMLForm.generate(STDOUT) do comment "This is a simple HTML form" form :name => "registration", :action => "example/register.cgi" do content "Name:" input :name => "name" content "Address:" textarea :name => "address", :rows=>6, :cols=>40 do "Please enter your mailing address here" end end end
如果写“全”来,就相当于这样:
HTMLForm.generate(STDOUT) {
selfment("This is a simple HTML form") self.form({:name => "registration", :action => "example/register.cgi"}) { self.content("Name:") self.input({:name => "name"}) self.content("Address:") self.textarea({:name => "address", :rows=>6, :cols=>40}) { "Please enter your mailing address here" } } } Q:我听说 Ruby 分 1.8 和 1.9 两个版本,二者的语法有什么不同? 目前 Ruby 流行 1.8.x 和 1.9.x 两个主要版本。