# Ruby's symbols

- Thread: https://externals.io/message/64541
- Original archive: https://news-web.php.net/php.internals/64541
- Started by Nikita Nefedov on 2013-01-05T14:07:10+00:00
- Messages: 19
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #64542 — Crocodile — 2013-01-05T10:27:01+00:00

URL: https://externals.io/message/64541#64542 · In reply to: #64541

Sounds like it could make some sense. However, I've got a question..

array(
 'label' => 'Comment',
 'required' => false,
 'property_path' => 'properties.comment'
)

is actually equivalent to

array(
 'label' => 'Comment',
 'property_path' => 'properties.comment',
 'required' => false,
)

(Notice the change in keys order. As long as we just use those arrays as
hash maps, we notice no differences).

With symbols, which act as aliases for integer array keys, the situation
could be different, right? Or excuse me if I don't get what symbols are (I
don't know much about Ruby)

Cheers,
Victor

2013/1/5 Nikita Nefedov <inefedor@gmail.com>

> array(
>                 'label' => 'Comment',
>                 'required' => false,
>                 'property_path' => 'properties.comment'
>             )

---

## #64545 — Ivan Enderlin @ Hoa — 2013-01-05T11:28:17+00:00

URL: https://externals.io/message/64541#64545 · In reply to: #64541

Hi :-),

Nice proposal but I have few questions and remarks.

My first question is how to delete symbols? I don't know if it is useful 
or not. We should discuss about that. Is `unset(:foo)` enough? How are 
they handled by the GC?

Another question is: where are we able to use symbols? Is it allowed to 
write `const FOO = :bar` for example? Or in a default argument value: 
`public function f ( $x = :foo ) { … }`?

What kind of (arithmetical) operations are allowed on symbols?

You proposed to represent symbols as integers. Could it create 
conflicts? For example: `$foo = [0 => 'bar', :baz => 'qux']`. What 
happens if `:baz` is set to 0?

Finally, if my memory is good, a few months ago, some patches were 
updating “constant strings” performances by representing them as 
“buffers”/“constants” internally, no? Maybe I'm wrong, but it could be a 
middle-way solution if it is not yet implemented (especially since we 
have strings dereferencing, implementation could be ease).

My two cents :-).
Best regards.





