In Ruby, why does inspect() print out some kind of object id which is different from what object_id() gives? - ruby

When the p function is used to print out an object, it may give an ID, and it is different from what object_id() gives. What is the reason for the different numbers?
Update: 0x4684abc is different from 36971870, which is 0x234255E
>> a = Point.new
=> #<Point:0x4684abc>
>> a.object_id
=> 36971870
>> a.__id__
=> 36971870
>> "%X" % a.object_id
=> "234255E"

The default implementation of inspect calls the default implementation of to_s, which just shows the hexadecimal value of the object directly, as seen in the Object#to_s docs (click on the method description to reveal the source).
Meanwhile the comments in the C source underlying the implementation of object_id shows that there are different “namespaces” for Ruby values and object ids, depending on the type of the object (e.g. the lowest bit seems to be zero for all but Fixnums). You can see that in Object#object_id docs (click to reveal the source).
From there we can see that in the “object id space” (returned by object_id) the ids of objects start from the second bit on the right (with the first bit being zero), but in “value space” (used by inspect) they start from the third bit on the right (with the first two bits zero). So, to convert the values from the “object id space” to the “value space”, we can shift the object_id to the left by one bit and get the same result that is shown by inspect:
> '%x' % (36971870 << 1)
=> "4684abc"
> a = Foo.new
=> #<Foo:0x5cfe4>
> '%x' % (a.object_id << 1)
=> "5cfe4"

0x234255E
=>36971870
It's not different, it's the hexadecimal representation of the memory address:-)

Related

Multiplying string by integer vs integer by string in ruby

