Case Expressions and Classes

(Daniel Schierbeck) #1

Could anyone explain to me why this isn't working?

  # returns 'no'
  case :foo.class
    when Symbol then
      puts 'yes'
    else
      puts 'no'
  end

.... when this does

  # returns 'yes'
  case :foo.class.object_id
    when Symbol.object_id then
      puts 'yes'
    else
       puts 'no'
  end

I'm puzzled...

Thank you in advance,
Daniel Schierbeck

(James Edward Gray II) #2

Cases use ===() to do the check in when. The ===() for class checks to see if the passed object is of that class. The object you are using in the case above is Symbol, which is an object of the class Class, not the class Symbol you are testing for.

Put another way, you're outsmarting Ruby's very intelligent case statement. Let it do all the work:

     # returns 'yes'
     case :foo
       when Symbol
         puts 'yes'
       else
         puts 'no'
     end

Hope that helps.

James Edward Gray II

···

On Aug 19, 2005, at 9:51 AM, Daniel Schierbeck wrote:

Could anyone explain to me why this isn't working?

    # returns 'no'
    case :foo.class
      when Symbol then
        puts 'yes'
      else
        puts 'no'
    end

(David A. Black) #3

Hi --

Could anyone explain to me why this isn't working?

  # returns 'no'
  case :foo.class
    when Symbol then
      puts 'yes'
    else
      puts 'no'
  end

.... when this does

  # returns 'yes'
  case :foo.class.object_id
    when Symbol.object_id then
      puts 'yes'
    else
     puts 'no'
  end

I'm puzzled...

:foo.class is Symbol. In your first case statement, you're asking
whether Symbol is an instance of... Symbol. It isn't: it's an
instance of Class.

What you want is:

   case :foo
   when Symbol # i.e., if an instance of Symbol

etc.

The second case statement gives you 'yes' because the numbers match,
and the way numbers get compared in case statements isn't affected by
where those numbers come from.

David

···

On Fri, 19 Aug 2005, Daniel Schierbeck wrote:

--
David A. Black
dblack@wobblini.net

(Patrick Fernie) #4

With the case...when construct, the class of the object is already
being checked. Therefore, your first form should be:
case :foo
when Symbol then
  puts 'yes'
else
  puts 'no'
end

By adding the .class to the :foo, the construct is actually checking
the class of :foo.class, which is Class, so you fall through to the
'no' case.

-Patrick

···

On 8/19/05, Daniel Schierbeck <daniel.schierbeck@gmail.com> wrote:

Could anyone explain to me why this isn't working?

        # returns 'no'
        case :foo.class
          when Symbol then
            puts 'yes'
          else
            puts 'no'
        end

.... when this does

        # returns 'yes'
        case :foo.class.object_id
          when Symbol.object_id then
            puts 'yes'
          else
           puts 'no'
        end

I'm puzzled...

Thank you in advance,
Daniel Schierbeck

(Gavin Kistner) #5

Case statements use ===, not == to compare the value against arguments. The Class#=== operator matches against the class of an object, so you want:

case :foo
     when Symbol then puts 'yes'
     else puts no
end

I know, it's sort of confusing. :expressionless:

···

On Aug 19, 2005, at 8:51 AM, Daniel Schierbeck wrote:

Could anyone explain to me why this isn't working?

    # returns 'no'
    case :foo.class
      when Symbol then
        puts 'yes'
      else
        puts 'no'
    end

(Ara.T.Howard) #6

case statements use the '===' operator. the '===' for classes is the same as
'is_a?' for classes. so writing

with case statements the obj of the statement is used as the argument for the
'===' operator of each case, so

   case obj
     when Foo
       ...
     when Bar
   end

is the same as

   if Foo === obj
     ...
   elsif Bar === obj
     ...
   end

and

   case string
     when %r/foo/
       ...
     when %r/bar/
   end

is the same as

   if %r/foo/ === string
     ...
   elsif %/bar/ === string
     ...
   end

so what you've written:

   case Symbol
     when Symbol
       'yes'
     else
       'no'
   end

is the same as

   if Symbol === Symbol
     'yes'
   else
     'no'
   end

so, '===', when applied to a class, tests if an object is an __instance__ of
that class. so

     String === 'a string' #=> true
     Array === [42] #=> true

therefore, you are asking if Symbol is an instance of a Symbol - which it is
not. it __is__ equalivalent to Symbol, but that would mean '==' and not
'==='.

case statements can also do this

   case obj
     when String, Fixnum, Array
     when File
     when %r/foo/, %r/bar/
     else
   end

where each element in the list applies '===' to the argument 'obj' to see when
line triggers - it's really powerful.

hth.

-a

···

On Fri, 19 Aug 2005, Daniel Schierbeck wrote:

Could anyone explain to me why this isn't working?

  # returns 'no'
  case :foo.class
    when Symbol then
      puts 'yes'
    else
      puts 'no'
  end

.... when this does

  # returns 'yes'
  case :foo.class.object_id
    when Symbol.object_id then
      puts 'yes'
    else
     puts 'no'
  end

I'm puzzled...

Thank you in advance,
Daniel Schierbeck

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

===============================================================================

(Daniel Schierbeck) #7

James Edward Gray II wrote:

···

On Aug 19, 2005, at 9:51 AM, Daniel Schierbeck wrote:

Could anyone explain to me why this isn't working?

    # returns 'no'
    case :foo.class
      when Symbol then
        puts 'yes'
      else
        puts 'no'
    end

Cases use ===() to do the check in when. The ===() for class checks to see if the passed object is of that class. The object you are using in the case above is Symbol, which is an object of the class Class, not the class Symbol you are testing for.

Put another way, you're outsmarting Ruby's very intelligent case statement. Let it do all the work:

    # returns 'yes'
    case :foo
      when Symbol
        puts 'yes'
      else
        puts 'no'
    end

Hope that helps.

James Edward Gray II

That worked like a charm! Thank you very much!

Daniel Schierbeck