> I know I shouldn't write "Ruby" in the subject of a letter for 
> php-internals ML, but... Just wanted to ask, is anybody interested in 
> this feature in PHP?
> You can read about it here: 
> http://www.randomhacks.net/articles/2007/01/20/13-ways-of-looking-at-a-ruby-symbol
>
> It can be implemented in PHP as a HashTable where key would be strings 
> and values would be unique identifiers (just incrementing long, can be 
> tracked with nNextFreeElement).
>
> How it would work in userland?
>
> If it would be proposal, I would divide it on two different 
> (competitive) proposals:
>
> First, we could implement it so symbol expression would return an 
> associated integer.
> (note that symbols are most often used as hash keys in ruby so my 
> examples are relying on it)
> Example:
> $foo = array();
> $foo[:bar] = "qwerty";
>
> var_dump($foo);
> // array(1) {
> //  [0] =>
> //  string(6) "qwerty"
> //}
>
> var_dump(:bar); // int(0)
>
> var_dump(:some_new_symbol); // int(1)
>
> This is the easiest way, and I can implement it. But, it would be hard 
> to debug.
>
> The second way - we can implement it as a new variable type, and the 
> main thing is that arrays will be able to take variables of symbol 
> type as keys, I know it sounds scary but it's not so hard actually.
> I will drop the part about new variable type, the main thing is how 
> HashTables could work with symbols as keys.
> We could change the type of nKeyLength (in Bucket) to signed integer 
> (now it's unsigned, I don't think we will miss something from that) 
> and use it as a flag: if it's -1 (less than zero) - then we know the 
> symbol was used as a key, there will be filled bucket.h member with a 
> symbol identifier.
> That way the above code will evaluate so:
> $foo = array();
> $foo[:bar] = "qwerty";
>
> var_dump($foo);
> // array(1) {
> //  [:bar] =>
> //  string(6) "qwerty"
> //}
>
> var_dump(:bar); // symbol(:bar)
>
> var_dump(:some_new_symbol); // symbol(:some_new_symbol)
>
> To make it clear, when retrieving an element by symbol from array, 
> these steps will be needed:
> 1. Get symbol identifier (ulong)
> 2. Get elements from array where bucket.h equals to this identifier
> 3. Iterate over those elements and find the one that has nKeyLength == -1
> (actually we will iterate over pNext/pLast elements)
>
>
> What symbols can give:
> 1. More convenient way to use it almost everywhere as a replacement 
> for strings and sometimes for constants. There's a lot of code that 
> uses arrays as a parameter-stores. For example, here's how you usually 
> define a form in Symfony2:
>         $builder
>             ->add('title', 'text', array(
>                 'label' => 'Album title'
>             ))
>             ->add('title_alias', 'text', array(
>                 'label' => 'Album alias',
>                 'required' => false,
>                 'property_path' => 'properties.titleAlias'
>             ))
>             ->add('comment', 'text', array(
>                 'label' => 'Comment',
>                 'required' => false,
>                 'property_path' => 'properties.comment'
>             ))
>             ->add('labels', 'text', array(
>                 'label' => 'Musical labels',
>                 'required' => false,
>                 'property_path' => 'properties.labels'
>             ))
>             ->add('language', 'text', array(
>                 'required' => false,
>                 'property_path' => 'properties.language'
>             ))
> It could be improved this way:
>         $builder
>             ->add('title', :text, array(
>                 :label => 'Album title'
>             ))
>             ->add('title_alias', :text, array(
>                 :label => 'Album alias',
>                 :required => false,
>                 :property_path => 'properties.titleAlias'
>             ))
>             ->add('comment', :text, array(
>                 :label => 'Comment',
>                 :required => false,
>                 :property_path => 'properties.comment'
>             ))
>             ->add('labels', :text, array(
>                 :label => 'Musical labels',
>                 :required => false,
>                 :property_path => 'properties.labels'
>             ))
>             ->add('language', :text, array(
>                 :required => false,
>                 :property_path => 'properties.language'
>             ))
> 2. Memory usage reduction. AFAIK, there's a lot of cases like the 
> above and the use of symbols would affect on memory usage significantly.
> 3. Memory leaks. Symbols can't be just garbage collected as, for 
> example zvals, it's not possible. But we can do it for every request, 
> so I don't think it would be problem.
> 4. Autocompletion from IDEs.
>
> PS I don't want to call it "proposal", despite the fact that this is 
> actually a proposal, I'm just not sure it can go as a proposal.
>

-- 
Ivan Enderlin
Developer of Hoa
http://hoa.42/ or http://hoa-project.net/

PhD. student at DISC/Femto-ST (Vesontio) and INRIA (Cassis)
http://disc.univ-fcomte.fr/ and http://www.inria.fr/

Member of HTML and WebApps Working Group of W3C
http://w3.org/

---

## #64546 — Nikita Popov — 2013-01-05T12:21:26+00:00

URL: https://externals.io/message/64541#64546 · In reply to: #64541

