CORE - Literal Instantiation breaks Object Model

class String
alias_method :orig_initialize, :initialize
def initialize(val)
orig_initialize “OBSERVED: " + val
end
def my_method_test
print self.inspect, " test\n”
end
end

oo_string = String.new(“The OO String”)
li_string = “The Literal String”

print "Class: ", oo_string.class, " - content: ", oo_string, “\n”
print "Class: ", li_string.class, " - content: ", li_string, “\n”
oo_string.my_method_test
li_string.my_method_test

#OUTPUT
#=> Class: String - content: OBSERVED: The OO String
#=> Class: String - content: The Literal String
#=> “OBSERVED: The OO String” test
#=> “The Literal String” test

The behaviour of the class String has been altered, whilst using the
standard mechanisms of the Object Model.

To my huge surprise, although the li_string has been instantiated as
an object of class String, the new initialize method was not called.

This is essentially a defect, as the consistency of the Object Model
breaks.

The statement “Everything is an Object” becomes invalid, because e.g.
a string object instantiated from a literal behaves differently that a
string object instantiated normally via new() (although they share the
same class, and thus should behave the same).

My understanding is, that this is a know-issue and a trade-off due to
performance issues.

The questions are:

b) Is there any way to track (intercept) the instantiation of objects
(especially those instantiated from literals)

  1. without a C-level extension
  2. with a C-level extension

The interception can be post instantiation.

Underlying Requirement:

Ability to track instantiation of every object within the system.

.

Hi,

In message “Re: CORE - Literal Instantiation breaks Object Model”
on Fri, 10 Jun 2011 03:40:27 +0900, Ilias L.
[email protected] writes:

|The behaviour of the class String has been altered, whilst using the
|standard mechanisms of the Object Model.
|
|To my huge surprise, although the li_string has been instantiated as
|an object of class String, the new initialize method was not called.
|
|This is essentially a defect, as the consistency of the Object Model
|breaks.

You don’t have to teach me about Ruby’s object model. String objects
for literals are already created in the compile time, which is far
before you redefine the initialize method. The individual string
objects from literals are just copy of the already allocated and
initialized objects. The whole purpose of the initialize method is to
initialize newly created objects, as the name suggests. I don’t feel
any need to call the (redefined) initialize method for string
literals, that already initialized at the compile time. Even if you
can use it to track object creation, it’s only a side-effect. I am
not going to change the language (or its object model) to fit your
purpose better.

In general, if you want a perfect language that satisfies every random
ideas popping in your mind, you’d better design your own language,
rather than trying to hijacking existing one.

|The questions are:
|
|b) Is there any way to track (intercept) the instantiation of objects
|(especially those instantiated from literals)
| 1) without a C-level extension
| 2) with a C-level extension

If you don’t care about performance, you can investigate
ObjectSpace#each_object. Note that JRuby turns off the method by
default for performance reason. If you care about performance, I am
afraid that you have to modify the interpreter itself.

          matz.

On Thursday, June 09, 2011 05:30:43 PM Yukihiro M. wrote:

default for performance reason. If you care about performance, I am
afraid that you have to modify the interpreter itself.

Even this has limitations.
A few things that aren’t in ObjectSpace:

Fixnum (but note, Bignum is there)
Symbol
TrueClass
FalseClass
NilClass

That’s just off the top of my head.

But I guess that’s the best we can do when entirely guessing at Ilias’
actual
goal – as we must do every time he posts. The best we have is:

Ability to track instantiation of every object within the system.

If he wants to track instantiation for performance reasons – for
example, to
see how many objects he’s using at a given moment – then ObjectSpace
might
work, just slowly. If there’s some reason he wants to know when a Fixnum
is
“created”, then ObjectSpace isn’t sufficient, and I imagine a C
extension is
the least that’s required.

On 09.06.2011 20:40, Ilias L. wrote:

oo_string = String.new(“The OO String”)
#=> “OBSERVED: The OO String” test
#=> “The Literal String” test

If that really had worked the way you’d expect it, you had ended up in
an endless loop running out of stack levels soon. The reason for this is
that
each string literal would have to go through your special initialization
routine, including your “The OO String” and, very subtle, the "OBSERVED:
"
string as well. The former would make oo_string into having two times
the "OBSERVED: " prefix, once for initializing the string literal, and
second
inside of your explicit String.new() call. But the fact that "OBSERVED:
" would require string initialization as well, would lead to an endless
loop.

To fix this infinite loop, one would have to initialize a string object
prior to hooking initialize() like this:

observed_prefix = "OBSERVED: "

