Support

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

[Tutorial] Ruby: Symbols

For general discussion related FlowStone

[Tutorial] Ruby: Symbols

Postby tulamide » Thu Mar 18, 2021 7:12 am

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:

McDonalds-Logo-PNG8.png
McDonalds-Logo-PNG8.png (9.13 KiB) Viewed 12830 times


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 :o

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: 2687
Joined: Sat Jun 21, 2014 2:48 pm
Location: Germany

Re: [Tutorial] Ruby: Symbols

Postby Spogg » Thu Mar 18, 2021 9:21 am

Excellent tulamide!

Thank you for taking the time to explain this so well. :D
User avatar
Spogg
 
Posts: 3323
Joined: Thu Nov 20, 2014 4:24 pm
Location: Birmingham, England

Re: [Tutorial] Ruby: Symbols

Postby RJHollins » Thu Mar 18, 2021 5:02 pm

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 8-)
RJHollins
 
Posts: 1568
Joined: Thu Mar 08, 2012 7:58 pm

Re: [Tutorial] Ruby: Symbols

Postby HughBanton » Thu Mar 18, 2021 6:32 pm

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 :lol:

H
User avatar
HughBanton
 
Posts: 265
Joined: Sat Apr 12, 2008 3:10 pm
Location: Evesham, Worcestershire

Re: [Tutorial] Ruby: Symbols

Postby RJHollins » Thu Mar 18, 2021 7:36 pm

Q U A R T E R P O U N D E R




... with cheese :mrgreen:


NO KETCHUP !
RJHollins
 
Posts: 1568
Joined: Thu Mar 08, 2012 7:58 pm

Re: [Tutorial] Ruby: Symbols

Postby tulamide » Fri Mar 19, 2021 5:20 am

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: 2687
Joined: Sat Jun 21, 2014 2:48 pm
Location: Germany

Re: [Tutorial] Ruby: Symbols

Postby RJHollins » Fri Mar 19, 2021 6:28 am

Thanks T for the colon clarification :D

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: 1568
Joined: Thu Mar 08, 2012 7:58 pm


Return to General

Who is online

Users browsing this forum: No registered users and 25 guests

cron