> What symbols can give:
> 1. More convenient way to use it almost everywhere as a replacement for
> strings and sometimes for constants. There's a lot of code that uses arrays
> as a parameter-stores. For example, here's how you usually define a form in
> Symfony2:
>         $builder
>             ->add('title', 'text', array(
>                 'label' => 'Album title'
>             ))
>             ->add('title_alias', 'text', array(
>                 'label' => 'Album alias',
>                 'required' => false,
>                 'property_path' => 'properties.titleAlias'
>             ))
>             ->add('comment', 'text', array(
>                 'label' => 'Comment',
>                 'required' => false,
>                 'property_path' => 'properties.comment'
>             ))
>             ->add('labels', 'text', array(
>                 'label' => 'Musical labels',
>                 'required' => false,
>                 'property_path' => 'properties.labels'
>             ))
>             ->add('language', 'text', array(
>                 'required' => false,
>                 'property_path' => 'properties.language'
>             ))
> It could be improved this way:
>         $builder
>             ->add('title', :text, array(
>                 :label => 'Album title'
>             ))
>             ->add('title_alias', :text, array(
>                 :label => 'Album alias',
>                 :required => false,
>                 :property_path => 'properties.titleAlias'
>             ))
>             ->add('comment', :text, array(
>                 :label => 'Comment',
>                 :required => false,
>                 :property_path => 'properties.comment'
>             ))
>             ->add('labels', :text, array(
>                 :label => 'Musical labels',
>                 :required => false,
>                 :property_path => 'properties.labels'
>             ))
>             ->add('language', :text, array(
>                 :required => false,
>                 :property_path => 'properties.language'
>             ))
> 2. Memory usage reduction. AFAIK, there's a lot of cases like the above
> and the use of symbols would affect on memory usage significantly.
> 3. Memory leaks. Symbols can't be just garbage collected as, for example
> zvals, it's not possible. But we can do it for every request, so I don't
> think it would be problem.
> 4. Autocompletion from IDEs.
>

Hi Nikita!

I don't quite understand what those symbols would actually be good for. If
it's just for saving exactly one character for array keys (:foo vs "foo"),
then this isn't worth it. If this is about memory savings, then I don't
think it will help at all. PHP uses interned strings, so all those "label"
etc strings in your above example actually use the same string value. The
hash for those strings is also precomputed, so symbol don't have a
performance advantage either. Regarding your fourth point, autocompletion
is available for string array keys at least in PhpStorm and I guess also in
other IDEs.

So, I don't yet really get what the point behind the symbols is.

Thanks,
Nikita

---

## #64548 — Ivan Enderlin @ Hoa — 2013-01-05T12:27:54+00:00

URL: https://externals.io/message/64541#64548 · In reply to: #64546

> [snip]
> If this is about memory savings, then I don't
> think it will help at all. PHP uses interned strings, so all those "label"
> etc strings in your above example actually use the same string value. The
> hash for those strings is also precomputed, so symbol don't have a
> performance advantage either.
That's what I refered in my previous mail. Thanks Nikita (Popov) for the 
clarification.

Best regards.

-- 
Ivan Enderlin
Developer of Hoa
http://hoa.42/ or http://hoa-project.net/

PhD. student at DISC/Femto-ST (Vesontio) and INRIA (Cassis)
http://disc.univ-fcomte.fr/ and http://www.inria.fr/

Member of HTML and WebApps Working Group of W3C
http://w3.org/

---

## #64549 — Tom Boutell — 2013-01-05T13:39:15+00:00

URL: https://externals.io/message/64541#64549 · In reply to: #64545

If symbols could use the sign bit or otherwise distinguish from typical integer keys one would have some hope of meaningful debugging output. I don't think it makes sense to mix integer keys and symbol keys but being able to differentiate them for debugging purposes would be great. However since php arrays are sparse anyway is there much of a win from integer keys in the first place?

Sent from my iPhone



> Hi :-),
> 
> Nice proposal but I have few questions and remarks.
> 
> My first question is how to delete symbols? I don't know if it is useful or not. We should discuss about that. Is `unset(:foo)` enough? How are they handled by the GC?
> 
> Another question is: where are we able to use symbols? Is it allowed to write `const FOO = :bar` for example? Or in a default argument value: `public function f ( $x = :foo ) { … }`?
> 
> What kind of (arithmetical) operations are allowed on symbols?
> 
> You proposed to represent symbols as integers. Could it create conflicts? For example: `$foo = [0 => 'bar', :baz => 'qux']`. What happens if `:baz` is set to 0?
> 
> Finally, if my memory is good, a few months ago, some patches were updating “constant strings” performances by representing them as “buffers”/“constants” internally, no? Maybe I'm wrong, but it could be a middle-way solution if it is not yet implemented (especially since we have strings dereferencing, implementation could be ease).
> 
> My two cents :-).
> Best regards.
> 
> 
> 
> 
> 
> > […]
> 
> -- 
> Ivan Enderlin
> Developer of Hoa
> http://hoa.42/ or http://hoa-project.net/
> 
> PhD. student at DISC/Femto-ST (Vesontio) and INRIA (Cassis)
> http://disc.univ-fcomte.fr/ and http://www.inria.fr/
> 
> Member of HTML and WebApps Working Group of W3C
> http://w3.org/

