Self and Ruby Comparisons

M

Mystifier

------=_NextPart_000_0021_01C50188.93ACC2C0
Content-Type: text/plain;
charset="US-ASCII"
Content-Transfer-Encoding: 7bit

Hi

I could not locate any Self and Ruby comparison. Any links?


Thanks,

Mystifier

------=_NextPart_000_0021_01C50188.93ACC2C0--
 
T

Trans

I don't know if there is much comparision out there. You can have a
look at the suby-muse and suby-ruby archives. You may find a little bit
of info on the subject there --on occassion we have discussed of
prototype-based Ruby.

T.
 
M

Martin DeMello

Trans said:
I don't know if there is much comparision out there. You can have a
look at the suby-muse and suby-ruby archives. You may find a little bit
of info on the subject there --on occassion we have discussed of
prototype-based Ruby.

for one, self doesn't have a ruby keyword...

right. i'll get my coat.

martin
 
C

Csaba Henk

I could not locate any Self and Ruby comparison. Any links?

In Self really everything is message passing. Unlike Ruby and unlike
Smalltalk! Assignment is a special thing even in Smalltalk. In Self, you
are free to add/modify slots of objects from outside, and assignment is
in fact just a message which does this. (I think so.)

Recently I've been playing with Io (http://www.iolanguage.com/) (the
place where I heard of it is this very list). It has a similar object
model to Self, and is very compact, so it's easy to get a grasp on it
and see how that prototype based object model works. As an addition, the
syntax is very clever and clean. It's in fact a simple sexp-based
syntax, but you won't notice this fact unless you watch heavily.
(Basicly the syntax consists of nothing else just expressions lke "a
b(c,d) e(f)", which means something like "a.b(c,d).e(f)" in ruby (but,
as we know, in ruby there is more syntax than these kind of
expressions); besides, there is some sugaring for more intuitive usage
of operators (which are, of course, ordinary methods). It uses the same
great idea as ruby for separating expressions: you can use either a
semicolon or a newline).

Btw, I hope you know that Ruby has almost full support for prototype
based programming.

Csaba
 
T

Trans

Btw, I hope you know that Ruby has almost full support
for prototype based programming.

1) I would like to see a simple demonstration of this, I think while
basically possible, things like traits aren't so easily doable.

2) And even so, the "class-way" will be too tempting for lack of syntax
sugars, I think.

3) Also programming Ruby in this way would likely incur more overahead,
rather than less like in io (I imagine).

Thanks for the info.
T.
 
C

Csaba Henk

1) I would like to see a simple demonstration of this, I think while
basically possible, things like traits aren't so easily doable.

Uh, to admit, my above claim is somewhat intuitive.

I have a general understanding of what a prototype based object model
is, and I made a mental experiment what components are needed to support
it, and how these can be implemented in ruby, and I found that they can
be implemented quite easily and naturally.

I don't know what such "subtleties" like traits are. If you gave me a
concise explanation, I'd appreciate that. And then we could think about
my implementation, can/should it be extended to have that feature?

So, my idea is as follows:

A prototype is a module which extends itself.

Cloning is supported out of the box. The good question is inheritance
and that how you realize different method (slot) lookup schemes.

As my prototype is a module, a modification in an instance method is
inherited. You can add/modify methods of a prototype such that its
children are not affected by means of module/singleton methods.

There is also another way of cloning:

module Foo; extend self; end
# Bar will be children of Foo
module Bar; extend self; extend Foo; end

In fact, this is the proper way of cloning. If you do so, sending a
message to Bar which is defined in Foo will be properly dispatched at
Foo. You also get reflection for free: existing methods like
Module#ancerstors will give the correct info here as well.

By mixing in prototypes you gain a nice mechanism to have your prototype
based world interact with traditional ruby code (if it weren't an
important criterion, you could put together custom object models in any
language supporting closures). If you want more, by method_missing you
can make proxy modules to existing objects which give you all the freedom
that you enjoy with prototypes.