class String
alias_method :orig_initialize, :initialize
def initialize(val)
orig_initialize observed_prefix + val
end
[…]
end

As Matz already pointed out, there are quite some good reasons for
letting the parser translate literal constants into objects independent
from the
actual program flow.

The behaviour of the class String has been altered, whilst using the
standard mechanisms of the Object Model.

To my huge surprise, although the li_string has been instantiated as
an object of class String, the new initialize method was not called.

This is essentially a defect, as the consistency of the Object Model
breaks.

Another question could be why »"OBSERVED: " + val« does not call
initialize() on the resulting string right before that result is passed
to
orig_initialize. OTOH, this would lead to another endless loop.

My understanding is, that this is a know-issue and a trade-off due to
performance issues.

As you see from the above, it’s not just a trade-off for performance
reasons.

Underlying Requirement:
Ability to track instantiation of every object within the system.

This is an interesting idea. I think you have to patch NEWOBJ() in the
sources, at least.

– Matthias

On Thu, Jun 9, 2011 at 11:40 AM, Ilias L. [email protected]
wrote:

This is essentially a defect, as the consistency of the Object Model
breaks.

The statement “Everything is an Object” becomes invalid, because
e.g. a string object instantiated from a literal behaves differently that a
string object instantiated normally via new() (although they share the
same class, and thus should behave the same).

The logic in this argument is fundamentally flawed. “Everything is an
Object” does not mean “every object of the same class behaves the
same”. Objects of the same class instantiated with different syntax
regularly behave differently. Aside from literal vs. new, you have:

#allocate vs. #new generally
creation via other methods specific to a particular class (e.g., for
Procs objects, proc {} vs. lambda {} vs. Proc.new vs ->() {} vs.
method() vs. & to capture the block passed to a method)

Others in the thread have explained adequately the practical reasons
why you can’t have be interpreted as
.new() where both are identical [as
that would produce infinite recursion], but aside from the
practicality you are wrong on the basic theory: different
initialization mechanism producing objects which are discernably
different in the path of method calls involved in their instantiation
and/or their behavior later in their lifecycle is not inconsistent
with Ruby’s object model, it is rather fundamental to it.

Yukihiro M. wrote:

In general, if you want a perfect language that satisfies every random
ideas popping in your mind, you’d better design your own language,
rather than trying to hijacking existing one.

In this particular case, that’s not even necessary. Ioke and Seph
already allow overriding of literals. Just use them.

jwm

On 10 , 01:30, Yukihiro M. [email protected] wrote:

|
|This is essentially a defect, as the consistency of the Object Model
|breaks.

You don’t have to teach me about Ruby’s object model.

I’m writing here in comp.lang.ruby, addressing the public, not you
personally.

But: of course I can teach you something about the object model,
especially because you have designed it. Because you are - as the
language designer and implementer - far to deep in the internals, in
order to view the model (and the language in general) strictly from a
users view. You miss some basics - that’s natural.

String objects
for literals are already created in the compile time, which is far
before you redefine the initialize method.

Basics: Interpreted language, OO

From my (OO user) point of view, there is no compile-time.

And my OO-level code supersedes the core-level code. Because the core-
level code is simply there to serve my OO-level code (which has more
importance).

The individual string
objects from literals are just copy of the already allocated and
initialized objects.

you say: “Individual string objects”

Those are not String objects, as their related initialize method was
not called (remember: my user OO-code supersedes naturally the core-
level code)

If those would be instances of a class like StringLiterals, it would
be different.

The whole purpose of the initialize method is to
initialize newly created objects, as the name suggests.

The “initialize” method is the constructor. By definition, an object
must call the constructor, to become an instance of the class.

I don’t feel
any need to call the (redefined) initialize method for string
literals, that already initialized at the compile time.

This is not about “feelings” and “needs”, but about strictness.

If I use a valid language-construct to override the constructor, then
the language must call the modified constructor in order to be
compliant to the OO-model/language. If the language designer “feels”
otherwise… then it has to control those feelings.

Or he must clearly state, that those are not objects of class
String.

Even if you
can use it to track object creation, it’s only a side-effect. I am
not going to change the language (or its object model) to fit your
purpose better.

Here I’m asking here the public (including you of course), if there’s
a workaround available / possible.

Neither here, nor on the issue-track I’ve asked you to “change the
language (or its object model)”, but to deal with an inconsistency -
at least to acknowledge the known issue.

Knowing that there is an issue, enables interested people to
collaborate in order to solve it.

In general, if you want a perfect language that satisfies every random
ideas popping in your mind, you’d better design your own language,
rather than trying to hijacking existing one.

I am sorry to hear you talking like this, although I believe it was
simply a bad moment.