---

## #64541 — Nikita Nefedov — 2013-01-05T14:07:10+00:00

URL: https://externals.io/message/64541#64541

I know I shouldn't write "Ruby" in the subject of a letter for  
php-internals ML, but... Just wanted to ask, is anybody interested in this  
feature in PHP?
You can read about it here:  
http://www.randomhacks.net/articles/2007/01/20/13-ways-of-looking-at-a-ruby-symbol

It can be implemented in PHP as a HashTable where key would be strings and  
values would be unique identifiers (just incrementing long, can be tracked  
with nNextFreeElement).

How it would work in userland?

If it would be proposal, I would divide it on two different (competitive)  
proposals:

First, we could implement it so symbol expression would return an  
associated integer.
(note that symbols are most often used as hash keys in ruby so my examples  
are relying on it)
Example:
$foo = array();
$foo[:bar] = "qwerty";

var_dump($foo);
// array(1) {
//  [0] =>
//  string(6) "qwerty"
//}

var_dump(:bar); // int(0)

var_dump(:some_new_symbol); // int(1)

This is the easiest way, and I can implement it. But, it would be hard to  
debug.

The second way - we can implement it as a new variable type, and the main  
thing is that arrays will be able to take variables of symbol type as  
keys, I know it sounds scary but it's not so hard actually.
I will drop the part about new variable type, the main thing is how  
HashTables could work with symbols as keys.
We could change the type of nKeyLength (in Bucket) to signed integer (now  
it's unsigned, I don't think we will miss something from that) and use it  
as a flag: if it's -1 (less than zero) - then we know the symbol was used  
as a key, there will be filled bucket.h member with a symbol identifier.
That way the above code will evaluate so:
$foo = array();
$foo[:bar] = "qwerty";

var_dump($foo);
// array(1) {
//  [:bar] =>
//  string(6) "qwerty"
//}

var_dump(:bar); // symbol(:bar)

var_dump(:some_new_symbol); // symbol(:some_new_symbol)

To make it clear, when retrieving an element by symbol from array, these  
steps will be needed:
1. Get symbol identifier (ulong)
2. Get elements from array where bucket.h equals to this identifier
3. Iterate over those elements and find the one that has nKeyLength == -1
(actually we will iterate over pNext/pLast elements)


What symbols can give:
1. More convenient way to use it almost everywhere as a replacement for  
strings and sometimes for constants. There's a lot of code that uses  
arrays as a parameter-stores. For example, here's how you usually define a  
form in Symfony2:
         $builder
             ->add('title', 'text', array(
                 'label' => 'Album title'
             ))
             ->add('title_alias', 'text', array(
                 'label' => 'Album alias',
                 'required' => false,
                 'property_path' => 'properties.titleAlias'
             ))
             ->add('comment', 'text', array(
                 'label' => 'Comment',
                 'required' => false,
                 'property_path' => 'properties.comment'
             ))
             ->add('labels', 'text', array(
                 'label' => 'Musical labels',
                 'required' => false,
                 'property_path' => 'properties.labels'
             ))
             ->add('language', 'text', array(
                 'required' => false,
                 'property_path' => 'properties.language'
             ))
It could be improved this way:
         $builder
             ->add('title', :text, array(
                 :label => 'Album title'
             ))
             ->add('title_alias', :text, array(
                 :label => 'Album alias',
                 :required => false,
                 :property_path => 'properties.titleAlias'
             ))
             ->add('comment', :text, array(
                 :label => 'Comment',
                 :required => false,
                 :property_path => 'properties.comment'
             ))
             ->add('labels', :text, array(
                 :label => 'Musical labels',
                 :required => false,
                 :property_path => 'properties.labels'
             ))
             ->add('language', :text, array(
                 :required => false,
                 :property_path => 'properties.language'
             ))
