If you have a problem or need to report a bug please email : support@dsprobotics.com
There are 3 sections to this support area:
DOWNLOADS: access to product manuals, support files and drivers
HELP & INFORMATION: tutorials and example files for learning or finding pre-made modules for your projects
USER FORUMS: meet with other users and exchange ideas, you can also get help and assistance here
NEW REGISTRATIONS - please contact us if you wish to register on the forum
Users are reminded of the forum rules they sign up to which prohibits any activity that violates any laws including posting material covered by copyright
[Tutorial] Ruby: Symbols
7 posts
• Page 1 of 1
[Tutorial] Ruby: Symbols
The question came up. What is a symbol? To answer it, we will first have a look at a totally different topic. Logos! Have a look at this one:
If you thought of a Cheeseburger, that's fine.
If you thought of a McFlurry, that's fine.
If you thought of hot coffee, that's fine.
If you thought of a big company acting worldwide, that's fine.
It's fine, because the logo stands for all of it. It is not just a picture for a specific thing, it's the entirety of the McDonald's cosmos. A famous graphic designer described it like so: "A logo is a flag, a signature, an escutcheon, a street sign. A logo does not sell (directly), it identifies."
And indeed, a logo is the biggest part of "corporate identity". And if you understand, that one logo stands for several different things, as it identifies a whole company, you are already prepared to understand Ruby's symbols.
A symbol is a unique identifier. It is not a variable, it is not a string, although it reminds on a string. Everytime you write in your RubyEdit the following, it creates a new object.
To prevent that, we can make use of variables.
But we can easily change the object, @greet is pointing to.
And we can change mutable objects, too. In programming, mutable means that the object itself can change, immutable means it can't be changed ever.
There's something missing here and that's a thing that is kind of immutable and can't point to different objects. And that's the birth of symbols. A symbol is written with a preceding double-colon, to differentiate from variables, contants, classes, etc.
The symbol we created is now added to a table of all symbols used by Ruby. All of them are unique, :greet is only in there one time, no matter how often and under what circumstances we use it! You can check this table, by using the Symbol class's method.
If you do that, you will notice that there are no rules as to how you name it, other than a preceding double-colon. In fact, you will find symbols like
:Class
:"core#set_method_alias"
:[]=
and even the name of the class Symbol, :Symbol
Now you might think, that symbols still are much like strings. Maybe not in how they are handled by Ruby, but in their behavior. And yes, that's not wrong. A symbol is an identifier, and as such needs a descriptive name, which is almost as if it were a string. And you can indeed convert a symbol to a string, and a string to a symbol.
I want to point out, that you should never use #to_sym, unless you know exactly what you are doing! Since symbols stay in memory, you can create a memory leak, when, for example, automatically creating symbols from a user inputted string over and over again (every different string will become an additional symbol, sitting in memory until the app/plugin is closed)!
But of course there are advantages. For once, there's only ever one symbol of the same label, which means a small lookup table where it can be found much quicker. Then they are immutable and therefore instantiating them is faster than instantiating strings. Execution time can be reduced as much as to a third of the strings' time.
The best use case for explaining symbols is Hashes, as they use key - value pairs. In other languages (they don't have symbols), you have to use strings as keys.
But we can use symbols and save time. Even better, symbols are so useful in hashes that there is a specific way of writing a key-value pair!
Compare the two ways of using a string or a symbol as key, and you see the clear advantage of identifiers over strings even just for the state of programming, aside from all optimizations! In the first example, you can't tell, which one is data, because both are strings. In the other examples it is obvious what is data and what is key. And even more, you can have nested Hashes, and use the same symbols, without any compromise. The same symbol in another Hash represents another type of data, just like a logo stands for fries or cheeseburger (or both), depending on your appetite.
In short, keep the strings for users of your app/plugin. Keep the symbols in your code, use them whenever you need an identifier and save time over strings.
If you thought of a Cheeseburger, that's fine.
If you thought of a McFlurry, that's fine.
If you thought of hot coffee, that's fine.
If you thought of a big company acting worldwide, that's fine.
It's fine, because the logo stands for all of it. It is not just a picture for a specific thing, it's the entirety of the McDonald's cosmos. A famous graphic designer described it like so: "A logo is a flag, a signature, an escutcheon, a street sign. A logo does not sell (directly), it identifies."
And indeed, a logo is the biggest part of "corporate identity". And if you understand, that one logo stands for several different things, as it identifies a whole company, you are already prepared to understand Ruby's symbols.
A symbol is a unique identifier. It is not a variable, it is not a string, although it reminds on a string. Everytime you write in your RubyEdit the following, it creates a new object.
- Code: Select all
"Hallo" #first object
"Hallo" #second object
"Hallo" #third object, etc
To prevent that, we can make use of variables.
- Code: Select all
@greet = "Hallo" #"hallo" is created, let's ID it as object_1
@greet #points to object_1
@greet #points to object_1
@greet #points to object_1, etc
But we can easily change the object, @greet is pointing to.
- Code: Select all
@greet = "moin" #"moin" is created, let's ID it as object_2
@greet #points to object_2
@greet #points to object_2
@greet #points to object_2, etc
And we can change mutable objects, too. In programming, mutable means that the object itself can change, immutable means it can't be changed ever.
- Code: Select all
@var_a = "moin" #object moin is created and var_a associated with it
@var_b = @var_a #a second variable is associated with object moin
@var_b.upcase! #an exclamation mark tells you the method is changing the object itself
#both, @var_a and @var_b now point to object moin, which reads "MOIN" instead of "moin"
There's something missing here and that's a thing that is kind of immutable and can't point to different objects. And that's the birth of symbols. A symbol is written with a preceding double-colon, to differentiate from variables, contants, classes, etc.
- Code: Select all
:greet #a symbol is created
:greet = "moin" #syntax error, a symbol is immutable, it is not a variable
The symbol we created is now added to a table of all symbols used by Ruby. All of them are unique, :greet is only in there one time, no matter how often and under what circumstances we use it! You can check this table, by using the Symbol class's method.
- Code: Select all
Symbol.all_symbols
If you do that, you will notice that there are no rules as to how you name it, other than a preceding double-colon. In fact, you will find symbols like
:Class
:"core#set_method_alias"
:[]=
and even the name of the class Symbol, :Symbol
Now you might think, that symbols still are much like strings. Maybe not in how they are handled by Ruby, but in their behavior. And yes, that's not wrong. A symbol is an identifier, and as such needs a descriptive name, which is almost as if it were a string. And you can indeed convert a symbol to a string, and a string to a symbol.
- Code: Select all
@moin = :greet.to_s #symbol was converted and is now the string object "greet"
@sym = @moin.to_sym #string converted to symbol object :greet
I want to point out, that you should never use #to_sym, unless you know exactly what you are doing! Since symbols stay in memory, you can create a memory leak, when, for example, automatically creating symbols from a user inputted string over and over again (every different string will become an additional symbol, sitting in memory until the app/plugin is closed)!
But of course there are advantages. For once, there's only ever one symbol of the same label, which means a small lookup table where it can be found much quicker. Then they are immutable and therefore instantiating them is faster than instantiating strings. Execution time can be reduced as much as to a third of the strings' time.
The best use case for explaining symbols is Hashes, as they use key - value pairs. In other languages (they don't have symbols), you have to use strings as keys.
- Code: Select all
names = {"forename" => "Jessica"}
But we can use symbols and save time. Even better, symbols are so useful in hashes that there is a specific way of writing a key-value pair!
- Code: Select all
names = { :forename => "Jessica" } #standard way of creating key-value pair
names = { forename: "Jessica" } #symbol specific way of creating key-value pair
Compare the two ways of using a string or a symbol as key, and you see the clear advantage of identifiers over strings even just for the state of programming, aside from all optimizations! In the first example, you can't tell, which one is data, because both are strings. In the other examples it is obvious what is data and what is key. And even more, you can have nested Hashes, and use the same symbols, without any compromise. The same symbol in another Hash represents another type of data, just like a logo stands for fries or cheeseburger (or both), depending on your appetite.
In short, keep the strings for users of your app/plugin. Keep the symbols in your code, use them whenever you need an identifier and save time over strings.
"There lies the dog buried" (German saying translated literally)
- tulamide
- Posts: 2714
- Joined: Sat Jun 21, 2014 2:48 pm
- Location: Germany
Re: [Tutorial] Ruby: Symbols
Excellent tulamide!
Thank you for taking the time to explain this so well.
Thank you for taking the time to explain this so well.
-
Spogg - Posts: 3358
- Joined: Thu Nov 20, 2014 4:24 pm
- Location: Birmingham, England
Re: [Tutorial] Ruby: Symbols
This will take several readthroughs to absorb.
One confusing thing was the mention of 'double colons'. But I didn't see them [or missed it].
I was then looking for [::] that would be 2 colons.
Again, I'll need to re-read.
Always appreciate your sharing of knowledge Tulamide !
Thank-you
One confusing thing was the mention of 'double colons'. But I didn't see them [or missed it].
I was then looking for [::] that would be 2 colons.
Again, I'll need to re-read.
Always appreciate your sharing of knowledge Tulamide !
Thank-you
- RJHollins
- Posts: 1571
- Joined: Thu Mar 08, 2012 7:58 pm
Re: [Tutorial] Ruby: Symbols
Yes thanks indeed for putting this together, much appreciated. I feel compelled to find me an application ...
However, if at any point I thought of a MacCheeseburger .. that's NOT so fine
H
However, if at any point I thought of a MacCheeseburger .. that's NOT so fine
H
-
HughBanton - Posts: 265
- Joined: Sat Apr 12, 2008 3:10 pm
- Location: Evesham, Worcestershire
Re: [Tutorial] Ruby: Symbols
Q U A R T E R P O U N D E R
... with cheese
NO KETCHUP !
... with cheese
NO KETCHUP !
- RJHollins
- Posts: 1571
- Joined: Thu Mar 08, 2012 7:58 pm
Re: [Tutorial] Ruby: Symbols
HughBanton wrote:Yes thanks indeed for putting this together, much appreciated. I feel compelled to find me an application ...
There are quite a few. For example, when defining a class, you normally go through the painfully boring routine of creating getter and setter methods.
- Code: Select all
class Test
def intialize
@forename = ""
end
##getter
def forename
return @forename
end
##setter
def forename=(obj)
@forename = obj
end
end
names = Test.new
names.forename = "Rex"
names.forename
But Ruby allows us to take a shortcut. Use the method attr_accessor ("attribute accessor") and pass a symbol. Ruby then creates the variable and the two methods, whose names are based on the symbol!
- Code: Select all
class Test
attr_accessor :forename
end
names = Test.new
names.forename = "Rex"
names.forename
Here is a more sophisticated example.
- Code: Select all
def addsub(*args)
return args[0] + args[1][:add] - args[1][:subtract]
end
addsub(4, add: 3, subtract: 2)
Flowstone also makes use of symbols. Whenever you name an input of a RubyEdit, it creates a symbol from that name and uses it to give you access to the input and its data.
EDIT: My bad! In German this sign ":" is called a "Doppelpunkt" (double dot). I mixed German and English here and talked about "double-colon", where it has to be a "colon", of course!
"There lies the dog buried" (German saying translated literally)
- tulamide
- Posts: 2714
- Joined: Sat Jun 21, 2014 2:48 pm
- Location: Germany
Re: [Tutorial] Ruby: Symbols
Thanks T for the colon clarification
Hey, I only speak English ... so I can focus 'messing up' to my full potential.
[yeah ... took Spanish and French in High School ... many eons ago].
Hey, I only speak English ... so I can focus 'messing up' to my full potential.
[yeah ... took Spanish and French in High School ... many eons ago].
- RJHollins
- Posts: 1571
- Joined: Thu Mar 08, 2012 7:58 pm
7 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 48 guests