How does Ruby use symbols to reference variable names? - ruby

When we are defining getter and setter methods for name in the following code:
class Animal
attr_accessor :name
def initialize(name)
#name = name
end
end
what is happening internally? How is Ruby able to take a symbol and match it with a variable?

It uses instance_variable_get and instance_variable_set for that.
Update: as Andrew Marshall noted, not exactly. Most ruby core methods are defined in C, but the result is essentially the same.
One could define attr_accessor and friends as follows:
def self.attr_accessor(*names)
names.each do |name|
define_method(name) do
instance_variable_get("##{name}")
end
define_method("#{name}=") do |new_value|
instance_variable_set("##{name}", new_value)
end
end
end
Note that I've also used define_method here to define the accessor methods.
I recommend that you take a look at some introductory texts about ruby metaprogramming, such as "Don’t Know Metaprogramming In Ruby?".

It doesn't match it with a variable, attr_accessor does essentially this (it's actually written in C, but I've written it's roughly Ruby translation here):
def attr_accessor(var_name)
ivar_name = :"##{var_name}"
define_method(var_name) do
instance_variable_get ivar_name
end
define_method("#{var_name}=") do |value|
instance_variable_set ivar_name, value
end
end
As you can see, it simply uses the symbol passed to create two methods. It doesn't do anything fancy with the symbol, and is mostly just passing it through. Note, also, that all instance variables "exist" by default and are set to nil, so this will never blow up.

Related

Redefining "class" keyword in Ruby

To define a class I must do the following (for example)
class Foo
#attr_accessors
#methods
#so on
end
foo = Foo.new #to create an instance
Problem
I need to achieve the following
case_class Foo_inmutable #I change class for case_class
#attr_accessors
#methods
#so on
end
foo_inmutable = Foo_inmutable.new
#->SyntaxError: uninitialze constant Foo_inmutable
I need the ruby interpreter to treat the case_class the same way to keyword class
Like almost all programming languages, Ruby does not allow you to modify its syntax or semantics. So, what you want is not possible.
You can, however, quite easily write a method that accomplishes your goal, but without changing the syntax and semantics of Ruby:
class Module
def case_class(name, superclass = ::Object, &blk)
const_set(name, Class.new(superclass, &blk))
end
end
def case_class(name, superclass = ::Object, &blk)
self.class.case_class(name, superclass, &blk)
end
case_class :Foo_immutable do
# ↑ ↑↑
# these are the only differences to your proposed syntax
#attr_accessors
#methods
#so on
end
foo_immutable = Foo_immutable.new
To achieve this, besides defining what's already been said in the previous answer:
class Module
def case_class(name, superclass = ::Object, &blk)
const_set(name, Class.new(superclass, &blk))
end
end
def case_class(name, superclass = ::Object, &blk)
self.class.case_class(name, superclass, &blk)
end
You may want to have a look at the const_missing method, and the "Lookup" that ruby does for constants inside the various scopes
That will allow you to do stuff like
case_class Foo do
...
end
For further explanation you can refer to this page: tadp-utn-frba.github.io
It has tons of useful scripts explaining ruby metaprogramming (in spanish) and how to achieve what you are looking for, also it has contact references for the
people in charge of the page, so you can email them at any time (Given you are a student of the class) for academic reasons.
Cheers!

What is the difference between the following two? [duplicate]

