Як я можу перевірити, чи визначена змінна в Ruby? Чи isset
доступний метод -типу?
Як я можу перевірити, чи визначена змінна в Ruby? Чи isset
доступний метод -типу?
Відповіді:
Використовуйте defined?
ключове слово ( документація ). Він поверне рядок із типом елемента або nil
якщо його не існує.
>> a = 1
=> 1
>> defined? a
=> "local-variable"
>> defined? b
=> nil
>> defined? nil
=> "nil"
>> defined? String
=> "constant"
>> defined? 1
=> "expression"
Як коментує skalee: "Варто зазначити, що змінна, яка встановлена на нуль, ініціалізується".
>> n = nil
>> defined? n
=> "local-variable"
||=
оператора) нижче.
defined?
все одно повертається true для змінної, визначеної в цьому блоці!
defined?
що повертає булевий?
!!defined?(object_name)
Це корисно, якщо ви не хочете нічого робити, якщо він існує, але створити його, якщо його немає.
def get_var
@var ||= SomeClass.new()
end
Це створює новий екземпляр лише один раз. Після цього він просто продовжує повертати вар.
||=
булеві значення, щоб не відчути біль розгубленості.
nil
, якщо ви дійсно не хочете оцінювати вираз кожен раз, коли воно викликане, коли воно повертаєтьсяnil
var = (var or var.nil?)
Правильний синтаксис для наведеного вище твердження:
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
заміщення ( var
) вашою змінною. Цей синтаксис поверне справжнє / хибне значення для оцінки в операторі if.
defined?(var) == nil
?
.nil?
Як говорять, використання дзвінка до більш ідіоматичного. Більш "об'єктно-орієнтований" запитувати об'єкт, якщо він, nil
ніж використовувати оператор порівняння. Читати це не складно, тому використання того, що допоможе вам доставити більше товару.
defined?(your_var)
буду працювати. Залежно від того, що ви робите, ви можете зробити щось подібнеyour_var.nil?
your_var.nil?
тому що він повертає істинне помилкове значення і набагато приємніше читати і писати, ніж defined? var
. Дякую за це
your_var.nil?
призведе до помилки: undefined local variable or method your_var
коли не визначено раніше ...
Спробуйте "якщо" замість "якщо"
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
Ось якийсь код, нічого ракетного науки, але він працює досить добре
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
Зрозуміло, що забарвлення коду не обов’язкова, просто приємна візуалізація в цьому прикладі іграшки.
nil?
необов'язковий.
Це ключова відповідь: defined?
метод. Прийнята вище відповідь чудово ілюструє це.
Але є акула, яка ховається під хвилями ...
Розглянемо цей тип загального рубінового малюнка:
def method1
@x ||= method2
end
def method2
nil
end
method2
завжди повертається nil
. Перший раз, коли ви телефонуєте method1
, @x
змінна не встановлюється - тому method2
буде запущена. і method2
встановить @x
до nil
. Це добре, і все добре і добре. Але що відбувається вдруге, коли ви телефонуєте method1
?
Пам'ятайте, що @x вже встановлено на нуль. But method2
все одно буде запущений знову !! Якщо method2 є дорогим завданням, це може бути не те, що ви хочете.
Нехай defined?
метод приходить на допомогу - при цьому вирішується конкретний випадок - використовуйте наступне:
def method1
return @x if defined? @x
@x = method2
end
Чорт у деталях: але ви можете уникнути цієї ховаючої акули defined?
методом.
Ви можете спробувати:
unless defined?(var)
#ruby code goes here
end
=> true
Тому що це повертає булеву форму.
SyntaxError: compile error (irb):2: syntax error, unexpected $end, expecting kEND
unless
заяву здається надмірно складним
Як багато інших прикладів показують, що насправді не потрібно булевого методу, щоб зробити логічний вибір у рубіні. Це було б поганою формою, щоб примусити все до булевого, якщо вам насправді не потрібно булеве.
Але якщо вам абсолютно потрібен бул. Використовуйте !! (брехливий вибух) або "фальшивий фальш розкриває правду".
› irb
>> a = nil
=> nil
>> defined?(a)
=> "local-variable"
>> defined?(b)
=> nil
>> !!defined?(a)
=> true
>> !!defined?(b)
=> false
Чому зазвичай не платять примусово:
>> (!!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
Ось приклад, де це має значення, оскільки воно покладається на неявну примус булевого значення до його рядкового подання.
>> puts "var is defined? #{!!defined?(a)} vs #{defined?(a)}"
var is defined? true vs local-variable
=> nil
Слід зазначити, що використання defined
для перевірки, чи певне поле встановлено в хеші, може вести себе несподівано:
var = {}
if defined? var['unknown']
puts 'this is unexpected'
end
# will output "this is unexpected"
Синтаксис тут правильний, але defined? var['unknown']
буде оцінено як рядок "method"
, томуif
блок буде виконаний
edit: Правильне позначення для перевірки наявності ключа в хеші було б:
if var.key?('unknown')
Зверніть увагу на відмінність "визначеного" та "призначеного".
$ ruby -e 'def f; if 1>2; x=99; end;p x, defined? x; end;f'
nil
"local-variable"
x визначено, хоча він ніколи не призначається!
NameError Exception: undefined local variable or method
і розгубився, коли єдине призначення / згадка змінної було в блоці if, який не потрапляв.
Крім того, ви можете перевірити, чи визначено це в рядку за допомогою інтерполяції, якщо ви кодуєте:
puts "Is array1 defined and what type is it? #{defined?(@array1)}"
Система підкаже вам тип, якщо він визначений. Якщо він не визначений, він просто поверне попередження про те, що змінна не ініціалізується.
Сподіваюся, це допомагає! :)
defined?
це чудово, але якщо ви перебуваєте в середовищі Rails, ви також можете користуватися try
, особливо у випадках, коли ви хочете перевірити ім'я динамічної змінної:
foo = 1
my_foo = "foo"
my_bar = "bar"
try(:foo) # => 1
try(:bar) # => nil
try(my_foo) # => 1
try(my_bar) # => nil
nil
, ініціалізується.