You can get your (ie. not basic or third party) classes involved to the
game (of communicating with prototypes, ie. making them possible to be
mixed in; I don't mean here converting them to a prototype based model)
by changing the "class Foo" type opening stanza to "module Foo", and
defining a "new" module method like

def new(*a,&b)
o=Object.new
o.extend self
o.initialize(*a,&b)
o
end

(some subtleties like the "class" instance method need to be worked out
here). Or, you can just use project evil's class-to-module transformer
:)

It's also nice that the initial copy of your prototype can be created in
the usual way, by assigning it to a constant with the

module Foo
...
end

syntax, but copies of it don't need to occupy costants, there you can
use Module.new.

Maybe it would be worth to consider creating a Prototype < Module class
which sugares all these actions (the initialize method of Prototype
would care about the self-extension, etc.)

So, I'm just curious what you think of the power of this approach; is
anything essential missing?
2) And even so, the "class-way" will be too tempting for lack of syntax
sugars, I think.

By my opinion the watershed is not having a class keyword or type or
metatype not, but that in what extent are the important OO mechanisms
(inheritance and co.) are available for "ordinary" objects. By having
singleton methods, the "clone" operation, fully objectified
classes/modules and the possibility of creating proxy modules, the
situation is quite good in ruby.

I don't think of the usual class-based structure as a temptation to
avoid. I do think of prototype-like techniques as a powerful tool which
can be utilized at the right time.

Eg., I tell you about the circumstances amongst which I meditated over
these things.

I was writing a small utility for displaying tree-like structures (in
ascii art in my case, but that could be easily replaced by other
rendering engines, so it's not important). For first, I wrote the code
in mind with that I got serial data to be properly allocated in a fresh
custom structure (eg., reading a directory tree from disk or from the
content listing of a tarball), so I created the necessary classes which
provided this structure.

But then I realized that if I want good, flexible code, I can't exclude
the possibility of displaying something which is not serial, and already
has an implicit tree-like structure (like (nested) Arrays). Converting
such things ("clients") instance-by-instance to my custom structure
(which can be passed to the renderer) is a superfluous overhead. So
rather than doing this, I just wanted to make the implicit structure
explicit by adding the methods to the clients needed by the renderer. I
then converted a bunch of classes to modules, but it was not that easy,
because both class and istance methods were necessary to be added to the
clients to make the renderer happy. The solultion was both extending and
including a module in the client class.

That is, upon necessity, you have alternatives to the stock
"class A < B; include C; ... end; a=A.new" OO. And it's good enough for
me.

I've also seen techniques like self-extending modules, and instead of
having an Foo::Bar type module or class for some task in the context of
Foo, having just a simple Bar object like

module Foo
Bar = Object.new
class << Bar
....
end

in other people's code so I think these ideas are existing ruby
patterns, not just my deviance. Kernel itself is a self-extending
module.
3) Also programming Ruby in this way would likely incur more overahead,
rather than less like in io (I imagine).

I don't think that any of the above would mean an overhead for the
interpreter. As for the programmer, it depends on her needs. If she
wants to use these techniques in a clear, explicit way, she will be able
to add the necessary sugar. Ruby does a good job in this respect.

Csaba
 
C

Csaba Henk

In fact, this is the proper way of cloning. If you do so, sending a
message to Bar which is defined in Foo will be properly dispatched at
Foo. You also get reflection for free: existing methods like
Module#ancerstors will give the correct info here as well.

Ah, and one more neat trick: as prototype based objects are instances of
the same class Module (or a customized Prototype class), you can get
just one particular method of one p.b.o as UnboundMethod, and bind it to
another p.b.o. ... You also use here that p.b.o-s extend themselves.

Csaba
 
M

Mathieu Bouchard

Btw, I hope you know that Ruby has almost full support for prototype
based programming.

Actually, Perl has it better, because you can change the class of an
object, and you can change the list of superclasses of any class.

However, this is only a slight advantage, as some other people have
demonstrated you can do the same for Ruby using not that many lines of C
code.

