Jak mogę sprawdzić, czy zmienna jest zdefiniowana w Ruby? Czy dostępna jest isset
metoda typu?
Jak mogę sprawdzić, czy zmienna jest zdefiniowana w Ruby? Czy dostępna jest isset
metoda typu?
Odpowiedzi:
Użyj defined?
słowa kluczowego ( dokumentacja ). Zwróci ciąg znaków z rodzajem elementu lub nil
jeśli nie istnieje.
>> a = 1
=> 1
>> defined? a
=> "local-variable"
>> defined? b
=> nil
>> defined? nil
=> "nil"
>> defined? String
=> "constant"
>> defined? 1
=> "expression"
Jak zauważył skalee: „Warto zauważyć, że zmienna ustawiona na zero jest inicjalizowana”.
>> n = nil
>> defined? n
=> "local-variable"
||=
operatora) poniżej.
defined?
nadal zwraca wartość true dla zmiennej zdefiniowanej w tym bloku!
defined?
która zwraca wartość logiczną?
!!defined?(object_name)
Jest to przydatne, jeśli nie chcesz nic robić, jeśli istnieje, ale utwórz go, jeśli nie istnieje.
def get_var
@var ||= SomeClass.new()
end
To tworzy nową instancję tylko raz. Potem po prostu zwraca var.
||=
wartości boolowskich, aby nie poczuć bólu pomieszania.
nil
chyba że naprawdę chcesz oceniać wyrażenie za każdym razem, gdy jest wywoływane, gdy ono powracanil
var = (var or var.nil?)
Prawidłowa składnia powyższej instrukcji to:
if (defined?(var)).nil? # will now return true or false
print "var is not defined\n".color(:red)
else
print "var is defined\n".color(:green)
end
podstawiając ( var
) swoją zmienną. Ta składnia zwróci wartość prawda / fałsz do oceny w instrukcji if.
defined?(var) == nil
?
.nil?
jest bardziej idiomatyczne, jak mówią. Bardziej „obiektowo” jest pytać obiekt, czy jest nil
to operator niż porównywanie. Żadna z tych rzeczy nie jest trudna do odczytania, więc użyj którejkolwiek, która pomoże Ci wysłać więcej produktów.
defined?(your_var)
będzie działać. W zależności od tego, co robisz, możesz także zrobić coś takiegoyour_var.nil?
your_var.nil?
ponieważ zwraca wartość prawda fałszu i jest o wiele ładniejszy do odczytu i zapisu niż defined? var
. Dzięki za to.
your_var.nil?
spowoduje błąd: undefined local variable or method your_var
jeśli nie zdefiniowano wcześniej ...
Spróbuj „chyba” zamiast „jeśli”
a = "apple"
# Note that b is not declared
c = nil
unless defined? a
puts "a is not defined"
end
unless defined? b
puts "b is not defined"
end
unless defined? c
puts "c is not defined"
end
Oto kod, nic, nauka rakietowa, ale działa wystarczająco dobrze
require 'rubygems'
require 'rainbow'
if defined?(var).nil? # .nil? is optional but might make for clearer intent.
print "var is not defined\n".color(:red)
else
print "car is defined\n".color(:green)
end
Oczywiście kod kolorowania nie jest konieczny, tylko ładna wizualizacja w tym przykładzie zabawki.
nil?
jest opcjonalny.
Oto kluczowa odpowiedź: defined?
metoda. Powyższa odpowiedź doskonale to ilustruje.
Ale pod falami czai się rekin ...
Rozważ ten typ wspólnego wzoru rubinowego:
def method1
@x ||= method2
end
def method2
nil
end
method2
zawsze wraca nil
. Gdy po raz pierwszy nazywają method1
The @x
zmienna nie jest ustawiona - zatem method2
będą działać. i method2
ustawi @x
na nil
. W porządku, a wszystko dobrze i dobrze. Ale co się stanie, kiedy zadzwonisz po raz drugi method1
?
Pamiętaj, że @x zostało już ustawione na zero. But method2
nadal będzie uruchamiany ponownie !! Jeśli metoda 2 jest kosztownym przedsięwzięciem, może nie być to coś, czego chcesz.
Niech defined?
metoda przyjdzie na ratunek - dzięki temu rozwiązaniu, że konkretny przypadek jest obsługiwany - użyj następujących poleceń:
def method1
return @x if defined? @x
@x = method2
end
Diabeł tkwi w szczegółach: ale tą defined?
metodą możesz uniknąć tego czającego się rekina .
Możesz spróbować:
unless defined?(var)
#ruby code goes here
end
=> true
Ponieważ zwraca wartość logiczną.
SyntaxError: compile error (irb):2: syntax error, unexpected $end, expecting kEND
unless
oświadczenia wydaje się zbyt skomplikowane
Ponieważ wiele innych przykładów pokazuje, że tak naprawdę nie potrzebujesz logicznej metody, aby dokonać logicznych wyborów w Rubim. Byłoby kiepską formą przymuszanie wszystkiego do wartości logicznej, chyba że faktycznie potrzebujesz wartości logicznej.
Ale jeśli absolutnie potrzebujesz wartości logicznej. Posługiwać się !! (Bang Bang) lub „Falsy Falsy ujawnia prawdę”.
› irb
>> a = nil
=> nil
>> defined?(a)
=> "local-variable"
>> defined?(b)
=> nil
>> !!defined?(a)
=> true
>> !!defined?(b)
=> false
Dlaczego zwykle nie opłaca się wymuszać:
>> (!!defined?(a) ? "var is defined".colorize(:green) : "var is not defined".colorize(:red)) == (defined?(a) ? "var is defined".colorize(:green) : "var is not defined".colorize(:red))
=> true
Oto przykład, w którym ma to znaczenie, ponieważ opiera się na domniemanym przymusie wartości logicznej do jego reprezentacji ciągu.
>> puts "var is defined? #{!!defined?(a)} vs #{defined?(a)}"
var is defined? true vs local-variable
=> nil
Należy wspomnieć, że użycie defined
do sprawdzenia, czy określone pole w haszowaniu może zachowywać się nieoczekiwanie:
var = {}
if defined? var['unknown']
puts 'this is unexpected'
end
# will output "this is unexpected"
Składnia jest tutaj poprawna, ale defined? var['unknown']
zostanie przetworzona na ciąg znaków "method"
, więcif
blok zostanie wykonany
edytuj: Poprawnym zapisem do sprawdzania, czy klucz istnieje w haszowaniu byłoby:
if var.key?('unknown')
Zwróć uwagę na rozróżnienie między „zdefiniowanym” a „przypisanym”.
$ ruby -e 'def f; if 1>2; x=99; end;p x, defined? x; end;f'
nil
"local-variable"
x jest zdefiniowane, nawet jeśli nigdy nie jest przypisane!
NameError Exception: undefined local variable or method
i byłem zdezorientowany, gdy jedynym przypisaniem / wzmianką o zmiennej był blok if, który nie został trafiony.
Możesz również sprawdzić, czy jest zdefiniowany w ciągu znaków za pomocą interpolacji, jeśli kodujesz:
puts "Is array1 defined and what type is it? #{defined?(@array1)}"
System poinformuje o typie, jeśli jest zdefiniowany. Jeśli nie zostanie zdefiniowane, zwróci tylko ostrzeżenie, że zmienna nie została zainicjowana.
Mam nadzieję że to pomoże! :)
defined?
jest świetny, ale jeśli jesteś w środowisku Railsów, możesz również użyć try
, szczególnie w przypadkach, gdy chcesz sprawdzić nazwę zmiennej dynamicznej:
foo = 1
my_foo = "foo"
my_bar = "bar"
try(:foo) # => 1
try(:bar) # => nil
try(my_foo) # => 1
try(my_bar) # => nil
nil
jest inicjalizowana.