The few issues that I’ve filed are for sure not “random popping
ideas”. Mostly, they are either user needs or usage barriers.

“hijacking” implies “stealing” “taking away”.

As for “my language”: I’m not interested to design my own language (at
least not now). Designing a processor would fit my interests more -
but I’ve no time for such hobbies (as I could most possibly never beat
the “big players”).

I simply try to use this language, to report issues which can evolve
the language positively, whilst increasing it’s consistency and
flexibility. You don’t even have to understand every use-case. There
are users which supersede e.g. your ability in framework-design. Those
users need some constructs (implementable only in C-core-level), and
those constructs enhance the language in general (none is forced to
use them or course). The next user will find those constructs build-in
and choose the language possibly exactly for this tiny construct.

I am talking here about 5 to 10 issues (estimated).

|The questions are:
|
|b) Is there any way to track (intercept) the instantiation of objects
|(especially those instantiated from literals)
| 1) without a C-level extension
| 2) with a C-level extension

If you don’t care about performance, you can investigate
ObjectSpace#each_object. Note that JRuby turns off the method by
default for performance reason.

ObjectSpace#each_object is not the solution (by design).

A possible solution would be this one:

Provide Class#cb_object_instantiated_from_literal(object)

If you care about performance, I am
afraid that you have to modify the interpreter itself.

Modifying the interpreter is not an option for me - at least not if
the modification is not to be included in core.

And here comes the most important issue:

If a person with over two decades of experience in hard- system- and
firmware-design shows interest to contribute on C-core-level, then you
should encourage this instead of suggesting that he is trying to
“hijack” the language.

You should say “ok, Mr. X can help you to find the relevant sources
and constructs”, not “go find another language or write your own”.

Finally I’d like to say:

The issue “Literal Instantiation breaks Object Model” is crystal-
clear. It should not take anyone more than 15min. to accept it as a
“known issue, trade-off for execution speed”. That’s really nothing
special.

This is how evolution works: accept the issue (weakness, defect, trade-
off, …), collect relevant information, make it available for
interested people, wait till someone claims the issue and hopefully
comes up with a solution.

“Ruby 2.0 - Everything First Class Objects”

Or can it become ruby 1.9.5?

.

On 10 Ιούν, 11:53, Matthias Wächter [email protected] wrote:

On 09.06.2011 20:40, Ilias L. wrote:

class String
alias_method :orig_initialize, :initialize
def initialize(val)
orig_initialize "OBSERVED: " + val

#change to something like:

orig_initialize val
puts self.inspect

end
def my_method_test
print self.inspect, " test\n"
end
end
[…]

If that really had worked the way you’d expect it, you had ended up in an
endless loop running out of stack levels soon. The reason for this is that
[…] - (elaborations of recursion problems with current showcase)

I’ve understood your elaborations.

You should not focus on the showcase code, which could be easily
rewritten to not fall into this “trap” at all (e.g. placing a simple
“puts object.inspect” in the constructor).

Please see the reply to Mr. Matsumoto for more details on the essence
of this issue (and the general essence subjecting development).

As you see from the above, it’s not just a trade-off for performance reasons.

The performance problem is the central one. Everything else comes
after, and should be solvable easily.

Underlying Requirement:
Ability to track instantiation of every object within the system.

This is an interesting idea. I think you have to patch NEWOBJ() in the sources,
at least.

Is “NEWOBJ()” the central function, used system-wide (even from the
parser)?

.

2011/6/10 Ilias L. [email protected]:

But: of course I can teach you something about the object model,
especially because you have designed it. Because you are - as the
language designer and implementer - far to deep in the internals, in
order to view the model (and the language in general) strictly from a
users view. You miss some basics - that’s natural.

We’ve been here before:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/139166


Phillip G.

A method of solution is perfect if we can forsee from the start,
and even prove, that following that method we shall attain our aim.
– Leibnitz

2011/6/10 Ilias L. [email protected]:

you say: “Individual string objects”

Those are not String objects, as their related initialize
method was not called

Um, yes, they are String objects.

Having String.initialize called is not required to have a String
object. Even ignoring literals, the usual requirement to get an object
of a given class in Ruby is to call the class’s allocate method.
Calling “Klass.new” is a convenience wrapper which is equivalent to
calling Klass.allocate.initialize

The “initialize” method is the constructor.

No its not. “initialize” isn’t even a constructor. The
default/standard constructor is the class method “new”, which calls
the class method “allocate” to get a new object of the class, and then
calls the instance method “initialize” on the new object.

By definition, an object must call the constructor, to become
an instance of the class.