2. Memory usage reduction. AFAIK, there's a lot of cases like the above  
and the use of symbols would affect on memory usage significantly.
3. Memory leaks. Symbols can't be just garbage collected as, for example  
zvals, it's not possible. But we can do it for every request, so I don't  
think it would be problem.
4. Autocompletion from IDEs.

PS I don't want to call it "proposal", despite the fact that this is  
actually a proposal, I'm just not sure it can go as a proposal.

---

## #64543 — Nikita Nefedov — 2013-01-05T14:31:16+00:00

URL: https://externals.io/message/64541#64543 · In reply to: #64542

On Sat, 05 Jan 2013 10:27:01 -0000, Crocodile <crocodile2u@gmail.com>  
wrote:

> Sounds like it could make some sense. However, I've got a question..
>
> array(
> 'label' => 'Comment',
> 'required' => false,
> 'property_path' => 'properties.comment'
> )
>
> > […]
>
> > […]
> 'label' => 'Comment',
> 'property_path' => 'properties.comment',
> 'required' => false,
> )
>
> > […]
>
> > […]
>
> > […]
> Victor
>
> 2013/1/5 Nikita Nefedov <inefedor@gmail.com>
> > […]
>

Hi,

PHP arrays are always ordered (they actually are doubly-linked lists and  
hash tables at the same time), so there won't be any change in ordering  
behavior.

---

## #64552 — Nikita Popov — 2013-01-05T16:49:14+00:00

URL: https://externals.io/message/64541#64552 · In reply to: #64551

> **
> Though there would be a little speed-up because with Symbols array's
> Buckets will keep numeric key, so instead of memcmp you will need to just
> compare two longs when retrieving element.
>

Before memcmping the array keys PHP will first compare the pointers. For
interned strings the pointers will be the same so the memcmp is not done.
See http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_hash.c#950.


> Actually this is looks a little bad now, AFAIK this is what happens when
> you trying to receive value from array by string key:
>
>    1. Calling zend_new_interned_string_int for interning or getting
>    already interned same string, receiving pointer to the stored string from
>    it:
>       1. Hash the string (O(n))
>       2. Retrieve bucket from arBuckets
>       3. Find needed bucket by iterating over all retrieved buckets (over
>       *pLast) and comparing its keys with memcmp
>       4. If found - return pointer to string, else create new bucket...
>    2. Now that we have an interned string, we can try to retrieve value
>    from array with string:
>       1. Hash the string again (O(n))
>       2. Retrieve bucket by hash fro arBuckets
>       3. And again memcmp used for comparing strings
>
> The string interning happens at compile time, so for all practical
purposes it does not matter much how long it takes. At runtime the hash is
already precalculated and the ptrs are the same (see above) so the array
access goes through pretty much the fastest possible code-path. I quickly
tried out how fast they are compared to numeric keys:
http://codepad.viper-7.com/Km9hPz String and integer keys perform pretty
much the same there.

Nikita

---

## #64553 — inefedor@gmail.com — 2013-01-05T17:43:43+00:00

URL: https://externals.io/message/64541#64553 · In reply to: #64552

> On Sat, Jan 5, 2013 at 6:58 PM, Nikita Nefedov <inefedor@gmail.com>  
> wrote:
>
> > […]
>
> Before memcmping the array keys PHP will first compare the pointers. For
> interned strings the pointers will be the same so the memcmp is not done.
> See http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_hash.c#950.

My fault, didn't see it in the source...

---

## #64551 — Nikita Nefedov — 2013-01-05T17:58:19+00:00

URL: https://externals.io/message/64541#64551 · In reply to: #64546

On Sat, 05 Jan 2013 12:21:26 -0000, Nikita Popov <nikita.ppv@gmail.com>  
wrote:

