簡體   English   中英

為什么正則表達式 object 在 Ruby 中被認為是“虛假的”?

[英]Why is a Regexp object considered to be “falsy” in Ruby?

Ruby具有“真”和“”的普遍觀念。

Ruby確實有兩個針對 Boolean 對象的特定類TrueClassFalseClass ,其中 singleton 實例分別由特殊變量truefalse表示。

但是,真假不限於這兩個類的實例,這個概念是通用的,適用於Ruby中的每個 object。 每個object要么為真,要么為 規則非常簡單。 特別是,只有兩個對象是虛假的

其他每一個 object都是真實的。 這甚至包括在其他編程語言中被認為是虛假的對象,例如

這些規則是內置在語言中的,不是用戶可定義的。 沒有to_bool隱式轉換或類似的東西。

這是來自ISO Ruby 語言規范的引用:

6.6 Boolean 值

object 被分類為真實的object或虛假的object

只有falsenil是虛假對象。 falseclass FalseClass的唯一實例(請參見 15.2.6),對其進行評估(請參見 11.5.4.8.3)。 nil是 class NilClass的唯一實例(參見 15.2.4), nil 表達式對其求值(參見 11.5.4.8.2)。

除了falsenil之外的對象被歸類為 true 對象。 true是 class TrueClass的唯一實例(見 15.2.5),真表達式求值(見 11.5.4.8.3)。

可執行的 Ruby/Spec 似乎同意

 it "considers a non-nil and non-boolean object in expression result as true" do if mock('x') 123 else 456 end.should == 123 end

根據這兩個來源,我會假設Regexp s也是truthy ,但根據我的測試,它們不是:

if // then 'Regexps are truthy' else 'Regexps are falsy' end
#=> 'Regexps are falsy'

我在YARV 2.7.0-preview1TruffleRuby 19.2.0.1JRuby 9.2.8.0上對此進行了測試。 所有三個實現都相互同意,並且不同意 ISO Ruby 語言規范和我對 Ruby/Spec 的解釋。

更准確地說,作為計算Regexp文字結果的Regexp對象是falsy ,而作為其他表達式結果的Regexp對象是truthy

r = //
if r then 'Regexps are truthy' else 'Regexps are falsy' end
#=> 'Regexps are truthy'

這是一個錯誤,還是期望的行為?

這不是錯誤。 發生的事情是 Ruby 正在重寫代碼,以便

if /foo/
  whatever
end

有效地變成

if /foo/ =~ $_
  whatever
end

如果您在普通腳本中運行此代碼(而不是使用-e選項),那么您應該會看到一個警告:

warning: regex literal in condition

大多數時候這可能有點令人困惑,這就是給出警告的原因,但對於使用-e選項的一行可能很有用。 例如,您可以打印文件中與給定正則表達式匹配的所有行

$ ruby -ne 'print if /foo/' filename

print的默認參數也是$_ 。)

這是(據我所知)ruby 語言的未記錄功能的結果, 此規范對此進行了最佳解釋:

it "matches against $_ (last input) in a conditional if no explicit matchee provided" do
  -> {
    eval <<-EOR
    $_ = nil
    (true if /foo/).should_not == true
    $_ = "foo"
    (true if /foo/).should == true
    EOR
  }.should complain(/regex literal in condition/)
end

您通常可以將$_視為“ gets讀取的最后一個字符串”

更令人困惑的是, $_ (與$-一起)不是全局變量; 它有本地 scope


當 ruby 腳本啟動時, $_ == nil

所以,代碼:

// ? 'Regexps are truthy' : 'Regexps are falsey'

被解釋為:

(// =~ nil) ? 'Regexps are truthy' : 'Regexps are falsey'

...返回錯誤。

另一方面,對於非文字正則表達式(例如r = //Regexp.new('') ),這種特殊解釋不適用。

//是真實的; 就像除nilfalse之外的 ruby 中的所有其他 object 一樣。


除非直接在命令行上運行 ruby 腳本(即使用-e標志),否則 ruby 解析器將針對此類用法顯示警告:

警告:條件中的正則表達式文字

可以在腳本中使用此行為,例如:

puts "Do you want to play again?"
gets
# (user enters e.g. 'Yes' or 'No')
/y/i ? play_again : back_to_menu

...但是將局部變量分配給gets的結果並顯式地對該值執行正則表達式檢查會更正常。

我不知道使用正則表達式執行此檢查的任何用例,尤其是在定義為文字值時。 您強調的結果確實會讓大多數 ruby 開發人員措手不及。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM