首页 文章

为什么Ruby方法中使用感叹号?

提问于
浏览
462

在Ruby中,一些方法有一个问号( ? ),它询问像 include? 这样的问题,询问是否包含有问题的对象,然后返回true / false .

但是为什么有些方法会有感叹号( ! )而其他方法却没有?

这是什么意思?

10 回答

  • 14

    简单说明:

    foo = "BEST DAY EVER" #assign a string to variable foo.
    
    => foo.downcase #call method downcase, this is without any exclamation.
    
    "best day ever"  #returns the result in downcase, but no change in value of foo.
    
    => foo #call the variable foo now.
    
    "BEST DAY EVER" #variable is unchanged.
    
    => foo.downcase! #call destructive version.
    
    => foo #call the variable foo now.
    
    "best day ever" #variable has been mutated in place.
    

    但是如果您在上面的解释中调用了方法 downcase!foo 将永久更改为downcase . downcase! 不会返回一个新的字符串对象,而是替换该字符串,完全将 foo 更改为downcase . 我建议你不要使用 downcase! ,除非它是完全必要的 .

  • 539

    通常,以 ! 结尾的方法表示该方法将为 modify the object it's called on . Ruby将这些称为“ dangerous methods ”,因为它们会更改其他人可能引用的状态 . 这是一个简单的字符串示例:

    foo = "A STRING"  # a string called foo
    foo.downcase!     # modifies foo itself
    puts foo          # prints modified foo
    

    这将输出:

    a string
    

    在标准库中,有很多地方你会看到一对类似命名的方法,一个用 ! ,一个没用 . 没有的那些被称为"safe methods",并且它们返回原始的副本,其中更改应用于 the copy ,被调用者保持不变 . 这是没有 ! 的相同示例:

    foo = "A STRING"    # a string called foo
    bar = foo.downcase  # doesn't modify foo; returns a modified string
    puts foo            # prints unchanged foo
    puts bar            # prints newly created bar
    

    这输出:

    A STRING
    a string
    

    请记住,这只是一个约定,但很多Ruby类都遵循它 . 它还可以帮助您跟踪代码中修改的内容 .

  • 6

    感叹号意味着许多事情,除了“这是危险的,要小心”之外,有时你不能从中得到很多 .

    正如其他人所说,在标准方法中,它有一个感叹号( popshiftclear ),并且一些带感叹号的方法不会改变它们的接收器( exit! ) . 例如,请参见this article .

    其他库可能使用不同的方式 . 在Rails中,感叹号通常意味着该方法将在失败时抛出异常,而不是静默失败 .

    这是一个命名惯例,但许多人以微妙的方式使用它 . 在你自己的代码中,一个好的经验法则是在方法执行“危险”操作时使用它,特别是当存在两个具有相同名称的方法且其中一个比另一个更“危险”时 . “危险”几乎可以表示任何意义 .

  • 127

    来自themomorohoax.com:

    根据我的个人喜好,可以按照以下方式使用爆炸 .

    1)如果方法没有按照预期的方式执行,则活动记录方法会引发错误 . 2)活动记录方法保存记录或方法保存对象(例如条带!)3)方法执行“额外”操作,例如发布到某个地方,或执行某些操作 .

    关键是:当你真正考虑是否有必要时,只使用一声巨响,以免其他开发人员烦恼,不得不检查你使用爆炸的原因 .

    爆炸为其他开发者提供了两个线索 .

    1)调用方法后没有必要保存对象 . 2)当你调用方法时,db将被更改 .

    http://www.themomorohoax.com/2009/02/11/when-to-use-a-bang-exclamation-point-after-rails-methods

  • 63

    此命名约定从Scheme解除 .

    1.3.5命名约定按照惯例,总是返回布尔值的过程名称通常以“?”结尾 . 这样的过程称为谓词 . 按照惯例,将值存储到先前分配的位置(参见3.4节)的过程名称通常以“!”结尾 . 这种程序称为变异程序 . 按照惯例,突变过程返回的值未指定 .

  • 0

    被称为“破坏性方法”他们倾向于更改您所指对象的原始副本 .

    numbers=[1,0,10,5,8]
    numbers.collect{|n| puts n*2} # would multiply each number by two
    numbers #returns the same original copy
    numbers.collect!{|n| puts n*2} # would multiply each number by two and destructs the original copy from the array
    numbers   # returns [nil,nil,nil,nil,nil]
    
  • 1

    !通常意味着该方法作用于对象而不是返回结果 . 从书Programming Ruby

    “危险”或修改接收器的方法可能以尾随“!”命名 .

  • 23

    最准确的说方法是用Bang!是dangeroussurprising版本 . 有许多方法可以在没有Bang的情况下进行变异,例如.destroy,并且通常方法只有在核心库中存在更安全的替代方法的方法 .

    例如,在Array上我们有 .compact.compact! ,两个方法都会改变数组,但如果数组中没有nil,则 .compact! 返回nil而不是self,这比返回self更令人惊讶 .

    我发现爆炸的唯一非变异方法是 Kernel.exit!,这比 .exit 更令人惊讶,因为在进程结束时你无法捕获 SystemExit .

    Rails和ActiveRecord延续了这一趋势,因为它使用了更多的'surprising'效果,如.create!,这会在失败时引发错误 .

  • 0

    底线: ! 方法只是更改它们被调用的对象的值,而没有 ! 的方法返回一个被操纵的值,而不会写入调用该方法的对象 .

    如果您不打算需要,请仅使用 ! 原始值存储在您调用方法的变量上 .

    我喜欢做类似的事情:

    foo = "word"
    bar = foo.capitalize
    puts bar
    

    要么

    foo = "word"
    puts foo.capitalize
    

    代替

    foo = "word"
    foo.capitalize!
    puts foo
    

    以防我想再次访问原始值 .

  • 14
    !
    

    我认为这是一个爆炸性的变化,它会摧毁它前面的一切 . Bang或感叹号表示您在代码中进行了永久保存的更改 .

    如果您使用Ruby的全局替换方法 gsub! ,您所做的替换是永久性的 .

    您可以想象的另一种方法是打开文本文件并进行查找和替换,然后保存 . ! 在您的代码中也是如此 .

    如果你来自bash世界,另一个有用的提醒是 sed -i 具有类似的效果,可以永久保存更改 .

相关问题