Brian
Brian

Reputation: 13593

Defining a method that checks the existence of a variable

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

Answers (3)

Sam Farmer
Sam Farmer

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

Jörg W Mittag
Jörg W Mittag

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

Awlad Liton
Awlad Liton

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

Related Questions