If one accepts that definition, the only thing you might argue is a
“constructor” in Ruby is the class method “allocate”, since even
ignoring literals, calling the class method “allocate” is the only
prerequisite for getting an object of the class (the class method
“new” will return an object of the class, but it is by calling
“allocate” that it gets that object, not by the subsequent call to
“initialize”, which, as an instance method of the class, requires that
the instance already exist before it can be called.)

I don’t feel
any need to call the (redefined) initialize method for string
literals, that already initialized at the compile time.

This is not about “feelings” and “needs”, but about strictness.

Yes, and, strictly, you are wrong.

If I use a valid language-construct to override the constructor, > then the
language must call the modified constructor in
order to be compliant to the OO-model/language.

No definition I’ve ever seen of the OO model requires that a class
have only one constructor, nor does any version of the OO model
require that objects specified as literals be equivalent to calling
the default constructor with an argument that is some function of the
specified literal.

I can’t actually think of any actual language that fits that
definition of the OO model.

Here I’m asking here the public (including you of course), if
there’s a workaround available / possible.

No. Its not even logically possible, much less practical.

Neither here, nor on the issue-track I’ve asked you to “change
the language (or its object model)”, but to deal with an
inconsistency - at least to acknowledge the known issue.

The only issue here is that you have an incoherent understanding of
the OO model (I use incoherent in a strict sense: specifically, that
it requires something which is logically inconsistent.)

“Ruby 2.0 - Everything First Class Objects”

Or can it become ruby 1.9.5?

That would be a nice goal. The problem with your criticism is that you
are aiming it in the wrong direction: literals are first-class objects
and don’t need changed – OTOH, blocks and methods aren’t (though its
possible in each case to create an object from them, which mitigates
but doesn’t eliminate the issue.)

On 10 , 01:30, Yukihiro M. [email protected] wrote:

|
|This is essentially a defect, as the consistency of the Object Model
|breaks.

[…]

String objects for literals are already created in the compile time, which is
far
before you redefine the initialize method.
[…]

This should not matter.

In context of irb this becomes more clear (redefinition of the
initialize method happens clearly before it’s usage.).

#String2.rb
class String
def initialize(val)
self.replace(val)
puts object_id
end
def my_method_test
print self.inspect, " test\n"
end
end

command line

$ irb

irb(main):001:0> original = String.new(“original”)
=> “original”
irb(main):002:0> load “String2.rb”
=> true
irb(main):003:0> altered = String.new(“altered”)
21878604
=> “altered”
irb(main):004:0> altered.my_method_test
=> “has method <my_method_test>”
irb(main):005:0> literal = “literal”
=> “literal”
irb(main):006:0> literal.my_method_test
=> “has method <my_method_test>”
irb(main):007:0>

The initialize method is an integral part of the class String.

From the moment that “String2.rb” is loaded, the initialize method of
class String has been validly redefined.

(The behaviour of the String class within the “irb session” is
altered)

The altered initialize method is now an integral part of the class
String.

