In many of the Rails methods, symbols are being passed as arguments. I'm not sure how some of those arguments are references to other methods. In other words, the symbol points to another method. I understand how a symbol like :something will always point to the same memory allocation, which is different from multiple instances of, say, "something". If I have a symbol :x and also defined a method x(), does it mean that these two are linked somehow?
A Ruby book describes the concept of a table of symbols:
A symbol is an identifier whose value is itself. This describes, in a broad sense, they way that symbols behave from the point of view of the Ruby programmer. But it doesn't tell you what symbols are literally from the point of view of the Ruby interpreter. A symbol is, in fact, a pointer into the symbol table. The symbol table is Ruby's internal list of known identifiers—such as variable and method names.
I stumbled upon how it refers to different methods or strings. Can someone help me understand this table of symbols and how it relates to symbols being used as method names?
Symbols by themselves are not connected with methods in any way. Certain methods can accept symbols to dynamically call other methods, using symbols as their names. Observe:
class Foo
def bar
"called bar"
end
def baz
"called bazzz"
end
def invoke m
send m
end
end
f = Foo.new
f.invoke :bar # => "called bar"
f.invoke :baz # => "called bazzz"
# since `invoke` just delegates execution to `send`, and `send` can accept strings as well
# we can pass a string here.
f.invoke 'baz' # => "called bazzz"
This is the same case as in
before_filter :init_session
validates_presence_of :first_name
And many others
Edit:
if I have a symbol :x and also defined a method x(), does it mean that these two are linked somehow?
No, they are not linked in any way. You can safely ignore that passage about symbol table. It's unnecessary implementation detail for you at the moment.
Symbol names and method names are not linked in any way. A symbol is most closely related to a string. The difference between a string and a symbol is that a symbol is a unique object for the entire Ruby interpreter whereas strings are always unique objects. To illustrate this, open up IRB:
irb
1.9.3-p362 :001 > "hello".object_id
=> 70162149682220
1.9.3-p362 :002 > "hello".object_id
=> 70162149699280
1.9.3-p362 :003 > :hello.object_id
=> 460328
1.9.3-p362 :004 > :hello.object_id
=> 460328
1.9.3-p362 :005 > "hello".to_sym.object_id
=> 460328
As you can see, two identical strings containing "hello" have different object ids, even though they contain the same contents. Symbols on the other hand, always have the same object id as long as the contents of the symbol are the same. You can see that converting the string "hello" to a symbol gives the same object id as the symbol :hello. Symbols are much more memory efficient to use, and equality comparison is much faster. The trade off is that a symbol is essentially a memory leak, because you can never remove one from memory once you define it.
As Sergio said, you can invoke methods using the send method, but send uses Ruby's robust reflection to execute methods by name at runtime, it has nothing inherently to do with symbols other than the method names are identified by a symbol.
EDIT: If you are curious about how this works, check out Ruby Metaprogramming to see the things you are able to do. To understand exactly how this works, however, you would need to look at the C source code of the Ruby language.
If you define symbol :x and also defined a method x() and print :x.class => Symbol , x.class => "Datatype of return field or if nothing is return then NilClass".
This Shows that there is no relation between symbol :x and method x().
Things done with Symbol can also be done with String in Ruby.
Symbols are used instead of string if u want one instance of string means you want one memory location for particular string ,obviously for performance benefit.
Internally Ruby saves Methods name as Symbol.
So its better to use Symbol when passing Methods names around like in case of attr_accessor and send but its not compulsory and you can use String otherwise.
Related
I'm trying to understand the extent of what symbols do in Ruby. I understand that it is much more faster and efficient to use symbols as keys as opposed to strings, but how is it faster?
And from my understanding, when referencing methods it has to be represented as a symbol, :to_i as opposed to to_i. What is the purpose of this?
In Ruby, a symbol is just an immutable string:
"hello " + "world" #=> "hello world"
:hello_ + :world #=> NoMethodError: undefined method `+' for :hello:Symbol
Being immutable makes symbols a safe and reliable reference, for example:
Object.methods => [:new, :allocate, :superclass, #etc..]
If Ruby were to use strings here, users would be able to modify the strings, thus ruining future calls of Object.methods. This could be fixed by making copies of the strings each time the method is called, but that would be a huge memory footprint.
In fact, since Ruby knows symbols are never going to be modified, it saves each symbol only once, no matter how many times you declare it:
"hello".object_id #=> 9504940
"hello".object_id #=> 9565300
:hello.object_id #=> 1167708
:hello.object_id #=> 1167708
This takes the memory-saving potential of symbols even further, allowing you to use symbol literals in your code anywhere and everywhere with little memory overhead.
So, the round-about answer to your question: symbols can't be modified, but they're safer and more memory efficient; therefore, you should use them whenever you have a string that you know shouldn't be modified.
Symbols are used as the keys to hashes because:
You should never modify the key of a hash while it's in the hash.
Hashes require literal referencing a lot, ie my_hash[:test], so it's more memory-efficient to use symbols.
As for method references: you can't reference a method directly, ie send(my_method()) because can't tell the difference between passing the method in and executing it. Strings could have been used here, but since a method's name never changes once defined, it makes more sense to represent the name as a symbol.
What is the function of symbol in ruby? what's difference between string and symbol?
Why is it not a good idea to dynamically create a lot of symbols?
Symbols are like strings but they are immutable - they can't be modified.
They are only put into memory once, making them very efficient to use for things like keys in hashes but they stay in memory until the program exits. This makes them a memory hog if you misuse them.
If you dynamically create lots of symbols, you are allocating a lot of memory that can't be freed until your program ends (edit: this is no longer the case since Ruby 2.2). You should only dynamically create symbols (using string.to_sym) if you know you will:
need to repeatedly access the symbol
not need to modify them
As I said earlier, they are useful for things like hashes - where you care more about the identity of the variable than its value. Symbols, when correctly used, are a readable and efficient way to pass around identity.
I will explain what I mean about the immutability of symbols RE your comment.
Strings are like arrays; they can be modified in place:
12:17:44 ~$ irb
irb(main):001:0> string = "Hello World!"
=> "Hello World!"
irb(main):002:0> string[5] = 'z'
=> "z"
irb(main):003:0> string
=> "HellozWorld!"
irb(main):004:0>
Symbols are more like numbers; they can't be edited in place:
irb(main):011:0> symbol = :Hello_World
=> :Hello_World
irb(main):012:0> symbol[5] = 'z'
NoMethodError: undefined method `[]=' for :Hello_World:Symbol
from (irb):12
from :0
A symbol is the same object and the same allocation of memory no matter where it is used:
>> :hello.object_id
=> 331068
>> a = :hello
=> :hello
>> a.object_id
=> 331068
>> b = :hello
=> :hello
>> b.object_id
=> 331068
>> a = "hello"
=> "hello"
>> a.object_id
=> 2149256980
>> b = "hello"
=> "hello"
>> b.object_id
=> 2149235120
>> b = "hell" + "o"
Two strings which are 'the same' in that they contain the same characters may not reference the same memory, which can be inefficient if you're using strings for, say, hashes.
So, symbols can be useful for reducing memory overhead. However - they are a memory leak waiting to happen, because symbols cannot be garbage collected once created. Creating thousands and thousands of symbols would allocate the memory and not be recoverable. Yikes!
It can be particularly bad to create symbols from user input without validating the input against some kind of a white-list (for example, for query string parameters in RoR). If user input is converted to symbols without validation, a malicious user can cause your program to consume large amounts of memory that will never be garbage collected.
Bad (a symbol is created regardless of user input):
name = params[:name].to_sym
Good (a symbol is only created if the user input is allowed):
whitelist = ['allowed_value', 'another_allowed_value']
raise ArgumentError unless whitelist.include?(params[:name])
name = params[:name].to_sym
Starting Ruby 2.2 and above Symbols are automatically garbage collected and so this should not be an issue.
If you are using Ruby 2.2.0 or later, it should usually be OK to dynamically create a lot of symbols, because they will be garbage collected according to the Ruby 2.2.0-preview1 announcement, which has a link to more details about the new symbol GC. However, if you pass your dynamic symbols to some kind of code that converts it to an ID (an internal Ruby implementation concept used in the C source code), then in that case it will get pinned and never get garbage collected. I'm not sure how commonly that happens.
You can think of symbols as a name of something, and strings (roughly) as a sequence of characters. In many cases you could use either a symbol or a string, or you could use a mixture of the two. Symbols are immutable, which means they can't be changed after being created. The way symbols are implemented, it is very efficient to compare two symbols to see if they are equal, so using them as keys to hashes should be a little faster than using strings. Symbols don't have a lot the methods that strings do, such as start_with? so you would have to use to_s to convert the symbol into a string before calling those methods.
You can read more about symbols here in the documentation:
http://www.ruby-doc.org/core-2.1.3/Symbol.html
I have just started using Ruby and I am reading "Programming Ruby 1.9 - The Pragmatic Programmer's Guide". I came across something called symbols, but as a PHP developer I don't understand what they do and what they are good for.
Can anyone help me out with this?
It's useful to think of symbols in terms of "the thing called." In other words, :banana is referring to "the thing called banana." They're used extensively in Ruby, mostly as Hash (associative array) keys.
They really are similar to strings, but behind the scenes, very different. One key difference is that only one of a particular symbol exists in memory. So if you refer to :banana 10 times in your code, only one instance of :banana is created and they all refer to that one. This also implies they're immutable.
Symbols are similar to string literals in the sense that share the same memory space, but it is important to remark they are not string equivalents.
In Ruby, when you type "this" and "this" you're using two different memory locations; by using symbols you'll use only one name during the program execution. So if you type :this in several places in your program, you'll be using only one.
From Symbol doc:
Symbol objects represent names and some strings inside the Ruby interpreter. They are generated using the :name and :"string" literals syntax, and by the various to_sym methods. The same Symbol object will be created for a given name or string for the duration of a program‘s execution, regardless of the context or meaning of that name. Thus if Fred is a constant in one context, a method in another, and a class in a third, the Symbol :Fred will be the same object in all three contexts.
So, you basically use it where you want to treat a string as a constant.
For instance, it is very common to use it with the attr_accessor method, to define getter/setter for an attribute.
class Person
attr_accessor :name
end
p = Person.new
p.name= "Oscar"
But this would do the same:
class DontDoThis
attr_accessor( "name" )
end
ddt = DontDoThis.new
ddt.name= "Dont do it"
Think of a Symbol as a either:
A method name that you plan to use later
A constant / enumeration that you want to store and compare against
For example:
s = "FooBar"
length = s.send(:length)
>>> 6
#AboutRuby has a good answer, using the terms "the thing called".
:banana is referring to "the thing
called banana."
He notes that you can refer to :banana many times in the code and its the same object-- even in different scopes or off in some weird library. :banana is the thing called banana, whatever that might mean when you use it.
They are used as
keys to arrays, so you look up :banana you only have one entry. In most languages if these are Strings you run the risk of having multiple Strings in memory with the text "banana" and not having the code detect they are the same
method/proc names. Most people are familiar with how C distinguishes a method from its call with parentheses: my_method vs. my_method(). In Ruby, since parentheses are optional, these both indicate a call to that method. The symbol, however, is convenient to use as a standin for methods (even though there really is no relationship between a symbol and a method).
enums (and other constants). Since they don't change they exhibit many of the properties of these features from other languages.
I'm new to the Ruby and Ruby on Rails world. I've read some guides, but i've some trouble with the following syntax.
I think that the usage of :condition syntax is used in Ruby to define a class attribute with some kind of accessor, like:
class Sample
attr_accessor :condition
end
that implicitly declares the getter and setter for the "condition" property.
While i was looking at some Rails sample code, i found the following examples that i don't fully understand.
For example:
#post = Post.find(params[:id])
Why it's accessing the id attribute with this syntax, instead of:
#post = Post.find(params[id])
Or, for example:
#posts = Post.find(:all)
Is :all a constant here? If not, what does this code really means? If yes, why the following is not used:
#posts = Post.find(ALL)
Thanks
A colon before text indicates a symbol in Ruby. A symbol is kind of like a constant, but it's almost as though a symbol receives a unique value (that you don't care about) as its constant value.
When used as a hash index, symbols are almost (but not exactly) the same as using strings.
Also, you can read "all" from :all by calling to_s on the symbol. If you had a constant variable ALL, there would be no way to determine that it meant "all" other than looking up its value. This is also why you can use symbols as arguments to meta-methods like attr_accessor, attr_reader, and the like.
You might want to read up on Ruby symbols.
:all is a symbol. Symbols are Ruby's version of interned strings. You can think of it like this: There is an invisible global table called symbols which has String keys and Fixnum values. Any string can be converted into a symbol by calling .to_sym, which looks for the string in the table. If the string is already in the table, it returns the the Fixnum, otherwise, it enters it into the table and returns the next Fixnum. Because of this, symbols are treated at run-time like Fixnums: comparison time is constant (in C parlance, comparisons of symbols can be done with == instead of strcmp)
You can verify this by looking at the object_id of objects; when two thing's object_ids are the same, they're both pointing at the same object.
You can see that you can convert two strings to symbols, and they'll both have the same object id:
"all".to_sym.object_id == "all".to_sym.object_id #=> true
"all".to_sym.object_id == :all.object_id #=> true
But the converse is not true: (each call to Symbol#to_s will produce a brand new string)
:all.to_s.object_id == :all.to_s.object_id #=> false
Don't look at symbols as a way of saving memory. Look at them as indicating that the string ought to be immutable. 13 Ways of Looking at a Ruby Symbol gives a variety of ways of looking at a symbol.
To use a metaphor: symbols are for multiple-choice tests, strings are for essay questions.
This has nothing to do with Rails, it's just Ruby's Symbols. :all is a symbol which is effectively just a basic string.
What does Ruby constants really mean? The following code doesn't show any 'constant' attribute. The warning is there, but I still get to change what A refers to.
A = 1
puts A # => 1
A = 2 # warning: already initialized constant A
puts A # => 2
Or is Ruby constants are just an indication without any enforcement?
That's right, constants are just like variables in ruby, but you get a warning if you change them.
Also, there's one difference with mere variables: You can access constants even if they are defined inside another class or module, for example given this snippet:
module Constants
PI = 3,1415
other = "variable"
end
You can reach PI doing Constants::PI while Constants::other will not work.
Yes, Ruby constants aren't enforced, other than printing that warning.
That's right -- assigning to a constant is a warning, not an error; "constants" are just an indicator of how you should use something, not a rule that you do use it that way.
That may sound horrendous coming from a static-programming world, but it's immensely useful in various metaprogramming facilities, and it enables things that would otherwise be completely impossible in static languages.
That said, if you really want to make sure people keep their grubby hands off your references, you can use Object#freeze. It's still okay to change what a reference points to with this; you just can't change the contents of the reference itself:
irb(main):001:0> class Fruit; attr_accessor :name; end
=> nil
irb(main):002:0> f = Fruit.new
=> #<Fruit:0xb7e06570>
irb(main):003:0> f.name = "apple"
=> "apple"
irb(main):004:0> f.freeze # After freeze, can't touch this Fruit.
=> #<Fruit:0xb7e06570 #name="apple">
irb(main):005:0> f.name = "banana"
TypeError: can't modify frozen object # Kablammo!
from (irb):5:in `name='
from (irb):5
But this is okay:
irb(main):006:0> f = Fruit.new
=> #<Fruit:0xb7dfed84>
irb(main):007:0> f.name = "banana"
=> "banana"
"Constant" is really a misnomer, the most important aspect of Ruby's "Constants" is not their immutability but their lookup rules.
see: http://coderrr.wordpress.com/2008/03/11/constant-name-resolution-in-ruby/
Constants are used to store values that should not be changed. Their names must start with an uppercase letter. By convention, most constant names are written in all uppercase letters with an underscore as word separator, such as SOME_CONSTANT.
Constants defined within classes can be accessed by all methods of that class. Those created outside a class can be accessed globally (within any method or class).
class Car
WHEELS = 4
def initialize
puts WHEELS
end
end
c = Car.new # Output: 4
Note that Ruby does not stop us from changing the value of a constant, it only issues a warning.
SOME_CONSTANT = "foo"
SOME_CONSTANT = "bar"
warning: already initialized constant SOME_CONSTANT
warning: previous definition of SOME_CONSTANT was here
In Ruby, all class and module names are constants, but convention dictates they should be written in camel case, such as SomeClass.
Constants can be accessed from outside the class, even within another class, by using the :: (double colon) operator. To access the WHEELS constant from outside the Car class, we would use Car::WHEELS. The :: operator allows constants, public instance methods and class methods to be accessed from outside the class or module on which they are defined.
A built-in method called private_constant makes constants private (accessible only within the class on which they were created). The syntax is as follows:
class Car
WHEELS = 4
private_constant:WHEELS
end
Car::WHEELS # Output: NameError: private constant Car::WHEELS referenced
If you're coming from other programming languages, Ruby handles constants differently than what you may be used to. Constants, in general, take values that do not change through the entire application. The syntax is to use all capital letters while naming your constant so that the application knows how to handle it. For example, to set a constant to hold a baseball team you would declare it this way:
TEAM = "Angels"
I know you know this much, bear with me here. Typically, other programming languages will not allow you to change the value of TEAM. However, Ruby does not hold you back and takes the last value assigned to the constant. In the above example, I can change its value to:
TEAM = "Athletics"
Other programming languages would either throw an error or would print the value of Angels. However, Ruby prints the value Athletics because that is the last value assigned to the variable TEAM. Also, it gives a warning message that says that the constant was already initialized and was changed because changing a constant is considered a poor programming practice. But, it still allows you to make the change and follows the Ruby convention of trusting the developer to make the right programming decision. So, be careful while using constants in Ruby since they can be overridden.