So the only difference is that in Ruby you can't do full prototype-based
programming using just 100%-Ruby.

_____________________________________________________________________
Mathieu Bouchard -=- Montréal QC Canada -=- http://artengine.ca/matju
 
R

Robert Klemme

Mathieu Bouchard said:
Actually, Perl has it better, because you can change the class of an
object, and you can change the list of superclasses of any class.

However, this is only a slight advantage, as some other people have
demonstrated you can do the same for Ruby using not that many lines of C
code.

And if a copy is sufficient you can do this even in pure Ruby:

class Object
def cast(target_class)
copy = target_class.allocate

instance_variables.each do |var|
copy.instance_variable_set(var, instance_variable_get(var))
end

copy
end
end
=> Bar
So the only difference is that in Ruby you can't do full prototype-based
programming using just 100%-Ruby.

Do you have a link or explanation that demonstrates the merits of the
capability to change an instance's class at runtime? Currently I don't
have a clue in which situations I would want this. Thx!

Kind regards

robert
 
T

ts

M> Actually, Perl has it better, because you can change the class of an
M> object, and you can change the list of superclasses of any class.

and you forget to say that in this P language array, hash, ... are not
objects.

Always easy to change the class when you work with only *one* type.

M> However, this is only a slight advantage, as some other people have
M> demonstrated you can do the same for Ruby using not that many lines of C
M> code.

You are right, the demonstration was made that a few lines of C can crash
easily ruby ... (personnaly I just need one line to crash ruby)



Guy Decoux
 
N

Nicholas Van Weerdenburg

And if a copy is sufficient you can do this even in pure Ruby:

class Object
def cast(target_class)
copy = target_class.allocate

instance_variables.each do |var|
copy.instance_variable_set(var, instance_variable_get(var))
end

copy
end
end

=> Bar


Do you have a link or explanation that demonstrates the merits of the
capability to change an instance's class at runtime? Currently I don't
have a clue in which situations I would want this. Thx!

Kind regards

robert

How about migrating legacy objects to new objects at run-time?

Nick
 
R

Robert Klemme

Robert Klemme said:
And if a copy is sufficient you can do this even in pure Ruby:

class Object
def cast(target_class)
copy = target_class.allocate

instance_variables.each do |var|
copy.instance_variable_set(var, instance_variable_get(var))
end

copy
end
end

A slightly more sophisticated version:

class Object
def cast(target_class)
copy = case target_class
when Class; target_class.allocate
when Module; dup.extend(target_class)
else target_class.class.allocate
end

instance_variables.each do |var|
copy.instance_variable_set(var, instance_variable_get(var))
end

copy
end
end

Cheers

robert
 
J

Jeff Moss

What about instantly changing the class of an activerecord object based
on modification of the "class" column.
 
T

Trans

robert,

Class swapping was brought up on suby-ruby awhile ago under the topic
of "Soul of a New Machine" (among others). The basic idea was an
anology along the following lines:

Lets say you have a Person, that preson does all the usual person
things. But today that person has a job as a Fireman, so he goes to
work and changes modes. Perhaps at night he goes home and must change
modes again and be a Boyfriend (hopefully that means some fun methods
are involved ;-)

Okay so the notion is that an object can take on another level of
abstraction, such that it's instance vars are essentially its "soul"
and they can be embuded into different classes.

It's sort of an inverted way to look the use of #become. But I think, a
much more undersandable and applicable way to look at.

T.
 
T

Trans

Csaba,

<quote>
I don't know what such "subtleties" like traits are. If you gave me a
concise explanation, I'd appreciate that. And then we could think about
my implementation, can/should it be extended to have that feature?
</quote>

Well, I'm not an expert by any means but I do my best. A trait is
simply a specially designated slot that acts as a parent. I guess
that's key, everything is slot based. I think your proposal has merits
but extending modules does not quite coorespond to trait slots. The
obvious distinction being that one can change a slot on the fly, but
not so for module extensions.

