Rubyist

Method end with Bang means dangerous

Ruby里,方法可以以叹号结尾。以叹号结尾的方法通常表示这个方法是危险的。

但是,一般以叹号结尾的方法都会改变原对象,结果造成了一种误解。

以!结尾的方法通常改变原对象,但不是所有改变原对象的方法都以!结尾

常见的gsub!或chomp!都是以叹号结尾并且改变原对象的方法,但是也有一些会改变原对象的方法并不以叹号结尾。

例如:

  • Array#push
  • Array#pop
  • Array#shift
  • Array#unshift
  • Array#concat
  • Array#delete
  • Array#clear

什么是“危险”

不是说改变原有对象就是危险的,比如delete这个方法,语义很明确,就是会删除数组里的元素,改变原有数组。所以它不危险。

我的理解是这样:就像枪本来就是用来杀人的,不会在上面贴一个危险的标签,但是液化气不是用来杀人的,但是会引起危险,

所以通常看到被贴上危险的标签。

带!的方法一定成对出现

也就是说,如果存在一个xx!方法,就必然存在一个xx方法。反之不然。

这也是它危险的表现。

就是说,这个方法的语义可能是a,也可能是b,如果你不小心,就容易搞错。

真的是成对出现:-)

ruby-1.9.3-p0 :009 > "".methods.grep(/\w!/).map{|x| "".methods.include?(x.to_s.tr("!", "").to_sym) }
 => [true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true] 
ruby-1.9.3-p0 :010 > [].methods.grep(/\w!/).map{|x| [].methods.include?(x.to_s.tr("!", "").to_sym) }
 => [true, true, true, true, true, true, true, true, true, true, true, true, true]

危险的另一种解释

Rails里的save和save!可以更好的帮我们理解危险的意思。

普通的save在validation失败的时候返回false,而save!则抛出异常。

抛异常了你的server会500。这是多么的危险啊!!一定要小心使用,除非你早已经预料到了。

Yui说“force_encoding is another problem”

> Just for the record, there is one method that I think we should add a bang if we still could, and this is String#force_encoding. The reason isn’t that it changes String itself (which it does), but that I have come across quite some places where I use string.dup.force_encoding. It would have been best to use force_encoding! for what’s now force_encoding, and force_encoding for the copying variant. But I agree with both Michaels and Yui that it’s too late to change.

About String#force_encoding, I think add an alias named String#encoding= may be good. But it’s still under consideration.

相关链接

标签 Bang, force_encoding, save, gsub, delete, clear

Avatar
googya 接近 8 年 前

嗯,对!有了新的认识了。。。不止是修改原来的东西那么简单!不过,对于rails的!的用法是否符合ruby的习惯存有疑虑!

(使用BBCodeTextileGist)