Ruby memiliki gagasan universal tentang " kebenaran " dan " kepalsuan ".
Ruby memang memiliki dua kelas khusus untuk objek Boolean, TrueClass
dan FalseClass
, dengan instance tunggal dilambangkan oleh variabel khusus true
dan false
, masing-masing.
Namun, kebenaran dan kepalsuan tidak terbatas pada contoh dua kelas itu, konsepnya bersifat universal dan berlaku untuk setiap objek tunggal di Ruby. Setiap objek adalah baik truthy atau falsy . Aturannya sangat sederhana. Secara khusus, hanya dua objek yang palsu :
nil
, contoh tunggal dariNilClass
danfalse
, contoh tunggal dariFalseClass
Setiap objek tunggal lainnya adalah truthy . Ini termasuk objek genap yang dianggap falsy dalam bahasa pemrograman lain, seperti
Aturan-aturan ini dibangun ke dalam bahasa dan tidak dapat didefinisikan pengguna. Tidak ada to_bool
konversi tersirat atau yang serupa.
Berikut ini kutipan dari Spesifikasi Bahasa Ruby ISO :
6.6 Nilai Boolean
Suatu objek diklasifikasikan menjadi objek trueish atau objek falseish .
Hanya false dan nil yang merupakan objek falseish. false adalah satu-satunya instance dari kelas
FalseClass
(lihat 15.2.6), di mana ekspresi-palsu mengevaluasi (lihat 11.5.4.8.3). nil adalah satu-satunya instance dari kelasNilClass
(lihat 15.2.4), yang dievaluasi nil-ekspresi (lihat 11.5.4.8.2).Objek selain false dan nil diklasifikasikan menjadi objek trueish. true adalah satu-satunya instance dari kelas
TrueClass
(lihat 15.2.5), yang dievaluasi oleh ekspresi-sejati (lihat 11.5.4.8.3).
Ruby / Spec yang dapat dieksekusi tampaknya setuju :
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
Menurut dua sumber, saya akan berasumsi bahwa Regexp
s juga truthy , tetapi menurut tes saya, mereka tidak:
if // then 'Regexps are truthy' else 'Regexps are falsy' end
#=> 'Regexps are falsy'
Saya menguji ini pada YARV 2.7.0-preview1 , TruffleRuby 19.2.0.1 , dan JRuby 9.2.8.0 . Ketiga implementasi setuju satu sama lain dan tidak setuju dengan Spesifikasi Bahasa Ruby ISO dan interpretasi saya terhadap Ruby / Spec.
Lebih tepatnya, Regexp
benda-benda yang merupakan hasil dari evaluasi Regexp
literal adalah falsy , sedangkan Regexp
benda-benda yang merupakan hasil dari beberapa ekspresi lainnya adalah truthy :
r = //
if r then 'Regexps are truthy' else 'Regexps are falsy' end
#=> 'Regexps are truthy'
Apakah ini bug, atau perilaku yang diinginkan?
Regex.new("a")
adalah kebenaran.!!//
itu salah tetapi!!/r/
itu benar. Memang aneh.!!/r/
menghasilkanfalse
untuk saya menggunakan (RVM) Ruby 2.4.1.//
dalamif // then
diartikan sebagai tes (jalan pintas untukif //=~nil then
) (yang selalu salah pola apa pun) dan bukan sebagai contoh Regexp.Jawaban:
Ini bukan bug. Apa yang terjadi adalah Ruby menulis ulang kode itu
menjadi efektif
Jika Anda menjalankan kode ini dalam skrip normal (dan tidak menggunakan
-e
opsi) maka Anda akan melihat peringatan:Ini mungkin agak membingungkan sebagian besar waktu, itulah sebabnya peringatan diberikan, tetapi dapat berguna untuk satu baris menggunakan
-e
opsi. Misalnya Anda dapat mencetak semua baris yang cocok dengan regexp yang diberikan dari file dengan(Argumen default untuk
print
ini$_
juga.)sumber
-n
,-p
,-a
dan-l
pilihan, serta beberapa metode Kernel yang hanya tersedia bila-n
atau-p
digunakan (chomp
,chop
,gsub
dansub
).NODE_LIT
dengan tipeT_REGEXP
. Yang Anda posting dalam jawaban Anda adalah untuk literal dinamisRegexp
, yaituRegexp
literal yang menggunakan interpolasi, misalnya/#{''}/
.$_
sebagai simpul yang ditangani oleh kompiler seperti biasa, sementara dalam kasus statis semuanya ditangani oleh penyusun. Yang memalukan bagi saya karena "hei, Anda dapat melihat di mana pohon parse ditulis ulang di sini" membuat jawaban yang bagus.Ini adalah hasil dari (sejauh yang saya tahu) fitur tidak terdokumentasi dari bahasa ruby, yang paling baik dijelaskan oleh spesifikasi ini :
Anda umumnya dapat menganggap
$_
sebagai "string terakhir dibaca olehgets
"Untuk membuat masalah lebih membingungkan,
$_
(bersama dengan$-
) bukan variabel global; ini memiliki ruang lingkup lokal .Saat skrip ruby dimulai
$_ == nil
,.Jadi kodenya:
Ditafsirkan seperti:
... Yang mengembalikan falsey.
Di sisi lain, untuk regexp non-literal (misalnya
r = //
atauRegexp.new('')
), interpretasi khusus ini tidak berlaku.//
benar; sama seperti semua objek lain di ruby selainnil
danfalse
.Kecuali menjalankan skrip ruby langsung pada baris perintah (yaitu dengan
-e
bendera), parser ruby akan menampilkan peringatan terhadap penggunaan tersebut:Anda bisa memanfaatkan perilaku ini dalam skrip, dengan sesuatu seperti:
... Tetapi akan lebih normal untuk menetapkan variabel lokal ke hasil
gets
dan melakukan pemeriksaan regex terhadap nilai ini secara eksplisit.Saya tidak mengetahui adanya kasus penggunaan untuk melakukan pemeriksaan ini dengan regex kosong , terutama ketika didefinisikan sebagai nilai literal. Hasil yang Anda sorot memang akan membuat sebagian besar pengembang rubi lengah.
sumber
!// #=> true
memiliki perilaku yang sama dan tidak dalam kondisi. Saya tidak dapat menemukan konteks boolean (bersyarat atau tidak), di mana ia berperilaku seperti yang diharapkan.!// ? true : false
kembalitrue
? Saya pikir ini adalah poin yang sama lagi - ini sedang ditafsirkan seperti:!(// =~ nil) ? true : false
$_ = 'hello world'
sebelum menjalankan kode di atas, maka Anda harus mendapatkan hasil yang berbeda - karena// =~ 'hello world'
, tetapi tidak cocoknil
.!//
tanpa syarat untuk mengevaluasitrue
. Spesifikasi yang Anda kutip adalah tentangRegexp
literal dalam kondisi, tetapi dalam contoh ini, tidak ada kondisi, jadi spesifikasi ini tidak berlaku.puts !//; $_ = ''; puts !//
- Saya kira karena parser memperluasnya seperti makro; itu tidak perlu harus di dalam kondisi?