[英]Convert a regular expression in a string to a regexp object in ruby
[英]Why is a Regexp object considered to be “falsy” in Ruby?
Ruby具有“真”和“假”的普遍觀念。
Ruby確實有兩個針對 Boolean 對象的特定類TrueClass
和FalseClass
,其中 singleton 實例分別由特殊變量true
和false
表示。
但是,真假不限於這兩個類的實例,這個概念是通用的,適用於Ruby中的每個 object。 每個object要么為真,要么為假。 規則非常簡單。 特別是,只有兩個對象是虛假的:
nil
, NilClass 的NilClass
實例和false
, FalseClass 的FalseClass
實例其他每一個 object都是真實的。 這甚至包括在其他編程語言中被認為是虛假的對象,例如
這些規則是內置在語言中的,不是用戶可定義的。 沒有to_bool
隱式轉換或類似的東西。
這是來自ISO Ruby 語言規范的引用:
6.6 Boolean 值
object 被分類為真實的object或虛假的object 。
只有false和nil是虛假對象。 false是class
FalseClass
的唯一實例(請參見 15.2.6),對其進行評估(請參見 11.5.4.8.3)。 nil是 classNilClass
的唯一實例(參見 15.2.4), nil 表達式對其求值(參見 11.5.4.8.2)。除了false和nil之外的對象被歸類為 true 對象。 true是 class
TrueClass
的唯一實例(見 15.2.5),真表達式求值(見 11.5.4.8.3)。
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-preview1 、 TruffleRuby 19.2.0.1和JRuby 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('')
),這種特殊解釋不適用。
//
是真實的; 就像除nil
和false
之外的 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.