How can a variable have a value and also not be defined? - ruby

I am trying to learn ruby, and have come across something strange. This code:
if defined? branch
puts "param: #{branch}\n"
else
puts "no branch! #{branch}\n"
end
Outputs "no branch! thisisateststring\n", where 'thisisateststring' is the value that has been assigned to the variable branch earlier in the program. How can it be that the variable branch can have a value assigned to it, but not be defined?
Edit:
People seem to not be understanding my question. I am not asking you to figure out why, in this specific instance, the else is being executing; I am asking how can this happen in general. To put it another way, what code would need to be inserted before this, to cause my case to occur?
As I said, I am new to ruby, so I could easily be misunderstanding something basic. I am not trying to solve a specific problem; I am trying to improve my understanding, by learning more about how ruby works. In this instance, how ruby could output a string, while still thinking it is not defined.

#hirolau gave you an example that works. I'd like to reuse his idea and simplify it a little bit for you. Try the following:
defined? foo
=> nil
foo
NameError: undefined local variable or method 'foo' for main:Object
def method_missing(m, *params, &block)
if m.to_s == "foo"
return "cool stuff"
end
end
# foo is still not defined
defined? foo
=> nil
# but returns some value
foo
=> "cool stuff"

Generally no, but Ruby has a lot of ways to handle missing methods and undefined variables. Consider for example:
class Tree
def initialize
if defined? branch
p "param: #{branch}\n"
else
p "no branch! #{branch}\n"
end
end
def method_missing(method_call)
return 'this text comes from method_missing'
end
end
a = Tree.new #=> "no branch! this text comes from method_missing"
class Tree
def branch
return 'NOW I HAVE MY OWN METHOD'
end
end
a = Tree.new #=> "param: NOW I HAVE MY OWN METHOD"
Any more info regarding your problem is very hard to give without the context of the statement.

defined? in Ruby is a keyword.
It returns nil or a description of what the object is as a string.
In Ruby, the only two things that evaluate to false is false and nil
So, if the "thing" that you are trying to find out about is undefined, then defined? will return nil which will evaluate as false in your code, as shown in your question.
To answer your question: "How can a variable have a value and also not be defined?"
It can't. If it isn't defined as a variable, how could it even be a variable. But it can be defined as a variable and have a value of nil.

The defined? Ruby keyword does not check whether a target is nil or not, instead it checks that the target "refers to anything recognizable (literal object, local variable that has been initialized, method name visible from the current scope, etc.)."
Have a look at the documentation to understand its behaviour. http://ruby-doc.org/docs/keywords/1.9/Object.html#method-i-defined-3F
If you want to check if a variable is nil, you can do:
if branch.nil? or branch.empty?
puts "no branch!\n"
else
puts "param: #{branch}\n"
end

Related

Why does a method call need to be disambiguated when it can in principle be a constant?

Method calls can usually omit the receiver and the parentheses for the arguments:
def foo; "foo" end
foo # => "foo"
In the case above, foo is ambiguous between method call and reference to a potential local variable. In the absence of the latter, it is interpreted as a method call.
However, when the method name can in principle be a constant name (i.e., when it starts with a capital letter, and consists only of letters), it seems to need disambiguation.
def Foo; "Foo" end
Foo # => NameError: uninitialized constant Foo
Foo() # => "Foo"
self.Foo # => "Foo"
Why is this the case? Why does a method call need to be explicitly distinguished from a reference to a constant even under the absence of a constant with the same name?
The set of local variables which is in scope at any given point in the program is defined lexically and can thus be determined statically, even as early as parse time. So, Ruby knows even before runtime which local variables are in scope and can thus distinguish between a message send and a local variable dereference.
Constants are looked up first lexically, but then via inheritance, i.e. dynamically. It is not known which constants are in scope before runtime. Therefore, to disambiguate, Ruby always assumes it's a constant, unless obviously it isn't, i.e. it takes arguments or has a receiver or both.
There's no big reason behind the difference. I just wanted foo to be behave like foo(), if there's no local variable foo in the scope. I thought it was useful for creating DSL etc. But I saw no reason to make Foo to behave like Foo().
You ask a great question. As you point out ruby wants to treat it as a constant and therefore do a constant lookup.
The following snippet however shows the current behavior, and then by modifying const_missing, you seem to get the desired behavior. And to tell you the truth I can't seem to break anything.
My conclusion is that this was as somebody already suggested, just a design decision, but its odd because in general ruby favors convention vs enforcement.
Or I am missing some case where things do get confusing and the wrong thing happens.
<script type="text/ruby">
def puts(s); Element['#output'].html = Element['#output'].html + s.to_s.gsub("\n", "<br/>").gsub(" ", " ") + "<br/>"; end
class ImAClass
def self.to_s
"I am ImAClass Class"
end
end
def ImAMethod
"hello"
end
class DontKnowWhatIAm
def self.to_s
"a Class"
end
end
def DontKnowWhatIAm
"a method"
end
puts "ImAClass: #{ImAClass}"
begin
puts "ImAMethod: #{ImAMethod}"
rescue Exception => e
puts "confusion! #{e.message}"
end
puts "ImAMethod(): #{ImAMethod()}"
puts "DontKnowWhatIAm: #{DontKnowWhatIAm}"
puts "DontKnowWhatIAm(): #{DontKnowWhatIAm()}"
class Module
alias_method :old_const_missing, :const_missing
def const_missing(c)
if self.respond_to? c
self.send c
else
old_const_missing(c)
end
end
end
class Foo
def self.Bar
"im at the bar"
end
end
puts "now we can just say: Foo::Bar and it works! #{Foo::Bar}"
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/reactive-ruby/inline-reactive-ruby/master/inline-reactive-ruby.js"></script>
<div id="output" style="font-family: courier"></div>