In Ruby there are four different getter and setter methods for instance variables, attr, attr_reader, attr_writer, and attr_accessor. The question is, is in Ruby attr :dilithium, the same as attr_reader :dilithium, and identical to attr_accessor :dilithium if an additional parameter true is passed? That is to say is
class Enterprise
attr :dilithium, true
identical to
class Enterprise
attr_accessor :dilithium
Are the two functions attr and attr_accessor more or less redundant?
One difference is that attr_accessor and friends are clearer, and the optional boolean argument to attr is now deprecated. Other than that, and the fact that attr has no documentation, there's no real difference.
In Ruby 1.8, attr can define only a single attribute, with an optional true to create a setter . In 1.9 it behaves like attr_reader:it allows for multiple attributes. As #Linuxios says, the optional boolean is deprecated.
If you look at the C code in Ruby 2.3.0, you will see that attr and attr_reader are actually doing the same thing (except for the deprecated code path). They are essentially equivalent functions.
For me, the main differences are:
attr is a bit easier to write down as it's shorter. I like the way it feels in the context of functional/immutable programming too (in those contexts, attr_writer and attr_accessor are irrelevant and thus using attr_reader feels verbose and redundant).
attr with multiple instance variables makes it hard to document, except in very specific situations, e.g.
# The coordinates in WGS84.
attr :x, :y
# The location name.
attr :name
# The popularity of the location.
attr :popularity
It would be harder to document :name and :popularity independently if they were on the same line attr :name, :popularity.
Apart from that it boils down to personal preference. There is in practice no performance difference or any other difference.
attr and attr_accessor are methods in Ruby that are used to define instance variables in classes.
attr creates a simple getter method that returns the value of an instance variable with the same name as the symbol passed as an argument. For example:
class MyClass
attr :my_variable
def initialize
#my_variable = "Hello World"
end
end
my_object = MyClass.new
puts my_object.my_variable # outputs "Hello World"
attr_accessor creates both getter and setter methods for an instance variable with the same name as the symbol passed as an argument. For example:
class MyClass
attr_accessor :my_variable
def initialize
#my_variable = "Hello World"
end
end
my_object = MyClass.new
puts my_object.my_variable # outputs "Hello World"
my_object.my_variable = "Goodbye World"
puts my_object.my_variable # outputs "Goodbye World"
In the example above, my_object.my_variable can be read and written. The attr_accessor method creates both getter and setter methods, allowing the value of the instance variable to be read and written.

How does attr_accessor know that :player = #player?

Here's the code:
class Dungeon
attr_accessor :player
def initialize(player_name)
#player = Player.new(player_name)
end
end
Now, if I write:
dungeon = Dungeon.new("Robert")
puts dungeon.player.name
it's obviously going to spit out Robert.
I'm a little new to Ruby, so forgive me if this question is obvious to you all. I'm struggling to wrap my head around it still. I am learning about "instance", "class", and global variables and my question is: How does Ruby know that :player in the code above refers to #player? Why isn't the code written, instead, :#player?
Does that make any sense?
attr_accessor is just a method that defines a public getter/setter. #player is the actual instance variable that stores values. The getter it generates is based on the symbol name, so :player creates these methods:
def player
#player
end
def player=(player)
#player = player
end
If you only want the getter you can use attr_reader. If you only want the setter you can use attr_writer. attr_accessor combines these two methods and gives you both methods.
One thing that is easy to overlook when first learning Ruby is that the construct
attr_accessor :property_name
is just a shorter way of writing getter and setter methods for a class's instance variables:
# getter
def property_name
#property_name
end
# setter
def property_name=( some_value )
#property_name = some_value
end
It's basically an example of the "metaprogramming" support in Ruby, but it feels like something more mysterious.
Also, you do not have to use the symbol style, you could instead have:
attr_accessor "property_name"
The symbol version just "reads better" for most people.

What does attr mean in Ruby? [duplicate]

