Ответы:
Используйте defined?
ключевое слово ( документация ). Он вернет строку с типом элемента или, nil
если он не существует.
>> a = 1
=> 1
>> defined? a
=> "local-variable"
>> defined? b
=> nil
>> defined? nil
=> "nil"
>> defined? String
=> "constant"
>> defined? 1
=> "expression"
Как отметил Скали: «Стоит отметить, что переменная, для которой установлено значение nil, инициализирована».
>> n = nil
>> defined? n
=> "local-variable"
||=
оператором) ниже.
defined?
все равно возвращает true для переменной, определенной в этом блоке!
defined?
возвращает логическое значение?
!!defined?(object_name)
Это полезно, если вы хотите ничего не делать, если он существует, но создавать его, если он не существует.
def get_var
@var ||= SomeClass.new()
end
Это создает новый экземпляр только один раз. После этого он просто продолжает возвращать var.
||=
с булевыми значениями, чтобы не чувствовать боль путаницы.
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
) с вашей переменной. Этот синтаксис вернет значение true / false для оценки в операторе if.
defined?(var) == nil
?
.nil?
Как говорится, использование вызова более идиоматично. Более «объектно-ориентировано» спрашивать объект, если он, nil
чем использовать оператор сравнения. Ни то, ни другое не трудно прочитать, поэтому используйте тот, который поможет вам доставить больше продукта.
defined?(your_var)
будет работать. В зависимости от того, что вы делаете, вы также можете сделать что-то вродеyour_var.nil?
your_var.nil?
потому что он возвращает true из false и гораздо приятнее читать и писать, чем 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?
метод. Принятый ответ выше иллюстрирует это отлично.
Но под волнами скрывается акула ...
Рассмотрим этот тип общего шаблона ruby:
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
утверждение кажется слишком сложным
Как показывают многие другие примеры, на самом деле вам не нужно логическое значение из метода для логического выбора в ruby. Было бы плохой формой привести все к логическому значению, если вам не нужен логический тип.
Но если вам абсолютно необходимо логическое значение. Используйте! (bang bang) или «ложная ложь раскрывает правду».
› 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"
х определяется, хотя он никогда не назначается!
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
это инициализирован.