> On Sat, Jan 5, 2013 at 3:07 PM, Nikita Nefedov <inefedor@gmail.com>  
> wrote:
> > […]
>
> Hi Nikita!
>
> I don't quite understand what those symbols would actually be good for.  
> If it's just for saving exactly one >character for array keys (:foo vs  
> "foo"), then this isn't worth it. If this is about memory savings, then  
> I don't >think it will help at all. PHP uses interned strings, so all  
> those "label" etc strings in your above example >actually use the same  
> string value. The hash for those strings is also precomputed, so symbol  
> don't have a >performance advantage either. Regarding your fourth point,  
> autocompletion is available for string array keys at >least in PhpStorm  
> and I guess also in other IDEs.
>
> So, I don't yet really get what the point behind the symbols is.
>
> Thanks,
> Nikita

Hi, yes, you are right about interned strings, I didn't know it.
Actually my personal opinion is that strings should be used to store data  
(as values), not to retrieve it (not as keys). But strings are more  
developer-friendly than anything else (because you don't need to define  
new constant or new enumerable member for adding new parameter on  
receiving side, and you always see what this parameter is about). So you  
can see Symbols as enumerable that don't need to be initialized. There's  
actually no technical reason behind that.

Though there would be a little speed-up because with Symbols array's  
Buckets will keep numeric key, so instead of memcmp you will need to just  
compare two longs when retrieving element.
Actually this is looks a little bad now, AFAIK this is what happens when  
you trying to receive value from array by string key:
Calling zend_new_interned_string_int for interning or getting already  
interned same string, receiving pointer to the stored string from it:
Hash the string (O(n))
Retrieve bucket from arBuckets
Find needed bucket by iterating over all retrieved buckets (over *pLast)  
and comparing its keys with memcmp
If found - return pointer to string, else create new bucket...
Now that we have an interned string, we can try to retrieve value from  
array with string:
Hash the string again (O(n))
Retrieve bucket by hash fro arBuckets
And again memcmp used for comparing strings

This could be improved with Symbols, so that you won't need hash string  
twice and use memcmp.

BTW do we really need a doubly linked list for interned strings  
(pListLast, pListNext) and all the extra members from HashTable/Bucket  
that needed for arrays? I know this is offtopic and these structs are used  
everywhere in PHP (because of DRY), but there are some places like this or  
class tables where we don't need arrays (PHP's arrays) functionality.

---

## #64565 — Stas Malyshev — 2013-01-05T22:49:25+00:00

URL: https://externals.io/message/64541#64565 · In reply to: #64541

Hi!

> I know I shouldn't write "Ruby" in the subject of a letter for  
> php-internals ML, but... Just wanted to ask, is anybody interested in this  
> feature in PHP?

As I understand, :foo is basically an interned string "foo". But in PHP
all constant strings are interned now, so the only thing we gain is
comparison speed. Given that the strings we're talking about is under 10
chars, performance gain from this would be negligible, and symbols
aren't frequently directly compared anyway. So what exactly we're
gaining that is not there in just constant string?

> $foo = array();
> $foo[:bar] = "qwerty";
> 
> var_dump($foo);
> // array(1) {
> //  [0] =>
> //  string(6) "qwerty"
> //}

Here's a problem. How we know that :bar is 0? What if we serialized $foo
and later loaded it back - would :bar still be 0? Would :bar be 0 in all
scripts forever - and if not, how would we know where $foo[:bar] is
actually stored when we combine two scripts? I think it can not work
this way since link between :bar and actual hash key should be stable.

> I will drop the part about new variable type, the main thing is how  
> HashTables could work with symbols as keys.

HashTable can accept only string or number as key. As we have seen
before, making number from :bar is very hard to pull off properly. And
if we use string "bar", why not just use string "bar"?

> 1. More convenient way to use it almost everywhere as a replacement for  
> strings and sometimes for constants. There's a lot of code that uses  
> arrays as a parameter-stores. For example, here's how you usually define a  
> form in Symfony2:

How it's more convenient? I don't see any difference.

> 2. Memory usage reduction. AFAIK, there's a lot of cases like the above  
> and the use of symbols would affect on memory usage significantly.

I don't see any memory usage reduction - you still have to store the
string. Could you explain how memory usage is reduced?

-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #64568 — Kris Craig — 2013-01-05T23:29:09+00:00

