Reputation: 13593
Is it possible to define a method a?
which returns true
when a
exists, and returns false
when a
is not defined?
The following code doesn't work, because when defined? a
got executed, variable a
is outside of its scope.
a = 123
def a?
if defined? a
return true
else
return false
end
end
puts a? # false
Is it possible to make the last line of my code return true
?
Upvotes: 1
Views: 57
Reputation: 176
In ruby, the keyword def
acts a scope gate, so you lose access to local variables that are defined outside of the method definition. Alternatively, you can define methods using a block, allowing you access to variables defined outside of the method definition.
a = '123'
define_method 'a?' do
defined? a
end
For more information on this, I highly recommend reading through the first section of Metaprogramming Ruby
Upvotes: -1
Reputation: 369594
No, this is not possible. Local variables are called "local variables" because they are local to the scope they are defined in. They by definition do not exist in other scopes.
What you can do, is re-ify the local scope as a Binding
object by calling Kernel#binding
, and then check whether the local variable is defined in that Binding
using the Binding#local_variable_defined?
method:
def a?(binding)
binding.local_variable_defined?(:a)
end
a?(binding)
# => false
a = 42 if false
a?(binding)
# => true
a
# => nil
Or, more general:
def local_variable_defined?(name, binding)
binding.local_variable_defined?(name)
end
local_variable_defined?(:a, binding)
# => false
a = 42 if false
local_variable_defined?(:a, binding)
# => true
a
# => nil
Upvotes: 3
Reputation: 9351
Defined itself return nil or true based on the existence of the given variable/object.
You should use defined?
method directly instead use another method like this :
if defined?a
puts "defined"
else
puts "not defined"
end
a = 10
if defined?a
puts "defined a: #{a}"
else
puts "not defined"
end
Output:
not defined
defined a: 10
Upvotes: 0