[Q] case based on object class

Hello everyone,

I wonder if there is a more elegant/efficient way to rewrite
the case structure in the following code snippet:

def myfunc(obj)
         case obj.class.name
                 when Fixnum.name
                         puts :Fixnum
                 when Float.name
                         puts :Float
                 ...
                 default
                         puts :Object
         end
end

thanks in advance,

George Moschovitis

···

--
www.navel.gr | tel: +30 2106898050 | fax: +30 2106898437

Navel does not accept liability for any errors, viruses or omissions in the contents of this message. The full corporate policy is available on our site.

have fun: www.joy.gr

George Moschovitis wrote:

Hello everyone,

I wonder if there is a more elegant/efficient way to rewrite
the case structure in the following code snippet:

def myfunc(obj)
        case obj.class.name
                when Fixnum.name
                        puts :Fixnum
                when Float.name
                        puts :Float
                ...
                default
                        puts :Object
        end
end

case obj
when Fixnum
   puts obj.class.to_s.to_sym
when Float
   ...
else
   puts :Object
end

Regards,

   Michael

George Moschovitis wrote:

Hello everyone,

I wonder if there is a more elegant/efficient way to rewrite
the case structure in the following code snippet:

Certainly... see below.

def myfunc(obj)
        case obj
                when Fixnum
                        puts :Fixnum
                when Float
                        puts :Float
                ...
                default
                        puts :Object
        end
end

This works because case invokes ===, which takes a minute
or three to understand. :slight_smile:

Hal

PS - In my Mozilla, your font is microscopic. :0

H

This works because case invokes ===, which takes a minute
or three to understand. :slight_smile:

Thank you Hal and Michael!

Ruby can be VERY surprising after all. After the initial shock it
feels natural though.

-g.

···

--
www.navel.gr | tel: +30 2106898050 | fax: +30 2106898437

Navel does not accept liability for any errors, viruses or omissions in the contents of this message. The full corporate policy is available on our site.

have fun: www.joy.gr

Hmm my example was wrong, what I wanted to write is:

def myfunc(klass)
         case klass.name
                 when Fixnum.name
                         puts :Fixnum
                 when Float.name
                         puts :Float
                 ...
                 default
                         puts :Object
         end
end

myfunc(obj.class)

Now this === doesnt work :frowning: I am sure the solution is obvious,
but I would appreciate some help.

regards,
George Moschovitis

···

--
www.navel.gr | tel: +30 2106898050 | fax: +30 2106898437

Navel does not accept liability for any errors, viruses or omissions in the contents of this message. The full corporate policy is available on our site.

have fun: www.joy.gr

George Moschovitis wrote:

Hmm my example was wrong, what I wanted to write is:

def myfunc(klass)
        case klass.name
                when Fixnum.name
                        puts :Fixnum
                when Float.name
                        puts :Float
                ...
                default
                        puts :Object
        end
end

myfunc(obj.class)

Now this === doesnt work :frowning: I am sure the solution is obvious,
but I would appreciate some help.

I am not sure what you want to do... do you want to separate these
things by class and print out the corresponding symbol?

Anyhow, I tried your code and it worked fine for me. I substituted
4 for obj and commented the ... of course.

What's the problem about?

Hal

This doesn't work?

    def myfunc(klass)
case klass
when Fixnum
     puts :Fixnum
         when Float
puts :Float
         ...
default
puts :Object
     end
    end

BTW the method being used by case in the above is Class#===, to be more exact
it is calling Fixnum#=== and Float#===

T.

···

On Monday 11 October 2004 06:04 am, George Moschovitis wrote:

def myfunc(klass)
case klass.name
when Fixnum.name
puts :Fixnum
when Float.name
puts :Float
...
default
puts :Object
end
end

Hal Fulton wrote:

Anyhow, I tried your code and it worked fine for me. I substituted
4 for obj and commented the ... of course.

Also, what's this 'default' thing? I'm surprised it didn't give a
syntax error... 'else' is the thing.

I guess it's interpreting that as a method call but you're never
reaching it.

Hal

I am not sure what you want to do... do you want to separate these
things by class and print out the corresponding symbol?

i want to execute different code depending on the klass (Class) object
given to the method.

Anyhow, I tried your code and it worked fine for me. I substituted
4 for obj and commented the ... of course.