URL: https://externals.io/message/64541#64568 · In reply to: #64565

On Sat, Jan 5, 2013 at 2:49 PM, Stas Malyshev <smalyshev@sugarcrm.com>wrote:

> Hi!
>
> > […]
> this
> > […]
>
> As I understand, :foo is basically an interned string "foo". But in PHP
> all constant strings are interned now, so the only thing we gain is
> comparison speed. Given that the strings we're talking about is under 10
> chars, performance gain from this would be negligible, and symbols
> aren't frequently directly compared anyway. So what exactly we're
> gaining that is not there in just constant string?
>
> > […]
>
> Here's a problem. How we know that :bar is 0? What if we serialized $foo
> and later loaded it back - would :bar still be 0? Would :bar be 0 in all
> scripts forever - and if not, how would we know where $foo[:bar] is
> actually stored when we combine two scripts? I think it can not work
> this way since link between :bar and actual hash key should be stable.
>
> > […]
>
> HashTable can accept only string or number as key. As we have seen
> before, making number from :bar is very hard to pull off properly. And
> if we use string "bar", why not just use string "bar"?
>
> > […]
> a
> > […]
>
> How it's more convenient? I don't see any difference.
>
> > […]
>
> I don't see any memory usage reduction - you still have to store the
> string. Could you explain how memory usage is reduced?
>
> --
> Stanislav Malyshev, Software Architect
> SugarCRM: http://www.sugarcrm.com/
> (408)454-6900 ext. 227
>
> --
> 
> 
>
>
I'm still a total newb when it comes to Ruby, but as I understand it, a
symbol can be particularly helpful by maximizing code readability without
sacrificing efficiency.  As a PHP guy, I tend to think of a Ruby symbol as
a constant that doesn't need to be defined or set.  Its value is set
internally and is not relevant in userland except for the fact that it is
unique and unchanging.

For example, in current PHP, let's say I just bought a dog:

<?php

define( 'BROWN', 0x01 );
define( 'BLACK', 0x02 );
define( 'PURPLE', 0x03 );

switch ( $color )
{
case BROWN:
// Brown dog!
break;
case BLACK:
// Black dog!
break;
case PURPLE:
// Purple dog!?
break;
}

?>

Now, if we had symbols, I could get rid of the constants and just do this
instead:

<?php

switch ( $color )
{
case :brown:
// Brown dog!
break;
case :black:
// Black dog!
break;
case :purple:
// Purple dog!?
break;
}

?>

In both cases, we really don't care what the actual values of brown, black,
and purple are.  We just want it to be unique so we can reference each of
them in a visually friendly way with minimal performance impact.  That's
where I could see a valid use-case for Ruby-like symbols in PHP.

--Kris

---

## #64569 — Rasmus Lerdorf — 2013-01-05T23:32:11+00:00

URL: https://externals.io/message/64541#64569 · In reply to: #64568

> In both cases, we really don't care what the actual values of brown, black,
> and purple are.  We just want it to be unique so we can reference each of
> them in a visually friendly way with minimal performance impact.  That's
> where I could see a valid use-case for Ruby-like symbols in PHP.

What you are describing is just an enum. That's not really what Ruby
symbols are about.

-Rasmus

---

## #64570 — Kris Craig — 2013-01-05T23:36:19+00:00

URL: https://externals.io/message/64541#64570 · In reply to: #64569

> 
>
> > […]
> black,
> > […]
>
> What you are describing is just an enum. That's not really what Ruby
> symbols are about.
>
> -Rasmus
>
>
Ruby doesn't have native enums.  Symbols are often used in Ruby code to
obtain the same functionality, though.

--Kris

---

## #64572 — Nikita Popov — 2013-01-05T23:37:51+00:00

URL: https://externals.io/message/64541#64572 · In reply to: #64568