In Ruby there are four different getter and setter methods for instance variables, attr, attr_reader, attr_writer, and attr_accessor. The question is, is in Ruby attr :dilithium, the same as attr_reader :dilithium, and identical to attr_accessor :dilithium if an additional parameter true is passed? That is to say is
class Enterprise
attr :dilithium, true
identical to
class Enterprise
attr_accessor :dilithium
Are the two functions attr and attr_accessor more or less redundant?
One difference is that attr_accessor and friends are clearer, and the optional boolean argument to attr is now deprecated. Other than that, and the fact that attr has no documentation, there's no real difference.
In Ruby 1.8, attr can define only a single attribute, with an optional true to create a setter . In 1.9 it behaves like attr_reader:it allows for multiple attributes. As #Linuxios says, the optional boolean is deprecated.
If you look at the C code in Ruby 2.3.0, you will see that attr and attr_reader are actually doing the same thing (except for the deprecated code path). They are essentially equivalent functions.
For me, the main differences are:
attr is a bit easier to write down as it's shorter. I like the way it feels in the context of functional/immutable programming too (in those contexts, attr_writer and attr_accessor are irrelevant and thus using attr_reader feels verbose and redundant).
attr with multiple instance variables makes it hard to document, except in very specific situations, e.g.
# The coordinates in WGS84.
attr :x, :y
# The location name.
attr :name
# The popularity of the location.
attr :popularity
It would be harder to document :name and :popularity independently if they were on the same line attr :name, :popularity.
Apart from that it boils down to personal preference. There is in practice no performance difference or any other difference.
attr and attr_accessor are methods in Ruby that are used to define instance variables in classes.
attr creates a simple getter method that returns the value of an instance variable with the same name as the symbol passed as an argument. For example:
class MyClass
attr :my_variable
def initialize
#my_variable = "Hello World"
end
end
my_object = MyClass.new
puts my_object.my_variable # outputs "Hello World"
attr_accessor creates both getter and setter methods for an instance variable with the same name as the symbol passed as an argument. For example:
class MyClass
attr_accessor :my_variable
def initialize
#my_variable = "Hello World"
end
end
my_object = MyClass.new
puts my_object.my_variable # outputs "Hello World"
my_object.my_variable = "Goodbye World"
puts my_object.my_variable # outputs "Goodbye World"
In the example above, my_object.my_variable can be read and written. The attr_accessor method creates both getter and setter methods, allowing the value of the instance variable to be read and written.

attr vs attr_accessor

In Ruby there are four different getter and setter methods for instance variables, attr, attr_reader, attr_writer, and attr_accessor. The question is, is in Ruby attr :dilithium, the same as attr_reader :dilithium, and identical to attr_accessor :dilithium if an additional parameter true is passed? That is to say is
class Enterprise
attr :dilithium, true
identical to
class Enterprise
attr_accessor :dilithium
Are the two functions attr and attr_accessor more or less redundant?
One difference is that attr_accessor and friends are clearer, and the optional boolean argument to attr is now deprecated. Other than that, and the fact that attr has no documentation, there's no real difference.
In Ruby 1.8, attr can define only a single attribute, with an optional true to create a setter . In 1.9 it behaves like attr_reader:it allows for multiple attributes. As #Linuxios says, the optional boolean is deprecated.
If you look at the C code in Ruby 2.3.0, you will see that attr and attr_reader are actually doing the same thing (except for the deprecated code path). They are essentially equivalent functions.
For me, the main differences are:
attr is a bit easier to write down as it's shorter. I like the way it feels in the context of functional/immutable programming too (in those contexts, attr_writer and attr_accessor are irrelevant and thus using attr_reader feels verbose and redundant).
attr with multiple instance variables makes it hard to document, except in very specific situations, e.g.
# The coordinates in WGS84.
attr :x, :y
# The location name.
attr :name
# The popularity of the location.
attr :popularity
It would be harder to document :name and :popularity independently if they were on the same line attr :name, :popularity.
Apart from that it boils down to personal preference. There is in practice no performance difference or any other difference.
attr and attr_accessor are methods in Ruby that are used to define instance variables in classes.
attr creates a simple getter method that returns the value of an instance variable with the same name as the symbol passed as an argument. For example:
class MyClass
attr :my_variable
def initialize
#my_variable = "Hello World"
end
end
my_object = MyClass.new
puts my_object.my_variable # outputs "Hello World"
attr_accessor creates both getter and setter methods for an instance variable with the same name as the symbol passed as an argument. For example:
class MyClass
attr_accessor :my_variable
def initialize
#my_variable = "Hello World"
end
end
my_object = MyClass.new
puts my_object.my_variable # outputs "Hello World"
my_object.my_variable = "Goodbye World"
puts my_object.my_variable # outputs "Goodbye World"
In the example above, my_object.my_variable can be read and written. The attr_accessor method creates both getter and setter methods, allowing the value of the instance variable to be read and written.

Resources