Como posso verificar se uma variável está definida no Ruby? Existe um isset
método -type disponível?
Como posso verificar se uma variável está definida no Ruby? Existe um isset
método -type disponível?
Respostas:
Use a defined?
palavra - chave ( documentação ). Ele retornará uma String com o tipo do item, ou nil
se ele não existir.
>> a = 1
=> 1
>> defined? a
=> "local-variable"
>> defined? b
=> nil
>> defined? nil
=> "nil"
>> defined? String
=> "constant"
>> defined? 1
=> "expression"
Como skalee comentou: "Vale a pena notar que a variável definida como zero é inicializada".
>> n = nil
>> defined? n
=> "local-variable"
||=
operador) abaixo.
defined?
ainda retornará true para uma variável definida dentro desse bloco!
defined?
esse retorna booleano?
!!defined?(object_name)
Isso é útil se você não quiser fazer nada, se existir, mas criá-lo, se não existir.
def get_var
@var ||= SomeClass.new()
end
Isso cria apenas a nova instância uma vez. Depois disso, ele continua retornando o var.
||=
com valores booleanos, para que você não sinta a dor da confusão.
nil
bem menos que você realmente quer para avaliar a expressão cada vez que é chamado quando ele retornarnil
var = (var or var.nil?)
A sintaxe correta para a instrução acima é:
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
substituindo ( var
) por sua variável. Essa sintaxe retornará um valor verdadeiro / falso para avaliação na instrução if.
defined?(var) == nil
?
.nil?
é mais idiomático, como eles dizem. É mais "orientado a objetos" perguntar a um objeto se ele nil
do que usar um operador de comparação. Não é difícil ler, portanto, use o que for necessário para enviar mais produtos.
defined?(your_var)
vai funcionar. Dependendo do que você está fazendo, você também pode fazer algo comoyour_var.nil?
your_var.nil?
porque retorna true de false e é muito melhor ler e escrever do que defined? var
. Obrigado por isso.
your_var.nil?
resultará em erro: undefined local variable or method your_var
quando não definido antes ...
Tente "a menos que" em vez de "se"
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
Aqui está algum código, nada de ciência de foguetes, mas funciona bem o suficiente
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
Claramente, o código de coloração não é necessário, apenas uma boa visualização neste exemplo de brinquedo.
nil?
é opcional.
Esta é a resposta principal: o defined?
método A resposta aceita acima ilustra isso perfeitamente.
Mas há um tubarão, escondido sob as ondas ...
Considere este tipo de padrão ruby comum:
def method1
@x ||= method2
end
def method2
nil
end
method2
sempre retorna nil
. A primeira vez que você chama method1
, a @x
variável não está definida - portanto method2
, será executada. e method2
será definido @x
como nil
. Tudo bem, tudo muito bem. Mas o que acontece na segunda vez que você ligamethod1
?
Lembre-se de que @x já foi definido como nulo. But method2
ainda será executado novamente !! Se o método2 for um empreendimento caro, isso pode não ser o desejado.
Deixe o defined?
método ajudar - com esta solução, esse caso específico é tratado - use o seguinte:
def method1
return @x if defined? @x
@x = method2
end
O diabo está nos detalhes: mas você pode escapar desse tubarão à espreita com o defined?
método.
Podes tentar:
unless defined?(var)
#ruby code goes here
end
=> true
Porque retorna um valor booleano.
SyntaxError: compile error (irb):2: syntax error, unexpected $end, expecting kEND
unless
declaração parece muito complicado
Como muitos outros exemplos mostram, você realmente não precisa de um booleano de um método para fazer escolhas lógicas em ruby. Seria uma forma ruim coagir tudo a um booleano, a menos que você realmente precise de um booleano.
Mas se você absolutamente precisa de um booleano. Usar !! (bang bang) ou "falsy falsy revela a verdade".
› irb
>> a = nil
=> nil
>> defined?(a)
=> "local-variable"
>> defined?(b)
=> nil
>> !!defined?(a)
=> true
>> !!defined?(b)
=> false
Por que geralmente não vale a pena coagir:
>> (!!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
Aqui está um exemplo em que isso é importante porque se baseia na coerção implícita do valor booleano à sua representação de string.
>> puts "var is defined? #{!!defined?(a)} vs #{defined?(a)}"
var is defined? true vs local-variable
=> nil
Deve-se mencionar que usar defined
para verificar se um campo específico está definido em um hash pode se comportar inesperadamente:
var = {}
if defined? var['unknown']
puts 'this is unexpected'
end
# will output "this is unexpected"
A sintaxe está correta aqui, mas defined? var['unknown']
será avaliada para a sequência "method"
, para que o if
bloco seja executado
edit: A notação correta para verificar se existe uma chave em um hash seria:
if var.key?('unknown')
Observe a distinção entre "definido" e "atribuído".
$ ruby -e 'def f; if 1>2; x=99; end;p x, defined? x; end;f'
nil
"local-variable"
x é definido mesmo que nunca seja atribuído!
NameError Exception: undefined local variable or method
e fiquei confuso quando a única atribuição / menção da variável estava em um bloco if que não estava sendo atingido.
Além disso, você pode verificar se ele está definido enquanto está em uma string por interpolação, se você codificar:
puts "Is array1 defined and what type is it? #{defined?(@array1)}"
O sistema informará o tipo, se estiver definido. Se não estiver definido, retornará apenas um aviso dizendo que a variável não foi inicializada.
Espero que isto ajude! :)
defined?
é ótimo, mas se você estiver em um ambiente Rails, também poderá usá-lo try
, especialmente nos casos em que deseja verificar o nome de uma variável dinâmica:
foo = 1
my_foo = "foo"
my_bar = "bar"
try(:foo) # => 1
try(:bar) # => nil
try(my_foo) # => 1
try(my_bar) # => nil
nil
é inicializada.