<quote>
I don't think of the usual class-based structure as a temptation to
avoid. I do think of prototype-like techniques as a powerful tool which
can be utilized at the right time.
</quote>

I see your point, and I think prototype-like tools can be used (and are
used) in a class-based language. But IMHO you loose some of the reason
and foundationary advantage of prototype-based OOP --primarily that the
whole object hieracrhy and its use become radically simplified.

Even so, like I said, your approach does have merits, and is certainly
a good way to give prototype-based OOP some play in Ruby. If your are
interested I would enjoy developing a dedicated library together. We
can work on it over at suby-ruby (keep in mind I can't devote too muh
time on it at the moment, but I willl certainly be happy to help/get
started.)

T.
 
R

Robert Klemme

Trans said:
robert,

Class swapping was brought up on suby-ruby awhile ago under the topic
of "Soul of a New Machine" (among others). The basic idea was an
anology along the following lines:

Lets say you have a Person, that preson does all the usual person
things. But today that person has a job as a Fireman, so he goes to
work and changes modes. Perhaps at night he goes home and must change
modes again and be a Boyfriend (hopefully that means some fun methods
are involved ;-)

Okay so the notion is that an object can take on another level of
abstraction, such that it's instance vars are essentially its "soul"
and they can be embuded into different classes.

It's sort of an inverted way to look the use of #become. But I think, a
much more undersandable and applicable way to look at.

I missed the term "role" in your explanation. Cause that's the way I had
described this: the person changes her roles over time. Changing the
class is certainly an option here although in this example you would
likely want to restrict classes to sub classes of Person.

But what do you do if the Person needs to play several roles at a time?
Change the class for each method invocation? That's likely going to be
inefficient - and considering multiple threads it restricts concurrency
dramatically.

In Ruby the ideal way IMHO would be to have the reverse method of #extend
so if an instance takes on a role it uses a special mixin module's methods
and un-mixes this module when it leaves the role. Of course other
approaches are feasible, too. (Delegator instances that extend the role
module for example.)

Kind regards

robert
 
R

Robert Klemme

Robert Klemme said:
I missed the term "role" in your explanation. Cause that's the way I had
described this: the person changes her roles over time. Changing the
class is certainly an option here although in this example you would
likely want to restrict classes to sub classes of Person.

But what do you do if the Person needs to play several roles at a time?
Change the class for each method invocation? That's likely going to be
inefficient - and considering multiple threads it restricts concurrency
dramatically.

In Ruby the ideal way IMHO would be to have the reverse method of #extend
so if an instance takes on a role it uses a special mixin module's methods
and un-mixes this module when it leaves the role. Of course other
approaches are feasible, too. (Delegator instances that extend the role
module for example.)

Illustration:

require 'delegate'

class Object
def role(mod)
(@roles ||= {})[mod] ||= SimpleDelegator.new(self).extend(mod)
end

def role?(mod)
@roles and @roles.has_key? mod
end

def unrole(mod)
@roles and @roles.delete(mod)
end

def roles
@roles ? @roles.keys : []
end
end

class Foo
attr_accessor :name
end

module Bar
def xx() name() end
end

f = Foo.new
f.name = "George"
puts f.role? Bar
p f.role(Bar).xx()
puts f.role? Bar
p f.roles
f.unrole(Bar)
p f.roles
puts f.role? Bar

Regards

robert
 
T

Trans

robert,

Quite right, I'm not sure Ruby is particularly suited for role
swapping. (Prototype-based OOP handles it gracefully) And I don't know
how inefficent #become would be. It would be nice to think its just a
matter of changing one pointer, but I know that's not the case.

Your role delegator is nice. At the very least it's much easier to be
more than one thing at a time. (There's no problem with roles
interfereing with each at the method name level is there?) Unfortuately
I suspect that it may be nearly as inefficient as repeated using
#become (but that's just a guess).

Thanks for the illustration, I think I'll store this for potential
future use/exploration.

BTW, does #unrole actually work?

T.
 

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

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top