determining whether an object is an immediate?

E

Eric Mahurin

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
 
T

Timothy Hunter

Eric said:
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
 
G

Gene Tani

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
 
E

Eric Mahurin

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 said:
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

=20
=20
=20


__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around=20
http://mail.yahoo.com=20
 
G

Gyoung-Yoon Noh

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 } } }
 
G

Gyoung-Yoon Noh

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 } } }

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]#=3D> false
 
R

Ryan Leavengood

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
 
R

Ryan Leavengood

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]#=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
 
P

Park Heesob

Hi,
----- Original Message -----
From: "Eric Mahurin" <[email protected]>
To: "ruby-talk ML" <[email protected]>
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
 
G

Gyoung-Yoon Noh

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.
 
T

Trans

Eric said:
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.
 
B

Brian Mitchell

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.
 
E

Eric Mahurin

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

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--
 
G

Gene Tani

################ 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)
 
G

Gene Tani

(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)
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top