Is it possibly to call defined? on a dynamic instance variable name?

Is there a way to call check defined? on a dynamic instance variable name? What I want is to be able to do something like this:
dynamic_attr = 'foo'
define_method :my_method do
if defined? instance_variable_get("##{dynamic_attr}") # Obviously fails, but you see what I'm getting at...
....
end
end
Of course this fails because defined? is a special form that is looking at literals and thus returns "method" in this case because it's looking at the actual instance_variable_get method. And of course instance_variable_get("#foo") is going to return nil if I ever called #foo = nil so it's indistinguishable from having never been set. Is there any way I can see if #foo was defined with the same semantics as defined? but in a dynamic way?
Strange that nobody mentioned that. There is also Object#instance_variable_defined?.
dynamic_attr = 'foo'
define_method :my_method do
if instance_variable_defined?("##{dynamic_attr}")
....
end
end
If I did get your question, you'd need to check whether an instance variable is defined. Object#instance_variable_get retrieves a value of an existing variable or nil if not exists, not the instance variable name.
You can check the definition of dynamically created variable name by its membership to all existing like:
dynamic_attr = 'foo'
define_method :my_method do
if instance_variables.member? "##{dynamic_attr}".to_sym
....
end
end
See array returned with Object#instance_variables contains symbols so you need to convert an argument with String#to_sym to compare apples with apples.

Equivalent of “pass” in Ruby

