1. Ruby中的“===”符号

Ruby中每个对象都含有===方法,不过从意义上来说,===跟“相等”没有任何关系。先看看下面的例子:

1 === 1				#=> true
(1..9) === 3 		#=> true
(1..9) === 11		#=> false
/ab/ === "abcd"		#=> true
/ab/ === "def"		#=> true
Integer === 1		#=> true
1 === Integer		#=> false
Object === Integer	#=> true

stack overflow上的回答普遍认a === b的意义为:“假设用a描述一个集合,b能否放到这个集合中?”。上面的例子基本都符合这个解释,RangeRegexp自然不用说,而Integer === 1则表示为1Integer这个集合中的一个,我认为可以理解为数学上所说的集合,a === b意为b ∈ a,那么Integer === 1理解为1是否属于整数集Object === Integer理解为Integer是否属于Object集(Ruby中每个Class实际上是Object的一个instance)。那么[1,2,3] === 1这个表达式会返回什么呢?如果你理解了上面说的,那你就可以答出”false”。为什么?首先[1,2,3]Array的一个实例,那我们所说的集合是这样的: { [1,2,3] },只有一个元素,这个集合肯定不包含1了。

===这个符号平时很少见,但是实际上你经常用到。case...when语句中条件匹配使用的就是===符号。所以我们才能这样写:

case year
when 1980..1989
 "80后"
when 1990..1999
 "90后"
end

参考链接:

http://stackoverflow.com/questions/3422223/vs-in-ruby http://stackoverflow.com/questions/4467538/what-does-the-operator-do-in-ruby

2. Ruby中的换行

Ruby解释器根据换行符插入的位置不同而有不同的处理,下面语句能正确地将xy的和赋值给total

total = x +		# 解释器会认为语句未完结,继续往下解释
 y

但这条语句就不同了:

total = x		#解释器会认为这是完整语句,将x赋值给total
 + y			#另一个语句,对y求值

有三种情况下解释器会认为这是未完成的语句,分行应该以此为标准:

  1. 操作符之后插入换行符
  2. 方法调用的.之后插入换行符
  3. 数组、哈希或方法调用中用于分隔元素的,之后插入换行符

从ruby 1.9开始,加入了新规则: 如果一行代码的首个非空白字符是.,那么这一行就是上一行的延续,忽略上一行的换行符。要注意这个规则跟上面的换行规则是有不同的。而在ruby 1.9之前没有这个特性。

3. 闭包

Ruby的proclambda都是闭包的,比起block,闭包还绑定了代码块中的全部变量。

def plus(x)
 lambda { x + 1 }
end

my_plus = plus(5)
puts my_plus.call #=> 6

上面的例子可见,lambda返回后,调用是仍然能访问局部变量x。再看一个例子:

class Printer
 def initialize(message)
   @message = message
 end

 def change_to(message)
   @message = message
 end

 def get_printer
   lambda { puts @message }
 end
end

printer = Printer.new('init message')
my_printer = printer.get_printer
my_printer.call							#=>  "init message"

printer.change_to('changed message')
my_printer.call							#=>	"changed message"

@message更变后lambda中的@message也跟着改变。

除此之外,闭包之间还能共享变量。

class MessageManager
 def initialize(message)
   @message = message
 end

 def printer_helpers
   setter = lambda { |x| @message = x }
   getter = lambda { @message }
   return setter, getter
 end
end

setter,getter = MessageManager.new('init message').printer_helpers
puts getter.call				#=> init message

setter['changed message']
puts getter.call				#=> changed message

其他

Ruby默认采用ASCII编码,但支持使用其他编码方式。可以在文件的第一行加入编码注释(coding comment):

# -*- coding: utf-8 -*-

如果文件第一行是shebang注释,那编码注释放在第二行。

可以通过__ENCODING__获取当前执行的代码的源编码