determining whether an object is an immediate?

Discussion in 'Ruby' started by Eric Mahurin, Oct 29, 2005.

  1. Eric Mahurin

    Eric Mahurin Guest

    This is be best I could come up with for determining whether an
    object is an immediate (Fixnum, Symbol, false, true, nil,
    others?):

    begin
    obj.clone
    # clone worked - not an immediate
    rescue TypeError
    # clone failed - immediate
    end

    Anybody have a better way? If the above is the best, seems
    like an Object#immediate? would be nice to have.




    =09
    __________________________________=20
    Yahoo! FareChase: Search multiple travel sites in one click.
    http://farechase.yahoo.com
     
    Eric Mahurin, Oct 29, 2005
    #1
    1. Advertising

  2. Eric Mahurin wrote:
    > This is be best I could come up with for determining whether an
    > object is an immediate (Fixnum, Symbol, false, true, nil,
    > others?):
    >
    > begin
    > obj.clone
    > # clone worked - not an immediate
    > rescue TypeError
    > # clone failed - immediate
    > end
    >
    > Anybody have a better way? If the above is the best, seems
    > like an Object#immediate? would be nice to have.
    >

    I seem to remember that begin/rescue is extremely slow, so since we know
    up front what all the immediate classes are I guessed that it would be
    faster just to test for them in a case expression. I put together a
    benchmark test that confirms my suspicion. Results first, then the test.
    I ran the test on my Powerbook.

    me$ ruby test.rb
    user system total real
    rescue 2.040000 0.130000 2.170000 ( 2.527118)
    case 0.220000 0.010000 0.230000 ( 0.240941)

    Here's the test code. The OBJECTS array contains 5 immediate objects and
    5 non-immediate objects. Of course, with the "rescue" approach you get
    a clone of the non-immediate object and in the "case" approach you
    don't, but I'm assuming that you don't need the clone.

    require 'benchmark'
    include Benchmark

    OBJECTS = [1, [], :sym, "astring", true, {}, false, 1..3, nil, /x/]
    ITERATIONS = 10000

    bm(2) do |x|
    x.report("rescue") do
    ITERATIONS.times do
    OBJECTS.each do |obj|
    begin
    obj.clone
    rescue
    # nothing
    end
    end
    end
    end

    x.report("case ") do
    ITERATIONS.times do
    OBJECTS.each do |obj|
    case obj
    when Fixnum, Symbol, TrueClass, FalseClass, NilClass
    # nothing
    else
    # nothing
    end
    end
    end
    end

    end
     
    Timothy Hunter, Oct 29, 2005
    #2
    1. Advertising

  3. Eric Mahurin

    Gene Tani Guest

    you think #clone is slow, try (you could test for adding singleton
    methods, that would be even slower!):

    + x.report("objSpace ") do
    + ITERATIONS.times do
    + OBJECTS.each do |obj|
    + begin
    + if ObjectSpace.include?(obj)
    + # nothin
    + end
    + rescue TypeError
    + # noting
    + end
    + end
    + end
    + end

    Timothy Hunter wrote:
    > Eric Mahurin wrote:
    > > This is be best I could come up with for determining whether an
    > > object is an immediate (Fixnum, Symbol, false, true, nil,
    > > others?):
    > >
     
    Gene Tani, Oct 30, 2005
    #3
  4. Eric Mahurin

    Eric Mahurin Guest

    It is slow, but this is probably one of the better definitions
    of what an immediate is - whether it exists in ObjectSpace or
    not.

    Here's another solution:

    class Object; def immediate?;false;end;end
    class Fixnum; def immediate?;true; end;end
    class Symbol; def immediate?;true; end;end
    class NilClass; def immediate?;true; end;end
    class FalseClass;def immediate?;true; end;end
    class TrueClass; def immediate?;true; end;end


    --- Gene Tani <> wrote:

    > you think #clone is slow, try (you could test for adding
    > singleton
    > methods, that would be even slower!):
    >=20
    > + x.report("objSpace ") do
    > + ITERATIONS.times do
    > + OBJECTS.each do |obj|
    > + begin
    > + if ObjectSpace.include?(obj)
    > + # nothin
    > + end
    > + rescue TypeError
    > + # noting
    > + end
    > + end
    > + end
    > + end
    >=20
    > Timothy Hunter wrote:
    > > Eric Mahurin wrote:
    > > > This is be best I could come up with for determining

    > whether an
    > > > object is an immediate (Fixnum, Symbol, false, true, nil,
    > > > others?):
    > > >

    >=20
    >=20
    >=20



    __________________________________________________
    Do You Yahoo!?
    Tired of spam? Yahoo! Mail has the best spam protection around=20
    http://mail.yahoo.com=20
     
    Eric Mahurin, Oct 30, 2005
    #4
  5. On 10/31/05, Eric Mahurin <> wrote:
    > It is slow, but this is probably one of the better definitions
    > of what an immediate is - whether it exists in ObjectSpace or
    > not.
    >
    > Here's another solution:
    >
    > class Object; def immediate?;false;end;end
    > class Fixnum; def immediate?;true; end;end
    > class Symbol; def immediate?;true; end;end
    > class NilClass; def immediate?;true; end;end
    > class FalseClass;def immediate?;true; end;end
    > class TrueClass; def immediate?;true; end;end
    >


    Here is one-line version:

    [Object, Fixnum, Symbol, NilClass, FalseClass, TrueClass].each { |c|
    c.instance_eval { define_method:)immediate?) { true } } }

    --
    http://nohmad.sub-port.net
     
    Gyoung-Yoon Noh, Oct 31, 2005
    #5
  6. On 10/31/05, Gyoung-Yoon Noh <> wrote:
    > On 10/31/05, Eric Mahurin <> wrote:
    > > It is slow, but this is probably one of the better definitions
    > > of what an immediate is - whether it exists in ObjectSpace or
    > > not.
    > >
    > > Here's another solution:
    > >
    > > class Object; def immediate?;false;end;end
    > > class Fixnum; def immediate?;true; end;end
    > > class Symbol; def immediate?;true; end;end
    > > class NilClass; def immediate?;true; end;end
    > > class FalseClass;def immediate?;true; end;end
    > > class TrueClass; def immediate?;true; end;end
    > >

    >
    > Here is one-line version:
    >
    > [Object, Fixnum, Symbol, NilClass, FalseClass, TrueClass].each { |c|
    > c.instance_eval { define_method:)immediate?) { true } } }
    >
    > --
    > http://nohmad.sub-port.net
    >
    >


    Ouch, except Object:

    >> [Object, Fixnum, Symbol, NilClass, FalseClass, TrueClass].each {

    |c| c.instance_eval { define_method:)immediate?) { (Object =3D=3D self) ?
    false : true } } }
    #=3D> [Object, Fixnum, Symbol, NilClass, FalseClass, TrueClass]
    >> Fixnum.immediate?

    #=3D> true
    >> Object.immediate?

    #=3D> false

    --
    http://nohmad.sub-port.net
     
    Gyoung-Yoon Noh, Oct 31, 2005
    #6
  7. On 10/30/05, Gyoung-Yoon Noh <> wrote:
    >
    > Here is one-line version:
    >
    > [Object, Fixnum, Symbol, NilClass, FalseClass, TrueClass].each { |c|
    > c.instance_eval { define_method:)immediate?) { true } } }


    Interesting, except the Object version needs to return false:

    [Object, Fixnum, Symbol, NilClass, FalseClass, TrueClass].each { |c|
    c.instance_eval { define_method:)immediate?) { not c=3D=3DObject } } }

    Ryan
     
    Ryan Leavengood, Oct 31, 2005
    #7
  8. On 10/30/05, Gyoung-Yoon Noh <> wrote:
    >
    > Ouch, except Object:
    >
    > >> [Object, Fixnum, Symbol, NilClass, FalseClass, TrueClass].each {

    > |c| c.instance_eval { define_method:)immediate?) { (Object =3D=3D self) ?
    > false : true } } }
    > #=3D> [Object, Fixnum, Symbol, NilClass, FalseClass, TrueClass]
    > >> Fixnum.immediate?

    > #=3D> true
    > >> Object.immediate?

    > #=3D> false


    But also:

    irb(main):007:0> 'string'.immediate?
    =3D> true
    irb(main):008:0> [].immediate?
    =3D> true
    irb(main):009:0> Array.immediate?
    =3D> true

    Yours returns true for everything except Object. The other version I
    posted is correct.

    Ryan
     
    Ryan Leavengood, Oct 31, 2005
    #8
  9. Eric Mahurin

    Park Heesob Guest

    Hi,
    ----- Original Message -----
    From: "Eric Mahurin" <>
    To: "ruby-talk ML" <>
    Sent: Monday, October 31, 2005 12:57 AM
    Subject: Re: determining whether an object is an immediate?


    > It is slow, but this is probably one of the better definitions
    > of what an immediate is - whether it exists in ObjectSpace or
    > not.
    >
    > Here's another solution:
    >
    > class Object; def immediate?;false;end;end
    > class Fixnum; def immediate?;true; end;end
    > class Symbol; def immediate?;true; end;end
    > class NilClass; def immediate?;true; end;end
    > class FalseClass;def immediate?;true; end;end
    > class TrueClass; def immediate?;true; end;end
    >

    This would be better:

    class Object
    def immediate?
    [Fixnum, Symbol, NilClass, FalseClass, TrueClass].include?(self.class)
    end
    end

    Regards,

    Park Heesob
     
    Park Heesob, Oct 31, 2005
    #9
  10. On 10/31/05, Ryan Leavengood <> wrote:
    > On 10/30/05, Gyoung-Yoon Noh <> wrote:
    > >
    > > Ouch, except Object:
    > >
    > > >> [Object, Fixnum, Symbol, NilClass, FalseClass, TrueClass].each {

    > > |c| c.instance_eval { define_method:)immediate?) { (Object =3D=3D self)=

    ?
    > > false : true } } }
    > > #=3D> [Object, Fixnum, Symbol, NilClass, FalseClass, TrueClass]
    > > >> Fixnum.immediate?

    > > #=3D> true
    > > >> Object.immediate?

    > > #=3D> false

    >
    > But also:
    >
    > irb(main):007:0> 'string'.immediate?
    > =3D> true
    > irb(main):008:0> [].immediate?
    > =3D> true
    > irb(main):009:0> Array.immediate?
    > =3D> true
    >
    > Yours returns true for everything except Object. The other version I
    > posted is correct.
    >
    > Ryan
    >
    >


    Right. 'self' should not be there. Thanks for correcting.

    --
    http://nohmad.sub-port.net
     
    Gyoung-Yoon Noh, Oct 31, 2005
    #10
  11. Eric Mahurin

    Trans Guest

    Eric Mahurin wrote:
    > This is be best I could come up with for determining whether an
    > object is an immediate (Fixnum, Symbol, false, true, nil,
    > others?):
    >
    > begin
    > obj.clone
    > # clone worked - not an immediate
    > rescue TypeError
    > # clone failed - immediate
    > end
    >
    > Anybody have a better way? If the above is the best, seems
    > like an Object#immediate? would be nice to have.


    I wonder why you need this. I suspect becuase you're using #clone in a
    general situation and want to test to make sure before doing so?
    Perhaps not. But in either case, I'm not sure why #clone (or #dup) just
    doesn't return self for these. I mean if they are immediate and hence
    there is but "one", then why isn't the one a satisfactory clone? Is
    there a good reason not to do this?

    Thanks,
    T.
     
    Trans, Oct 31, 2005
    #11
  12. On 10/29/05, Eric Mahurin <> wrote:
    > This is be best I could come up with for determining whether an
    > object is an immediate (Fixnum, Symbol, false, true, nil,
    > others?):
    >
    > begin
    > obj.clone
    > # clone worked - not an immediate
    > rescue TypeError
    > # clone failed - immediate
    > end
    >
    > Anybody have a better way? If the above is the best, seems
    > like an Object#immediate? would be nice to have.
    >


    The clone test does not work. Reason? There are plenty of
    non-immediate objects that won't clone like Float and Bignum
    instances. One test you could use is the singleton class:

    # Should raise a TypeError
    class << :immediate_object; end

    Of course immediate object could also be found missing from
    ObjectSpace, but I would imagine that test to be very slow.

    May I ask why you need to know the immediacy of an object?

    Brian.
     
    Brian Mitchell, Oct 31, 2005
    #12
  13. Eric Mahurin

    Eric Mahurin Guest

    ------=_Part_18986_12013326.1130758321505
    Content-Type: text/plain; charset=ISO-8859-1
    Content-Transfer-Encoding: quoted-printable
    Content-Disposition: inline

    On 10/31/05, Brian Mitchell <> wrote:

    > The clone test does not work. Reason? There are plenty of
    > non-immediate objects that won't clone like Float and Bignum
    > instances.



    Didn't notice that. I wonder why they didn't make this work. If it were up
    to me, I would make all immutable objects (including immediate objects)
    return self for clone.

    One test you could use is the singleton class:
    >
    > # Should raise a TypeError
    > class << :immediate_object; end



    I thought of that one previously too. The problem with this one is that for
    non-immediates, it will create singleton/meta classes for them when I don't
    need them. Maybe not that big a deal.

    Of course immediate object could also be found missing from
    > ObjectSpace, but I would imagine that test to be very slow.



    Probably the best test for now, but slow.

    May I ask why you need to know the immediacy of an object?
    >


    Performance. I don't really "need" to know - since this is an optimization.
    I'm doing some code generation (parser generator). When I'm given an
    immediate object instead of storing it in a variable and having the code us=
    e
    the variable, I want immediates to appear directly in the code (because
    there is no object creation penalty and I know it is immutable). My
    generated code doesn't reassign these variables (but it may modify the
    objects) so this works.

    Looking at the C code (ruby.h: SPECIAL_CONST_P), another option would be
    this:

    id =3D obj.__id__
    (id&3).nonzero? || (id&~4).zero?

    As long as ruby continues to encode immediates as it does now (can add
    more), this should work.

    ------=_Part_18986_12013326.1130758321505--
     
    Eric Mahurin, Oct 31, 2005
    #13
  14. Eric Mahurin

    Gene Tani Guest

    ################ benchmark, round 2
    OBJECTS = [1, 3.14159, [], :sym, "astring", true, {}, false, 1..3, nil,
    /x/]
    ITERATIONS = 10000 ## change
    bm(2) do |x|
    x.report("VClass ") do
    ITERATIONS.times do
    OBJECTS.each do |obj|
    begin
    class<<obj; end
    rescue TypeError
    # nothing
    end; end; end; end
    x.report("=== ") do
    ITERATIONS.times do
    OBJECTS.each do |obj|
    case obj
    when Fixnum, Symbol, TrueClass,
    FalseClass, NilClass
    # nothing
    else
    # nothing
    end; end; end; end
    x.report("objSpac") do
    ITERATIONS.times do
    OBJECTS.each do |obj|
    begin
    if ObjectSpace.include?(obj)
    # nothin
    end
    rescue TypeError
    # noting
    end; end; end;end
    end
    ######################
    user system total real
    VClass 0.937000 0.000000 0.937000 ( 0.937000)
    === 0.219000 0.000000 0.219000 ( 0.219000)
    objSpac 4.734000 0.000000 4.734000 ( 4.734000)


    Eric Mahurin wrote:
    > On 10/31/05, Brian Mitchell <> wrote:
    >
    > > The clone test does not work. Reason? There are plenty of
    > > non-immediate objects that won't clone like Float and Bignum
    > > instances.

    >
    >
    > Didn't notice that. I wonder why they didn't make this work. If it were up
    > to me, I would make all immutable objects (including immediate objects)
    > return self for clone.
    >
    > One test you could use is the singleton class:
    > >
    > > # Should raise a TypeError
    > > class << :immediate_object; end

    >
    >
    > I thought of that one previously too. The problem with this one is that for
    > non-immediates, it will create singleton/meta classes for them when I don't
    > need them. Maybe not that big a deal.
    >
    > Of course immediate object could also be found missing from
    > > ObjectSpace, but I would imagine that test to be very slow.

    >
    >
    > Probably the best test for now, but slow.
    >
    > May I ask why you need to know the immediacy of an object?
    > >

    >
    > Performance. I don't really "need" to know - since this is an optimization.
    > I'm doing some code generation (parser generator). When I'm given an
    > immediate object instead of storing it in a variable and having the code use
    > the variable, I want immediates to appear directly in the code (because
    > there is no object creation penalty and I know it is immutable). My
    > generated code doesn't reassign these variables (but it may modify the
    > objects) so this works.
    >
    > Looking at the C code (ruby.h: SPECIAL_CONST_P), another option would be
    > this:
    >
    > id = obj.__id__
    > (id&3).nonzero? || (id&~4).zero?
    >
    > As long as ruby continues to encode immediates as it does now (can add
    > more), this should work.
     
    Gene Tani, Oct 31, 2005
    #14
  15. Eric Mahurin

    Gene Tani Guest

    I'm confused, don't you need to only check that least signif. bit is 1,
    whereas #zero? and #nonzero? look at everything except LSB on a Fixnum,
    once they've figured out whether object is Fixnum, Float or Bignum?

    Also, i noticed that python people noticed about tagged integers:
    http://mail.python.org/pipermail/python-dev/2004-July/046139.html

    Eric Mahurin wrote:

    > Looking at the C code (ruby.h: SPECIAL_CONST_P), another option would be
    > this:
    >
    > id = obj.__id__
    > (id&3).nonzero? || (id&~4).zero?
    >
    > As long as ruby continues to encode immediates as it does now (can add
    > more), this should work.
     
    Gene Tani, Oct 31, 2005
    #15
  16. Eric Mahurin

    Gene Tani Guest

    (pls ignore prior 2 posts, I'm still mulling over how __id__'s work for
    immed. values )
    ############## benchmark round 3
    OBJECTS = [1, 3.14159, [], :sym, "astring", true, {}, false, 1..3, nil,
    /x/]
    ITERATIONS = 10000
    IMMED_CLASSES=[Fixnum, Symbol, TrueClass, FalseClass, NilClass]
    bm(2) do |x|
    x.report("VClass ") do
    ITERATIONS.times do
    OBJECTS.each do |obj|
    begin
    class<<obj; end
    rescue TypeError
    # nothing
    end; end; end; end
    x.report("=== ") do
    ITERATIONS.times do
    OBJECTS.each do |obj|
    if obj=== IMMED_CLASSES
    # nothing
    else
    # nothing
    end; end; end; end
    x.report("===2 ") do
    ITERATIONS.times do
    OBJECTS.each do |obj|
    if IMMED_CLASSES===obj
    # nothing
    else
    # nothing
    end; end; end; end
    x.report("cl_incl") do
    ITERATIONS.times do
    OBJECTS.each do |obj|
    if IMMED_CLASSES.include?(obj.class)
    # nothing

    else
    # nothing

    end; end; end; end

    x.report("objSpac") do
    ITERATIONS.times do
    OBJECTS.each do |obj|
    begin
    if ObjectSpace.include?(obj)
    # nothin
    end
    rescue TypeError
    # noting
    end; end; end;end
    end
    ######################
    WinXP, 1.8.2 from 1-click installer, cut/pasted out of Komodo 3.5 alpha

    user system total real
    VClass 0.922000 0.000000 0.922000 ( 0.922000)
    === 0.672000 0.000000 0.672000 ( 0.672000)
    ===2 0.219000 0.000000 0.219000 ( 0.219000)
    cl_incl 0.187000 0.000000 0.187000 ( 0.187000)
    objSpac 4.453000 0.000000 4.453000 ( 4.453000)
    Gene Tani wrote:
    > I'm confused,
     
    Gene Tani, Oct 31, 2005
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. news.amnet.net.au

    Determining whether String Array is empty

    news.amnet.net.au, Sep 7, 2004, in forum: Java
    Replies:
    5
    Views:
    28,107
    Mark Wright
    Sep 8, 2004
  2. BigMan
    Replies:
    8
    Views:
    356
    BigMan
    Feb 17, 2005
  3. Nathan Sokalski
    Replies:
    5
    Views:
    3,027
    Nathan Sokalski
    May 21, 2006
  4. Dfenestr8
    Replies:
    3
    Views:
    381
    Scott David Daniels
    Oct 8, 2004
  5. Howard Gardner
    Replies:
    17
    Views:
    527
    Howard Gardner
    Apr 25, 2006
Loading...

Share This Page