In python there is a pass keyword for defining an empty function, condition, loop, ...
Is there something similar for Ruby?
Python Example:
def some_function():
# do nothing
pass
No, there is no such thing in Ruby. If you want an empty block, method, module, class etc., just write an empty block:
def some_method
end
That's it.
In Python, every block is required to contain at least one statement, that's why you need a "fake" no-op statement. Ruby doesn't have statements, it only has expressions, and it is perfectly legal for a block to contain zero expressions.
nil is probably the equivalent of it:
def some_function
nil
end
It's basically helpful when ignoring exceptions using a simple one-line statement:
Process.kill('CONT', pid) rescue nil
Instead of using a block:
begin
Process.kill('CONT')
rescue
end
And dropping nil would cause syntax error:
> throw :x rescue
SyntaxError: (irb):19: syntax error, unexpected end-of-input
from /usr/bin/irb:11:in `<main>'
Notes:
def some_function; end; some_function returns nil.
def a; :b; begin; throw :x; rescue; end; end; a; also returns nil.
You always have end statements, so pass is not needed.
Ruby example:
def some_function()
# do nothing
end
Ruby 3.0
As of Ruby 3.0, so-called "endless" method definitions are now supported -- we no longer require end statements with every single method definition. This means the most concise way of expressing an empty method like the example above is now arguably something like this:
def some_function = nil
Alternatively, there has always been an uglier one-line option using the much-hated semicolon:
def some_function; end
Note that this doesn't really change anything about the first solution except how the code can be written.
Single line functions and classes
def name ; end
class Name ; end
works fine for pseudocode.
As answered before everything in ruby is an expression so it is fine to leave it blank.
def name
end
class Name
end
A ruby alternative for python programmers who love the pass keyword
def pass
end
# OR
def pass; end
Note that it is useless to do this in Ruby since it allows empty methods but if you're that keen on pass, this is the simplest and cleanest alternative.
and now you can use this function inside any block and it will work the same.
def name
pass
end
# OR
class Name
pass
end
Keep in mind that pass is a function that returns, so it is up to you how you can use it.
If you want to be able to use it freely with any number of arguments, you have to have a small trick on the arguments:
def gobble *args, &pr; end
As others have said, in Ruby you can just leave a method body empty. However, this could prove a bit different than what Python accomplishes with pass.
In Ruby, everything is an object. The absence of value, which some programming languages indicate with null or nil is actually an object of NilClass in Ruby.
Consider the following example (in irb):
class A
def no_op
end
end
A.new.no_op
# => nil
A.new.no_op.class
# => NilClass
A.new.no_op.nil?
# => true
Here's Ruby's NilClass documentation for reference.
I believe Python's pass is used mainly to overcome the syntactic limitations of the language (indentation), although I'm not that experienced in Python.
Ruby's equivalent to pass can be ().
if 1 == 1
()
else
puts "Hello"
end
=> nil
lambda do
()
end.call
=> nil
You can also use it as part of condition ? true-expr : false-expr ternary operator.

In ruby, how do I declare the C++ equivalent of "static" function variables?

I'm trying to keep a hash local to one function that remembers its state between calls to the function. But I don't know how to declare it without a closure (as some users suggested in a similar thread).
I know C++ more thoroughly than ruby, and in C++, I would have ordinarily used a static local variable, like in the first example here: http://msdn.microsoft.com/en-us/library/s1sb61xd.aspx
I managed to hack something together in ruby using the defined? function:
def func x
if not defined? #hash
#hash = Hash.new
end
if #hash[x]
puts 'spaghetti'
else
#hash[x] = true
puts x.to_s
end
end
func 1
func 1
This prints, the following, which is kind of what I want. The only problem is that #hash can be accessed outside of that function.
1
spaghetti
Is there any "cleaner", more preferred way to declare a variable with this behavior (without a factory)? I was going to create two or three variables like #hash, so I was looking for a better way to express this concisely.
What you're doing is pretty common in Ruby, but also so common you don't need to make a big fuss about it. All #-type instance variables are local to that instance only. Keep in mind "instance" generally refers to an instance of a class, but it can refer to the instance of the class as well.
You can use ## to refer to a class instance variable from the context of an instance, but this tends to get messy in practice.
What you want to do is one of the following.
A variable that persists between method calls, but only within the context of a single object instance:
def func(x)
# Instance variables are always "defined" in the sense that
# they evaluate as nil by default. You won't get an error
# for referencing one without declaring it first like you do
# with regular variables.
#hash ||= { }
if #hash[x]
puts 'spaghetti'
else
#hash[x] = true
puts x.to_s
end
end
A variable that persists between method calls, but only within the context of all object instances:
def func(x)
# Instance variables are always "defined" in the sense that
# they evaluate as nil by default. You won't get an error
# for referencing one without declaring it first like you do
# with regular variables.
##hash ||= { }
if ##hash[x]
puts 'spaghetti'
else
##hash[x] = true
puts x.to_s
end
end
This is usually made cleaner by wrapping the ##hash into a class method. This has the secondary effect of making testing easier:
def self.func_hash
#func_hash ||= { }
end
def func(x)
if self.class.func_hash[x]
puts 'spaghetti'
else
self.class.func_hash[x] = true
puts x.to_s
end
end

Does Ruby have a method_missing equivalent for undefined instance variables?

When I invoke a method that doesn't exist, method_missing will tell me the name of the method. When I attempt to access a variable that hasn't been set, the value is simply nil.
I'm attempting to dynamically intercept access to nil instance variables and return a value based on the name of the variable being accessed. The closest equivalent would be PHP's __get. Is there any equivalent functionality in Ruby?
I do not believe this is possible in Ruby. The recommended way would be to use a ''user'' method rather than a ''#user'' instance var in your templates.
This is consistent with the way you deal with Ruby objects externally (''obj.user'' is a method which refers to ''#user'', but is actually not ''#user'' itself). If you need any kind of special logic with an attribute, your best bet is to use a method (or method_missing), regardless if you're accessing it from inside or outside the object.
See my answer to another similar question. But just because you can do it doesn't mean that it's a good idea. Sensible design can generally overcome the need for this kind of thing and allow you to produce more readable and hence maintainable code.
instance_variable_get seems to be the closest equivalent of PHP's __get from what I can see (although I'm not a PHP user).
Looking at the relevant Ruby source code, the only 'missing' method for variables is const_missing for constants, nothing for instance variables.
there isn't an instance_variable_missing (at least that I know of)
But why are you accessing randomly named instance variables anyway?
If your thread all the access to the object state through method calls (as you should anyway) then you wouldn't need this.
If you are looking for a way to define magic stuff without messing up with the method lookup, you may want to use const_missing.
A bit late but, instance_variable_missing is the same as method_missing to a point... Take the following class:
class Test
def method_missing(*args)
puts args.inspect
end
end
t = Test.new
Now let's get some instance variables:
t.pineapples #=> [:pineapples]
t.pineapples = 5 #=> [:pineapples=,5]
Not sure why the method is nil for you...
EDIT:
By the sounds of it you want to accomplish:
t = SomeClass.new
t.property.child = 1
So let's try returning a Test object from our previous example:
class Test
def method_missing(*args)
puts args.inspect
return Test.new
end
end
So what happens when we call:
t = Test.new
t.property.child = 1
#=>[:property]
#=>[:child=,1]
So this goes to show that this is indeed possible to do. OpenStruct uses this same technique to set instance variables dynamically. In the below example, I create EternalStruct which does exactly what you wanted:
require 'ostruct'
class EternalStruct < OpenStruct
def method_missing(*args)
ret = super(*args)
if !ret
newES = EternalStruct.new
self.__send__((args[0].to_s + "=").to_sym, newES)
return newES
end
end
end
Usage of EternalStruct:
t = EternalStruct.new
t.foo.bar.baz = "Store me!"
t.foo.bar.baz #=> "Store me!"
t.foo #=> #<EternalStruct bar=#<EternalStruct baz="Store me!">>
t.a = 1
t.a #=> 1
t.b #=> #<EternalStruct:...>
t.b = {}
t.b #=> {}
def t.c(arg)
puts arg
end
t.c("hi there") #=> "hi there"

Resources