> I'm still a total newb when it comes to Ruby, but as I understand it, a
> symbol can be particularly helpful by maximizing code readability without
> sacrificing efficiency.  As a PHP guy, I tend to think of a Ruby symbol as
> a constant that doesn't need to be defined or set.  Its value is set
> internally and is not relevant in userland except for the fact that it is
> unique and unchanging.
>
> For example, in current PHP, let's say I just bought a dog:
>
> <?php
>
> define( 'BROWN', 0x01 );
> define( 'BLACK', 0x02 );
> define( 'PURPLE', 0x03 );
>
> switch ( $color )
> {
> case BROWN:
> // Brown dog!
> break;
> case BLACK:
> // Black dog!
> break;
> case PURPLE:
> // Purple dog!?
> break;
> }
>
> ?>
>
> Now, if we had symbols, I could get rid of the constants and just do this
> instead:
>
> <?php
>
> switch ( $color )
> {
> case :brown:
> // Brown dog!
> break;
> case :black:
> // Black dog!
> break;
> case :purple:
> // Purple dog!?
> break;
> }
>
> ?>
>
> In both cases, we really don't care what the actual values of brown, black,
> and purple are.  We just want it to be unique so we can reference each of
> them in a visually friendly way with minimal performance impact.  That's
> where I could see a valid use-case for Ruby-like symbols in PHP.
>
> --Kris
>

The reason that Ruby needs symbols basically comes down to the fact that
Ruby has *mutable* strings. I'm not sure how they came up with that idea (I
mean, really, mutable strings? wtf?!), but due to it Ruby needs another
string type that is immutable. That's what symbols are. Symbols are Ruby's
variant of immutable interned strings. PHP doesn't need this because
strings in PHP are immutable by themselves and automatically interned where
reasonable.

Nikita

---

## #64573 — Rasmus Lerdorf — 2013-01-05T23:39:07+00:00

URL: https://externals.io/message/64541#64573 · In reply to: #64570

> 
> 
> On Sat, Jan 5, 2013 at 3:32 PM, Rasmus Lerdorf <rasmus@lerdorf.com
> <mailto:rasmus@lerdorf.com>> wrote:
> 
>     
> 
> > […]
>     brown, black,
> > […]
>     each of
> > […]
>      That's
> > […]
> 
>     What you are describing is just an enum. That's not really what Ruby
>     symbols are about.
> 
>     -Rasmus
> 
> 
> Ruby doesn't have native enums.  Symbols are often used in Ruby code to
> obtain the same functionality, though.

Right, but if that is the only use you can come up with for them in PHP,
then there are way simpler ways to do it. We already have an enum RFC.
https://wiki.php.net/rfc/enum

-Rasmus

---

## #64576 — Kris Craig — 2013-01-05T23:43:08+00:00

URL: https://externals.io/message/64541#64576 · In reply to: #64573

> 
> > […]
>
> Right, but if that is the only use you can come up with for them in PHP,
> then there are way simpler ways to do it. We already have an enum RFC.
> https://wiki.php.net/rfc/enum
>
> -Rasmus
>
>
Granted, but other use-cases have already been presented as well.
 Obviously the one I suggested would no longer be useful if PHP adopts
enums.

--Kris

---

## #64577 — Stas Malyshev — 2013-01-05T23:44:44+00:00

URL: https://externals.io/message/64541#64577 · In reply to: #64568

Hi!

> I'm still a total newb when it comes to Ruby, but as I understand it, a
> symbol can be particularly helpful by maximizing code readability
> without sacrificing efficiency.  As a PHP guy, I tend to think of a Ruby
> symbol as a constant that doesn't need to be defined or set.  Its value

String is a constant that doesn't need to be defined of set.

> In both cases, we really don't care what the actual values of brown,
> black, and purple are.  We just want it to be unique so we can reference

If you don't care what the values are, why have them at all? What's
wrong with just using "brown", etc.?

-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #64583 — Rasmus Lerdorf — 2013-01-06T00:23:29+00:00

URL: https://externals.io/message/64541#64583 · In reply to: #64576

> Granted, but other use-cases have already been presented as well.
>  Obviously the one I suggested would no longer be useful if PHP adopts
> enums.

Actually, I didn't see any other cases. The fact that we have interned
immutable strings in PHP invalidated all the other cases presented so far.

-Rasmus
