Today's the day

向软件大牛炫耀我会焊单片机,向硬件大牛炫耀我会写 Rails,向软硬件大牛炫耀我生物,向软硬件生物大牛炫耀我会折腾期货 -_-bbb

被 Ruby 耍了一下

Fixnum 有个实例方法 [ ],返回数字二进制表示的第 n 位,比如:

  1. > 8[3]
  2.  1

  1. > 10.downto(0){|n| print 255[n]}
  2. 00011111111

如果传入个符号会怎么样呢? 本以为会出错,发现运行正常,返回 0:

  1. > 5[:asdasdasd]
  2. 0

果不其然,[ ] 对传入的符号做了隐式转换,符号的 to_int 方法返回一个唯一代表本身的整数,一般这个整数很大,也就是返回数字的很高位,自然是 0。

这样的话,像 val[:something] 这样的形式,有可能 val 是个 hash,拿符号当作键,也有可能像上面那样 val 只是个数字。

前两天写个东西,类似下面的代码:

  1. @user.data ||= {:a => 1, :b => 2, :xxx => xxx ....... }
  2. ....
  3. val = @user.data[:someting]

运行发现,不管我怎么取,val 的值都是 0 ……百思不得其解

后来发现 users 表的 data 这项,不小心在数据库中指定默认值为 0 了,所以 @user.data 就不是 nil,根本没有被赋值为后面的 hash,val 就是 0[:something],怪不得取什么都是 0。

符号可以响应 to_int,字符串无法响应 to_int,所以传入个字符串就报错了,不过数字的 [ ] 方法传入非字符的变量有啥意义呢?检测参数不是 Fixnum 就 raise,这样就好了……


Update: 值得庆幸的是,最新的 Ruby 1.9.0 中已经拿掉了 Symbol 的 to_int 方法~

RUBY_VERSION                                       # => "1.9.0"
:foo.to_int                                       
# ~> -:2: undefined method `to_int' for :foo:Symbol (NoMethodError)