The altered String object behaves as expected (responds to
"my_method_test, initialized via redefined initialize method).

The String(Literal) object responds to “my_method_test”, but it is was
not initialized with the redefined initialize method.

The “Literal Instantiation” calls the original (core-C-level) String
initialize method instead of the redefined one (user-language-level).

This breaks the object model.

.

On 12 Ιούν, 17:39, Ilias L. [email protected] wrote:

In message “Re: CORE - Literal Instantiation breaks Object Model”

#String2.rb
class String
def initialize(val)
self.replace(val)
puts object_id
end
def my_method_test
print self.inspect, " test\n"

correction, replace:
print self.inspect, " test\n"
with:
‘has method <my_method_test>’

Ilias L., you try to change Ruby in a fundamental but also
totally random way.

Rather than believe your input has any real value, I suggest you to
start your own language instead and leave Ruby - and the community -
alone.

The initialize method is an integral part of the class String.

Go read the Pickaxe or try to understand Ruby first before you make
statements like that. An “integral part of class String”? Huh?

You simply show that you know nothing about proper OOP design when you
use buzzwords like “integral part” - no kidding eh? The initialize()
method must be important, hmm?

I advice you to go back to Lisp and abuse the mailing lists there - we
don’t need you here.

PS: Ilias ignores statements made selectively. His way to “discuss” only
fits when he wants to look at specific statements and ignore others.

He tries to soak up your energy and time.

Ignoring Ilias entirely is by far the best strategy.

Christopher D. already hit the most relevant OO and technical
concerns, so
I’ll just address this:

On Friday, June 10, 2011 01:00:26 PM Ilias L. wrote:

But: of course I can teach you something about the object model,
especially because you have designed it. Because you are - as the
language designer and implementer - far to deep in the internals, in
order to view the model (and the language in general) strictly from a
users view. You miss some basics - that’s natural.

That’s some pretty unbelievable arrogance. Really? Let’s examine this:

String objects
for literals are already created in the compile time, which is far
before you redefine the initialize method.

Basics: Interpreted language, OO

From my (OO user) point of view, there is no compile-time.

Of course there is, even from a "user"s point of view:

puts ‘Hello, world!’
class Foo
def bar
if false
a <> b
end
end
end

Execute that, and you find that despite the fact that this code will
never run
(and thus, will never be “interpreted”), the entire file will be
rejected by
Ruby at compile time. You’ll never see that “Hello, world!” message
because of
a syntax error buried at compile-time, later.

As a user, compile-time is also relevant to why symbols work the way
they do,
and why they’re so useful.

Pretending to be an uninformed user doesn’t mean you’re dealing with
something
more abstract or “pure”, it just means you’re less informed. For one
thing, as
Christopher pointed out, ‘initialize’ isn’t the constructor, and having
a
separate ‘initialize’ method is something I’ve seen (and implemented) in
other
languages.

Those are not String objects, as their related initialize method was
not called (remember: my user OO-code supersedes naturally the core-
level code)

While the notion of type is also orthogonal to OO-ness, I don’t see that
being
relevant here. These are in every way String objects. If you define
methods on
String, those methods apply to String literals. This includes your
initialize
method:

oo_string = String.new(“The OO String”)
li_string = “The Literal String”
li_string.send :initialize, li_string

Now the rest of the program works as you expected.

Their history is irrelevant. You’re talking about what they are now, and
they
are, in fact, Strings, in every sense that is relevant right now.

If those would be instances of a class like StringLiterals, it would
be different.

No, it wouldn’t. Then you’d be whining that when you overrode
‘initialize’ in
StringLiterals, your initialize still wasn’t called!

I don’t feel
any need to call the (redefined) initialize method for string
literals, that already initialized at the compile time.

This is not about “feelings” and “needs”, but about strictness.

Matz appears to be saying that he’d rather not call the strings’
initialize
method twice. Do you really think “strictness”, in any context, would be
satisfied by calling initialize twice?

If I use a valid language-construct to override the constructor, then
the language must call the modified constructor in order to be
compliant to the OO-model/language. If the language designer “feels”
otherwise… then it has to control those feelings.

Or he must clearly state, that those are not objects of class
String.

And as wrong as you’ve been, this is where you cannot possibly be more
wrong.

Unless you have somehow become Matz’ employer, he owes you nothing, and
you
are in no place to tell him (or anyone else) what they “must” do.
Telling them
this is not a recipe for cooperation.

And you do seem to care about cooperation.

Neither here, nor on the issue-track I’ve asked you to “change the
language (or its object model)”,

Oh, but you have. You just did! In fact, you didn’t “ask” him, you told
him,
you demanded that he change the way the language behaves.

The few issues that I’ve filed are for sure not “random popping
ideas”. Mostly, they are either user needs or usage barriers.

Giving us some context would go a long way towards establishing the
truth of
this.

If a person with over two decades of experience in hard- system- and
firmware-design shows interest to contribute on C-core-level, then you
should encourage this instead of suggesting that he is trying to
“hijack” the language.

Except you’re not that person. You’re some random guy on a discussion
group.
Even if you have the credentials you claim, and even if they are somehow
relevant, we only have what you say here to go on. Your real credentials
are
your contributions to this discussion.

And your contributions have been things like telling the creator of a
language
that they don’t understand their own language. You’d think that would be
enough of a clue, without the entire community convinced you’re not
worth
talking to.

You have it backwards. If you really do want to contribute, it isn’t the
responsibility of the core people to encourage you, it’s your
responsibility
to demonstrate to them that it is worth their time to help you.

The issue “Literal Instantiation breaks Object Model” is crystal-
clear. It should not take anyone more than 15min. to accept it as a
“known issue, trade-off for execution speed”. That’s really nothing
special.

Are you surprised that you now have several responses that disagree with
you?
Why do you think that is?

Think about it.

On 9 , 21:39, Ilias L. [email protected] wrote:

oo_string = String.new(“The OO String”)
#=> “OBSERVED: The OO String” test
This is essentially a defect, as the consistency of the Object Model
The questions are:
Ability to track instantiation of every object within the system.
Related Issue:

Literal Instantiation breaks Object Model

Related Issue (Attempt to workaround)

Provide Class#cb_object_instantiated_from_literal(object)

.