Проверка, определена ли переменная?

Как я могу проверить, определена ли переменная в Ruby? Есть ли isset-тип доступный способ?

14 ответов


использовать defined? ключевое слово (документация). Он вернет строку с типом элемента или nil если он не существует.

>> a = 1
 => 1
>> defined? a
 => "local-variable"
>> defined? b
 => nil
>> defined? nil
 => "nil"
>> defined? String
 => "constant"
>> defined? 1
 => "expression"

как прокомментировал Скали: "стоит отметить, что переменная, которая установлена в ноль, инициализируется."

>> n = nil  
>> defined? n
 => "local-variable"

это полезно, если вы хотите ничего не делать, если он существует, но создать его, если он не существует.

def get_var
  @var ||= SomeClass.new()
end

это создает новый экземпляр только один раз. После этого он просто возвращается к Варе.


правильный синтаксис для приведенного выше утверждения:

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?(your_var) будет работать. В зависимости от того, что вы делаете, вы также можете сделать что-то вроде your_var.nil?


попробуйте "если" вместо "Если"

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

использовать defined? YourVariable
держите его просто глупо .. ;)


можно попробовать:

unless defined?(var)
  #ruby code goes here
end
=> true

потому что он возвращает boolean.


вот какой-то код, ничего ракетостроения, но он работает достаточно хорошо

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

ясно, что код окраски не нужен, просто хорошая визуализация в этом примере игрушки.


Это ключевой ответ: определяешь? метод. Принятый выше ответ прекрасно иллюстрирует это.

но есть акула, скрывающаяся под волнами...

рассмотрим этот тип общего рубинового шаблона:

 def method1
    @x ||= method2
 end

 def method2
    nil
 end

давайте остановимся и подумаем об этом на секунду. Метод 2 всегда возвращает nil. При первом вызове method1 переменная @x не задана - поэтому method2 будет запущен. и Метод 2 установит @x в ноль. Это прекрасно, и все хорошо. Но что происходит во второй раз, когда вы вызываете method1?

помните, что @x уже установлен в ноль. Но метод 2 все равно будет запущен снова? Если method2 является дорогостоящим предприятием, это может быть не то, что вы хотите.

дай определение? метод пришел на помощь

  def method1
    return @x if defined? @x
    @x = method2
  end

Если вы не знали об этом трюке, ну тогда "вам понадобится большая лодка".


как показывают многие другие примеры, вам на самом деле не нужно логическое значение из метода, чтобы сделать логический выбор в ruby. Было бы плохой формой принудить все к логическому, если вам действительно не нужно логическое.

но если вам абсолютно нужно логическое значение. Использовать !! (бах-бах) или "ложь, ложь раскрывает истину".

› 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

обратите внимание на различие между "определенными"и " назначенными".

$ ruby -e 'def f; if 1>2; x=99; end;p x, defined? x; end;f'
nil
"local-variable"

x определяется, даже если он никогда не назначается!


следует отметить, что использование 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')

кроме того, вы можете проверить, определено ли оно в строке с помощью интерполяции, если вы кодируете:

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