I was playing around in irb, and noticed one cannot do
5 * "Hello".
Error
String can't be coerced into Fixnum
However "Hello"*5 provided "HelloHelloHelloHelloHello" as expected.
What is the exact reason for this? I've been looking around in the doc's and could not find the exact reason for this behavior. Is this something the designers of ruby decided?
Basically, you are asking "why is multiplication not commutative"? There are two possible answers for this. Or rather one answer with two layers.
The basic principle of OO is that everything happens as the result of one object sending a message to another object and that object responding to that message. This "messaging" metaphor is very important, because it explains a lot of things in OO. For example, if you send someone a message, all you can observe is what their response is. You don't know, and have no idea of finding out, what they did to come up with that response. They could have just handed out a pre-recorded response (reference an instance variable). They could have worked hard to construct a response (execute a method). They could have handed the message off to someone else (delegation). Or, they just don't understand the message you are sending them (NoMethodError).
Note that this means that the receiver of the message is in total control. The receiver can respond in any way it wishes. This makes message sending inherently non-commutative. Sending message foo to a passing b as an argument is fundamentally different from sending message foo to b passing a as an argument. In one case, it is a and only a that decides how to respond to the message, in the other case it is b and only b.
Making this commutative requires explicit cooperation between a and b. They must agree on a common protocol and adhere to that protocol.
In Ruby, binary operators are simply message sends to the left operand. So, it is solely the left operand that decides what to do.
So, in
'Hello' * 5
the message * is sent to the receiver 'Hello' with the argument 5. In fact, you can alternately write it like this if you want, which makes this fact more obvious:
'Hello'.*(5)
'Hello' gets to decide how it responds to that message.
Whereas in
5 * 'Hello'
it is 5 which gets to decide.
So, the first layer of the answer is: Message sending in OO is inherently non-commutative, there is no expectation of commutativity anyway.
But, now the question becomes, why don't we design in some commutativity? For example, one possible way would be to interpret binary operators not as message sends to one of the operands but instead message sends to some third object. E.g., we could interpret
5 * 'Hello'
as
*(5, 'Hello')
and
'Hello' * 5
as
*('Hello', 5)
i.e. as message sends to self. Now, the receiver is the same in both cases and the receiver can arrange for itself to treat the two cases identically and thus make * commutative.
Another, similar possibility would be to use some sort of shared context object, e.g. make
5 * 'Hello'
equivalent to
Operators.*(5, 'Hello')
In fact, in mathematics, the meaning of a symbol is often dependent on context, e.g. in ℤ, 2 / 3 is undefined, in ℚ, it is 2/3, and in IEEE754, it is something close to, but not exactly identical to 0.333…. Or, in ℤ, 2 * 3 is 6, but in ℤ|5, 2 * 3 is 1.
So, it would certainly make sense to do this. Alas, it isn't done.
Another possibility would be to have the two operands cooperate using a standard protocol. In fact, for arithmetic operations on Numerics, there actually is such a protocol! If a receiver doesn't know what to do with an operand, it can ask that operand to coerce itself, the receiver, or both to something the receiver does know how to handle.
Basically, the protocol goes like this:
you call 5 * 'Hello'
5 doesn't know how to handle 'Hello', so it asks 'Hello' for a coercion. …
… 5 calls 'Hello'.coerce(5)
'Hello' responds with a pair of objects [a, b] (as an Array) such that a * b has the desired result
5 calls a * b
One common trick is to simply implement coerce to flip the operands, so that when 5 retries the operation, 'Hello' will be the receiver:
class String
def coerce(other)
[self, other]
end
end
5 * 'Hello'
#=> 'HelloHelloHelloHelloHello'
Okay, OO is inherently non-commutative, but we can make it commutative using cooperation, so why isn't it done? I must admit, I don't have a clear-cut answer to this question, but I can offer two educated guesses:
coerce is specifically intended for numeric coercion in arithmetic operations. (Note the protocol is defined in Numeric.) A string is not a number, nor is string concatenation an arithmetic operation.
We just don't expect * to be commutative with wildly different types such as Integer and String.
Of course, just for fun, we can actually observe that there is a certain symmetry between Integers and Strings. In fact, you can implement a common version of Integer#* for both String and Integer arguments, and you will see that the only difference is in what we choose as the "zero" element:
class Integer
def *(other)
zero = case other
when Integer then 0
when String then ''
when Array then []
end
times.inject(zero) {|acc, _| acc + other }
end
end
5 * 6
#=> 30
5 * 'six'
#=> 'sixsixsixsixsix'
5 * [:six]
#=> [:six, :six, :six, :six, :six, :six]
The reason for this is, of course, that the set of strings with the concatenation operation and the empty string as the identity element form a monoid, just like arrays with concatenation and the empty array and just like integers with addition and zero. Since all three are monoids, and our "multiplication as repeated addition" only requires monoid operations and laws, it will work for all monoids.
Note: Python has an interesting twist on this double-dispatch idea. Just like in Ruby, if you write
a * b
Python will re-write that into a message send:
a.__mul__(b)
However, if a can't handle the operation, instead of cooperating with b, it cooperates with Python by returning NotImplemented. Now, Python will try with b, but with a slight twist: it will call
b.__rmul__(a)
This allows b to know that it was on the right side of the operator. It doesn't matter much for multiplication (because multiplication is (usually but not always, see e.g. matrix multiplication) commutative), but remember that operator symbols are distinct from their operations. So, the same operator symbol can be used for operations that are commutative and ones that are non-commutative. Example: + is used in Ruby for addition (2 + 3 == 3 + 2) and also for concatenation ('Hello' + 'World' != 'World' + 'Hello'). So, it is actually advantageous for an object to know whether it was the right or left operand.
This is because that operators are also methods(Well there are exceptions as Cary has listed in the comments which I wasn't aware of).
For example
array << 4 == array.<<4
array[2] == array.[](2)
array[2] ='x' == array.[] =(2,'x')
In your example:
5 * "Hello" => 5.*("Hello")
Meanwhile
"hello" *5 => 5.*("hello")
An integer cannot take that method with a string param
If you ever dabble around in python try 5*hello and hello*5, both work. Pretty interesting that ruby has this feature to be honest.
Well, as Muntasir Alam has already told that Fixnum does not has a method named * which takes a string as argument. So, 5*"Hello" produces that error.But, to have fun we can actually achieve 5*"Hello" this by adding that missing method to the Fixnum class.
class Fixnum # open the class
def * str # Override the *() method
if str.is_a? String # If argument is String
temp = ""
self.times do
temp << str
end
temp
else # If the argument is not String
mul = 0
self.times do
mul += str
end
mul
end
end
end
now
puts 5*"Hello" #=> HelloHelloHelloHelloHello
puts 4*5 #=> 20
puts 5*10.4 #=> 52.0
Well, that was just to show that the opposite is also possible. But that will bring a lot of overhead. I think we should avoid that at all cost.

How to unfreeze an object in Ruby?

In Ruby, there is Object#freeze, which prevents further modifications to the object:
class Kingdom
attr_accessor :weather_conditions
end
arendelle = Kingdom.new
arendelle.frozen? # => false
arendelle.weather_conditions = 'in deep, deep, deep, deep snow'
arendelle.freeze
arendelle.frozen? # => true
arendelle.weather_conditions = 'sun is shining'
# !> RuntimeError: can't modify frozen Kingdom
script = 'Do you want to build a snowman?'.freeze
script[/snowman/] = 'castle of ice'
# !> RuntimeError: can't modify frozen String
However, there is no Object#unfreeze. Is there a way to unfreeze a frozen kingdom?
Update: As of Ruby 2.7 this no longer works!
Yes and no. There isn't any direct way using the standard API. However, with some understanding of what #freeze? does, you can work around it. Note: everything here is implementation details of MRI's current version and might be subject to change.
Objects in CRuby are stored in a struct RVALUE.
Conveniently, the very first thing in the struct is VALUE flags;.
All Object#freeze does is set a flag, called FL_FREEZE, which is actually equal to RUBY_FL_FREEZE. RUBY_FL_FREEZE will basically be the 11th bit in the flags.
All you have to do to unfreeze the object is unset the 11th bit.
To do that, you could use Fiddle, which is part of the standard library and lets you tinker with the language on C level:
require 'fiddle'
class Object
def unfreeze
Fiddle::Pointer.new(object_id * 2)[1] &= ~(1 << 3)
end
end
Non-immediate value objects in Ruby are stored on address = their object_id * 2. Note that it's important to make the distinction so you would be aware that this wont let you unfreeze Fixnums for example.
Since we want to change the 11th bit, we have to work with the 3th bit of the second byte. Hence we access the second byte with [1].
~(1 << 3) shifts 1 three positions and then inverts the result. This way the only bit which is zero in the mask will be the third one and all other will be ones.
Finally, we just apply the mask with bitwise and (&=).
foo = 'A frozen string'.freeze
foo.frozen? # => true
foo.unfreeze
foo.frozen? # => false
foo[/ (?=frozen)/] = 'n un'
foo # => 'An unfrozen string'
No, according to the documentation for Object#freeze:
There is no way to unfreeze a frozen object.
The frozen state is stored within the object. Calling freeze sets the frozen state and thereby prevents further modification. This includes modifications to the object's frozen state.
Regarding your example, you could assign a new string instead:
script = 'Do you want to build a snowman?'
script.freeze
script = script.dup if script.frozen?
script[/snowman/] = 'castle of ice'
script #=> "Do you want to build a castle of ice?"
Ruby 2.3 introduced String#+#, so you can write +str instead of str.dup if str.frozen?
frozen_object = %w[hello world].freeze
frozen_object.concat(['and universe']) # FrozenError (can't modify frozen Array)
frozen_object.dup.concat(['and universe']) # ['hello', 'world', 'and universe']
As noted above copying the variable back into itself also effectively unfreezes the variable.
As noted this can be done using the .dup method:
var1 = var1.dup
This can also be achieved using:
var1 = Marshal.load(Marshal.dump(var1))
I have been using Marshal.load(Marshal.dump( ... )
I have not used .dup and only learned about it through this post.
I do not know what if any differences there are between Marshal.load(Marshal.dump( ... )
If they do the same thing or .dup is more powerful, then stylistically I like .dup better. .dup states what to do -- copy this thing, but it does not say how to do it, whereas Marshal.load(Marshal.dump( ... ) is not only excessively verbose, but states how to do the duplication -- I am not a fan of specifying the HOW part if the HOW part is irrelevant to me. I want to duplicate the value of the variable, I do not care how.

How to ask and validate a length from a `UI.Inputbox` field?

On SketchUp one can request user input using a dialog window created with the UI.Inputbox method. It is a basic task to ask for the dimension or length of some geometry the script will create afterwards.
Internally SketchUp uses Inches to define geometry. The user will give the answer in his/her localized dimension idiom: '1,5m' for 1.5 Meters. The built in SketchUp method .to_l converts strings to length. See https://github.com/thomthom/SketchUp-Units-and-Locale-Helper#sketchups-shortcomings for reference.
I'm asking the user for a length as a string from UI.Inputbox and then converting it to a length value using .to_l but if the user types an invalid value I don't know how check or how to handle the error.
As my localized length inputs have ',' as the decimal separation (in Portuguese it is 1,5m not 1.5m), I'm not willing to ask for a floating point value.
prompts = ['Length']
defaults = ['1,2']
inputs = UI.inputbox( prompts, defaults ,'Length Input')
inputs[0].to_l
#try inputs[0].to_f
How check the input string or catch .to_l failure?
This should work for you, but it might need to be fine-tuned depending on what you want each error case to do.
prompts = ['Length']
defaults = ['1,2']
inputs = UI.inputbox( prompts, defaults ,'Length Input')
Assuming the above, we can make a method to handle error cases for your input.
def parse_input(inputs)
input = normalize(inputs)
handle_error if input.empty?
input
end
def normalize(input)
input.gsub(/[a-zA-Z]/, "")
end
def handle_error
# you could raise an error or just return the default
end
When you parse the input, it attempts to 'normalize' it - meaning that it replaces commas with dots and then calls to_f. Since it looks like you're getting this as input from a field, inputs will always be a String, so there's no need to worry about handling other types. Sample output:
normalize('1,4') #=> '1.4'
normalize('2.6') #=> '2.6'
normalize('5a.2') #=> '5.2'
normalize('text') #=> ''
Now that the input is normalized, you can handle errors (which is basically when the normalized input is an empty string. What you want to do there is up to you and what works best in your specific case.
Finally the input is returned if there are no input errors.
I'm asking the user for a length as a string from UI.Inputbox and then
converting it to a length value using .to_l
The question is wrong, I mean, it is not a good idea to ask for a string and to try yourself to manage the complexities of localized float values. Don't do it!
Aks for a 'length' and SketchUp will take care of everything for you. Use .m and the user will be prompted a value in his local/chosen units. The resulting input will be in 'Length - internal units'.
prompts = ['Name', 'Width', 'Height']
defaults = ['My Own Square', 5.m, 2.m]
input = UI.inputbox( prompts, defaults, 'Create Square' )
# User enters Width: 300cm, Height 4
p input
# => ["My Own Square", 118.110236220472, 157.48031496063]
p input.map { |n| n.class }
# => [String, Length, Length]
p input.map { |n| n.to_s }
# => ["My Own Square", "3000mm", "4000mm"]
Source: ThomThom http://www.thomthom.net/thoughts/2012/08/dealing-with-units-in-sketchup/

Some `Fixnum` properties

I found the following features of Fixnum in doc.
Fixnum objects have immediate value. This means that when they are assigned or passed as parameters, the actual object is passed, rather than a reference to that object.
Can the same be shown in IRB? Hope then only it will be correctly understood by me?
Assignment does not alias Fixnum objects.
What does it actually then?
There is effectively only one Fixnum object instance for any given integer value, so, for example, you cannot add a singleton method to a Fixnum.
Couldn't understand the reason not to add the singleton method with Fixnum object instances.
I gave some try to the second point as below:
a = 1 # => 1
a.class # => Fixnum
b = a # => 1
b.class # => Fixnum
a == b # => true
a.equal? b # => true
a.object_id == b.object_id # => true
But still I am in confusion. Can anyone help me here to understand the core of those features please?
In Ruby, most objects require memory to store their class and instance variables. Once this memory is allocated, Ruby represents each object by this memory location. When the object is assigned to a variable or passed to a function, it is the location of this memory that is passed, not the data at this memory. Singleton methods make use of this. When you define a singleton method, Ruby silently replaces the objects class with a new singleton class. Because each object stores its class, Ruby can easily replace an object's class with a new class that implements the singleton methods (and inherits from the original class).
This is no longer true for objects that are immediate values: true, false, nil, all symbols, and integers that are small enough to fit within a Fixnum. Ruby does not allocate memory for instances of these objects, it does not internally represent the objects as a location in memory. Instead, it infers the instance of the object based on its internal representation. What this means is twofold:
The class of each object is no longer stored in memory at a particular location, and is instead implicitly determined by the type of immediate object. This is why Fixnums cannot have singleton methods.
Immediate objects with the same state (e.g., two Fixnums of integer 2378) are actually the same instance. This is because the instance is determined by this state.
To get a better sense of this, consider the following operations on a Fixnum:
>> x = 3 + 7
=> 10
>> x.object_id == 10.object_id
=> true
>> x.object_id == (15-5).object_id
=> true
Now, consider them using strings:
>> x = "a" + "b"
=> "ab"
>> x.object_id == "ab".object_id
=> false
>> x.object_id == "Xab"[1...3].object_id
=> false
>> x == "ab"
=> true
>> x == "Xab"[1...3]
=> true
The reason the object ids of the Fixnums are equal is that they're immediate objects with the same internal representation. The strings, on the other hand, exist in allocated memory. The object id of each string is the location of its object state in memory.
Some low-level information
To understand this, you have to understand how Ruby (at least 1.8 and 1.9) treat Fixnums internally. In Ruby, all objects are represented in C code by variables of type VALUE. Ruby imposes the following requirements for VALUE:
The type VALUE is is the smallest integer of sufficient size to hold a pointer. This means, in C, that sizeof(VALUE) == sizeof(void*).
Any non-immediate object must be aligned on a 4-byte boundary. This means that any object allocated by Ruby will have address 4*i for some integer i. This also means that all pointers have zero values in their two least significant bits.
The first requirement allows Ruby to store both pointers to objects and immediate values in a variable of type VALUE. The second requirement allows Ruby to detect Fixnum and Symbol objects based on the two least significant bits.
To make this more concrete, consider the internal binary representation of a Ruby object z, which we'll call Rz in a 32-bit architecture:
MSB LSB
3 2 1
1098 7654 3210 9876 5432 1098 7654 32 10
XXXX XXXX XXXX XXXX XXXX XXXX XXXX AB CD
Ruby then interprets Rz, the representation of z, as follows:
If D==1, then z is a Fixnum. The integer value of this Fixnum is stored in the upper 31 bits of the representation, and is recovered by performing an arithmetic right shift to recover the signed integer stored in these bits.
Three special representations are tested (all with D==0)
if Rz==0, then z is false
if Rz==2, then z is true
if Rz==4, then z is nil
If ABCD == 1110, then 'z' is a Symbol. The symbol is converted into a unique ID by right-shifting the eight least-significant bits (i.e., z>>8 in C). On 32-bit architectures, this allows 2^24 different IDs (over 10 million). On 64-bit architectures, this allows 2^48 different IDs.
Otherwise, Rz represents an address in memory for an instance of a Ruby object, and the type of z is determined by the class information at that location.
Well...
This is an internal implementation detail on MRI. You see, in Ruby (on the C side of things), all Ruby objects are a VALUE. In most cases, a VALUE is a pointer to an object living on the stack. But the immediate values (Fixnums, true, false, nil, and something else) live in the VALUE where a pointer to an object would usually live.
It makes the variable the exact same object. Now, I have no idea how this works internally, because it assigns it to the VALUE itself, but it does.
Because every time I use the number 1 in my program, I'm using the same object. So if I define a singleton method on 1, every place in my program, required programs, etc., will have that singleton method. And singleton methods are usually used for local monkeypatching. So, to prevent this, Ruby just doesn't let you.

Odd Ruby Behaviour

Consider the following Ruby code:
a = ["x"] * 3 # or a = Array.new(3, "x")
a[0].insert(0, "a")
a.each {|i| puts i}
I would expect the output to be ax, x, x (on new lines of course). However, with Ruby 1.9.1 the output is ax, ax, ax. What's going on? I've narrowed the problem down to the way the array a is defined. If I explicitly write out
a = ["x", "x", "x"]
then the code works as expected, but either version in the original code gives me this unexpected behaviour. It appears that the */initializer means the copies are actually references to the same copy of the string "x". However, if instead of the insert command I write
a[0] = "a" + a[0]
Then I get the desired output. Is this a bug, or is there some feature at work which I'm not understanding?
The documentation to Array.new(size=0, obj=nil):
... it is created with size copies of obj (that is, size references to the same obj).
and Array * int:
... returns a new array built by concatenating the int copies of self
So in both of the forms you're surprised by, you end up with three references to the same "x" object, just as you figured out. I'd say you might argue about the design decision, but it's a documented intentional behavior, not a bug.
The best way I know to get the behavior you want without manually writing the array literal (["x", "x", "x"]) is
a = Array.new(3) {"x"}
Or course, with just three elements, it doesn't much matter, but with anything much bigger, this form comes in handy.
In short, although "x" is just a literal, it is an object. You use ["x'] * 3 so a is containing 3 same object. You insert 'a' to one of them, they will be all changed.

Resources