the code works, I am wondering if there is a more elegant/efficient
way to write it.

-g.

···

--
www.navel.gr | tel: +30 2106898050 | fax: +30 2106898437

Navel does not accept liability for any errors, viruses or omissions in the contents of this message. The full corporate policy is available on our site.

have fun: www.joy.gr

How about

case klass.name.to_sym
  when :Fixnum
    ...

martin

···

Hal Fulton <hal9000@hypermetrics.com> wrote:

George Moschovitis wrote:
> Hmm my example was wrong, what I wanted to write is:
>
> def myfunc(klass)
> case klass.name
> when Fixnum.name
> puts :Fixnum

George Moschovitis wrote:

the code works, I am wondering if there is a more elegant/efficient
way to write it.

Well, I'd wonder why you're testing the class instead of the
object.

   def myfunc(obj)
     case obj
       when Fixnum
         # ...
       when Float
         # ...
       else
         # ...
     end
   end

  myfunc(some_obj)

This seems better to me...

Hal

Also, what's this 'default' thing? I'm surprised it didn't give a

hmm that was an error, I thought I was writing C or something.
it was pseudocode anyway, just to illustrate my question...

-g.

···

--
www.navel.gr | tel: +30 2106898050 | fax: +30 2106898437

Navel does not accept liability for any errors, viruses or omissions in the contents of this message. The full corporate policy is available on our site.

have fun: www.joy.gr

"George Moschovitis" <gm@navel.gr> schrieb im Newsbeitrag
news:ckdn7c$2eim$1@ulysses.noc.ntua.gr...

> I am not sure what you want to do... do you want to separate these
> things by class and print out the corresponding symbol?

i want to execute different code depending on the klass (Class) object
given to the method.

> Anyhow, I tried your code and it worked fine for me. I substituted
> 4 for obj and commented the ... of course.

the code works, I am wondering if there is a more elegant/efficient
way to write it.

The OO way is to use a mapping IMHO:

ACTION_MAPPING = {
  Fixnum => lambda { puts "Fixnum" },
  Float => lambda { puts "Float" },
  String => lambda { puts "String" },
}

def myfunc(klass)
  code = ACTION_MAPPING[klass]
  raise ArgumentError, "Klass not found: #{klass}" unless code
  code.call
end

You can even define a block for the error as default effectively rendering
the method a one liner like this:

ACTION_MAPPING = Hash.new( lambda { raise ArgumentError, "Klass not
found" } ).update(
  Fixnum => lambda { puts "Fixnum" },
  Float => lambda { puts "Float" },
  String => lambda { puts "String" }
)

def myfunc(klass) ACTION_MAPPING[klass].call end

Kind regards

    robert

"Robert Klemme" <bob.news@gmx.net> schrieb im Newsbeitrag
news:2sv8kcF1q3732U1@uni-berlin.de...

"George Moschovitis" <gm@navel.gr> schrieb im Newsbeitrag
news:ckdn7c$2eim$1@ulysses.noc.ntua.gr...
> > I am not sure what you want to do... do you want to separate these
> > things by class and print out the corresponding symbol?
>
> i want to execute different code depending on the klass (Class) object
> given to the method.
>
> > Anyhow, I tried your code and it worked fine for me. I substituted
> > 4 for obj and commented the ... of course.
>
> the code works, I am wondering if there is a more elegant/efficient
> way to write it.

The OO way is to use a mapping IMHO:

I forgot to mention that this is also more efficient if you have many
classes.

ACTION_MAPPING = {
  Fixnum => lambda { puts "Fixnum" },
  Float => lambda { puts "Float" },
  String => lambda { puts "String" },
}

def myfunc(klass)
  code = ACTION_MAPPING[klass]
  raise ArgumentError, "Klass not found: #{klass}" unless code
  code.call
end

You can even define a block for the error as default effectively

rendering

the method a one liner like this:

ACTION_MAPPING = Hash.new( lambda { raise ArgumentError, "Klass not
found" } ).update(
  Fixnum => lambda { puts "Fixnum" },
  Float => lambda { puts "Float" },
  String => lambda { puts "String" }
)

def myfunc(klass) ACTION_MAPPING[klass].call end

And then there is also the option to define those methods as singleton
methods of the classes although I recommend to do this *only* if the
functionality is general enough and has to do with the class more than
with your app.

Kind regards

    robert