# Symbols are your friends

**URL:** <https://www.ruby-forum.com/t/symbols-are-your-friends/100147>\
**Category:** Ruby\
**Created:** [July 27, 2006, 12:51pm UTC](https://www.ruby-forum.com/t/symbols-are-your-friends/100147 "2006-07-27T12:51:59Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![dasch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b2d939/32.png) [@dasch](https://www.ruby-forum.com/u/dasch)\
**Post date:** [July 27, 2006, 12:51pm UTC](https://www.ruby-forum.com/t/symbols-are-your-friends/100147/1 "2006-07-27T12:51:59Z")

</div>

Yes, it’s time for another Symbol trick!

class Symbol  
def ===(obj)  
obj.respond\_to? “to\_#{self}”  
end  
end

case “foo”  
when :int then “integer”  
when :str then “string”  
when :ary then “array”  
end #=\> “string”

Genius. Sheer genius.

Daniel

---

<div class="post-metadata">

**Author:** ![dasch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b2d939/32.png) [@dasch](https://www.ruby-forum.com/u/dasch)\
**Post date:** [July 27, 2006, 6:52pm UTC](https://www.ruby-forum.com/t/symbols-are-your-friends/100147/2 "2006-07-27T18:52:11Z")

</div>

On 7/27/06, Daniel S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Yes, it’s time for another Symbol trick!
> 
> class Symbol  
> def ===(obj)  
> obj.respond\_to? “to\_#{self}”  
> end  
> end

This idea has been discussed on this list before; I can’t find the  
thread at the moment.  
This seems like a really clever idea, and is fine for just playing  
around… but it’s not advisable for general use. You’re changing the  
semantics of Symbol#===, which will break things like this:

case method\_name  
when :reverse  
#…  
when :each  
#…  
else #…  
end

The following is a simplified extract of what I use in Reg for a  
similar feature. It’s safer, as long as nothing else decides to do  
something with Symbol#-@.

class Symbol  
def -@; Reg::Knows.new(self) end  
end

module Reg  
class Knows  
def initialize(sym)  
@sym=sym  
end  
def ===(other)  
other.respond\_to? @sym  
end  
end  
end

(You’re prepending “to\_” to your method names before checking; I don’t  
know why. This way seems more general…)

---

<div class="post-metadata">

**Author:** ![dasch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b2d939/32.png) [@dasch](https://www.ruby-forum.com/u/dasch)\
**Post date:** [July 27, 2006, 7:56pm UTC](https://www.ruby-forum.com/t/symbols-are-your-friends/100147/3 "2006-07-27T19:56:29Z")

</div>

Caleb C. wrote:

> thread at the moment.  
> end  
> Yes, that’s true – I only ever intended it to be a trick.

> (You’re prepending “to\_” to your method names before checking; I don’t  
> know why. This way seems more general…)

I was using it to demonstrate how you could duck type check with a case  
statement, so focusing on the “type” made sense. I see this all the  
time:

case obj  
when Integer then foo  
when String then bar  
end

and it strikes me as not being very duckish (quacky?) Using if  
statements can be annoying:

if obj.respond\_to? :to\_str  
foo  
elsif obj.respond\_to? :to\_int  
bar  
end

Maybe this would work?

class Symbol  
def ===(obj)  
return true if self == obj  
obj.respond\_to? “to\_#{self}”  
end  
end

though something like this may cause trouble:

obj = :int  
case obj  
when :int then “integer”  
when :str then “string”  
end

Cheers,  
Daniel

---

<div class="post-metadata">

**Author:** ![dasch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b2d939/32.png) [@dasch](https://www.ruby-forum.com/u/dasch)\
**Post date:** [July 27, 2006, 9:12pm UTC](https://www.ruby-forum.com/t/symbols-are-your-friends/100147/4 "2006-07-27T21:12:28Z")

</div>

On 7/27/06, Daniel S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> and it strikes me as not being very duckish (quacky?) Using if  
> statements can be annoying:
> 
> if obj.respond\_to? :to\_str  
> foo  
> elsif obj.respond\_to? :to\_int  
> bar  
> end

I see where you’re coming from, but I guess I just don’t see that  
#to\_\* methods as being that special. Why wouldn’t you want to do this  
kind of dispatch for other methods too?

Using the code I posted previously, the above conditionals could be  
written as:

case obj  
when -:to\_str  
foo  
when -:to\_int  
bar  
end

I like that one best.

Fooling with the existing Symbol#=== in any way is very likely to  
break some existing libs which assumes the current definition always  
obtains… my way lets you use (almost-)symbols in the way you want to  
use them. It is incompatible with libs that also define Symbol#-@ in a  
different way, but those are presumably much rarer, perhaps  
nonexistant. (Nobody’s as crazy as I am.) If you really want this  
feature in a general way, (and I do, for Reg) this seems to be the  
best compromise.

---

<div class="post-metadata">

**Author:** ![dasch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b2d939/32.png) [@dasch](https://www.ruby-forum.com/u/dasch)\
**Post date:** [July 28, 2006, 6:29pm UTC](https://www.ruby-forum.com/t/symbols-are-your-friends/100147/5 "2006-07-28T18:29:37Z")

</div>

> Because I only think the #to\_x methods are directly related to types.  
> They even have more nuances than class-based types; there’s a difference  
> between defining #to\_s and defining #to\_str, for example.

In the spirit of making sure I understand, and perhaps explaining this  
to anyone else that may be confused, the difference in these two kinds  
of methods:

If an object _can_ be represented as an integer in some cases (e.g. a  
string, which could be set to something like “12”), it implements  
to\_i.

If an object _is_ a natural representation of an integer, (like roman  
numerals, as the example the Pickaxe gives), it implements to\_int.

So this makes sense, though nothing about the naming convention of  
these methods makes this particularly clear. However, this brings up  
the question: If something acts exactly like an integer method-wise,  
whats the benefit of explicitly calling to\_int? This seems like a non  
duck-typey thing to do.

Aleks

---

<div class="post-metadata">

**Author:** ![dasch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b2d939/32.png) [@dasch](https://www.ruby-forum.com/u/dasch)\
**Post date:** [July 28, 2006, 6:36pm UTC](https://www.ruby-forum.com/t/symbols-are-your-friends/100147/6 "2006-07-28T18:36:35Z")

</div>

On Sat, 29 Jul 2006, Aleks Kissinger wrote:

> So this makes sense, though nothing about the naming convention of these  
> methods makes this particularly clear. However, this brings up the  
> question: If something acts exactly like an integer method-wise, whats the  
> benefit of explicitly calling to\_int? This seems like a non duck-typey  
> thing to do.

- it might be faster to actually have an int

- you can fail early by filtering on one ‘category’ of behaviours  
guaranteed  
by having an object respond\_to? ‘to\_int’, this is not unlike type or  
interface checking

-a

---

<div class="post-metadata">

**Author:** ![dasch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b2d939/32.png) [@dasch](https://www.ruby-forum.com/u/dasch)\
**Post date:** [July 27, 2006, 10:58pm UTC](https://www.ruby-forum.com/t/symbols-are-your-friends/100147/7 "2006-07-27T22:58:22Z")

</div>

Caleb C. wrote:

> > end  
> > I see where you’re coming from, but I guess I just don’t see that  
> > #to\_\* methods as being that special. Why wouldn’t you want to do this  
> > kind of dispatch for other methods too?

Because I only think the #to\_x methods are directly related to types.  
They even have more nuances than class-based types; there’s a difference  
between defining #to\_s and defining #to\_str, for example.

> I like that one best.
> 
> Fooling with the existing Symbol#=== in any way is very likely to  
> break some existing libs which assumes the current definition always  
> obtains… my way lets you use (almost-)symbols in the way you want to  
> use them. It is incompatible with libs that also define Symbol#-@ in a  
> different way, but those are presumably much rarer, perhaps  
> nonexistant. (Nobody’s as crazy as I am.) If you really want this  
> feature in a general way, (and I do, for Reg) this seems to be the  
> best compromise.

Yes, I’ve adopted your solution; it is indeed the best way to get around  
the problem.

This isn’t something I believe should go into core or anything, I just  
think it’s a great showcase of Ruby’s flexibility.

Cheers,  
Daniel

---

<div class="post-metadata">

**Author:** ![dasch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b2d939/32.png) [@dasch](https://www.ruby-forum.com/u/dasch)\
**Post date:** [July 28, 2006, 6:43pm UTC](https://www.ruby-forum.com/t/symbols-are-your-friends/100147/8 "2006-07-28T18:43:15Z")

</div>

That makes sense. Thanks.

---

<div class="post-metadata">

**Author:** ![dasch](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/b2d939/32.png) [@dasch](https://www.ruby-forum.com/u/dasch)\
**Post date:** [July 28, 2006, 8:46pm UTC](https://www.ruby-forum.com/t/symbols-are-your-friends/100147/9 "2006-07-28T20:46:16Z")

</div>

Aleks Kissinger wrote:

> If an object _can_ be represented as an integer in some cases (e.g. a  
> string, which could be set to something like “12”), it implements  
> to\_i.
> 
> If an object _is_ a natural representation of an integer, (like roman  
> numerals, as the example the Pickaxe gives), it implements to\_int.

That very nicely sums it up!

> So this makes sense, though nothing about the naming convention of  
> these methods makes this particularly clear. However, this brings up  
> the question: If something acts exactly like an integer method-wise,  
> whats the benefit of explicitly calling to\_int? This seems like a non  
> duck-typey thing to do.

In the example with the roman numerals, you might not want to implement  
all the behavior of Numeric or Fixnum – it would make your class  
unnecessarily complex. Rather just have a #to\_int method that returned a  
normal integer, be that a Fixnum or another object responded to the same  
methods. In many cases, you have to return a Fixnum, or some methods  
will complain.

This approach means that you can give your roman numeral objects  
directly as arguments to methods. If they call #to\_int on the object  
before dealing with it, it’ll behave just as if it’s a Fixnum.

# doesn’t really have to be an integer,

# but what the hell…

def double(num)  
num.to\_int \* 2  
end

double(roman\_num)

Cheers,  
Daniel
