Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Name resolution in Ruby

5 views
Skip to first unread message

Alan Stern

unread,
Feb 11, 2002, 4:56:15 PM2/11/02
to
I've been struggling to understand how name resolution is supposed to
work in Ruby. So far, this has been without looking at the source
code, for two reasons:

First, the source is rather long and hard to understand.

Second, I want to know how Ruby is *intended* to operate,
rather than the details of how a specific release actually
does operate.

My starting point was the book "Programming Ruby" by Hunt and Thomas
(an excellent book! -- thanks, Andy and Dave). However, their
discussion is framed almost entirely in terms of identifier scopes,
which only gives a static view of what is largely a dynamic process.
That is, a scope is a static region of a program that can be
identified by the parser at compile time, whereas name resolution and
lookup occurs later, when the interpreter is executing the compiled
code.

Here's what I've been able to glean. Hopefully nobody will mind this
posting. I could use some feedback -- what I've got is incomplete, and
parts of it are almost certainly wrong. I trust that somebody in the
newsgroup can help explain things better.


There are several different types of identifiers in Ruby: local
variables, instance variables, class variables, global variables,
constants, and method names. Identifier types are determined by the
parser as it compiles a program. (Sometimes there isn't enough
information available for the parser to decide which type a particular
identifier represents; method names can be confused with local
variables and with constants. In these situations the parser relies
on various heuristics to guess the type, and it doesn't always guess
right.) Each type of name gets resolved in a different way.


Global variables are the easiest. There's a single set of values for
the global variables, and a name always refers to the corresponding
value.

Instance variables are nearly as simple. Every object contains a
table of instance variable values, and an instance variable name is
looked up in the table of the current object (i.e., the value of
"self").

You would think that class variables would be equally simple to
explain, but they're not. The question of where one gets looked up or
stored is all tied in with the matter of meta-classes, and I don't
really understand how it's supposed to work. Also, Matz has mentioned
(in recent newsgroup postings) that he has had to fix some bugs in the
implementation of class variables during the last few weeks, so things
are in a state of flux. Maybe somebody can fill in the details here?


Local variables operate by way of bindings. A binding is (in
principle, anyway -- the implementation details may be different) just
a table listing variable names and their values. It corresponds more
or less to the data stored in a Binding object, although that also
includes the value of the current object and the current block, if
there is one. A binding is the dynamic representation of a scope: A
new blank one is created and installed as the current binding whenever
the flow of control enters a class definition (that is, whenever a
"class" statement or a "module" statement is executed). When the flow
of control enters a method, a new binding is created and initialized
with mappings for the method's parameters. When a block is created it
gets its own binding, which is initialized as a copy of (actually, it
must be a reference to) the current binding. And when the flow of
control leaves a class definition, method, or block, the binding is
destroyed and the one previously in force once again becomes the current
binding.

Local variable names are just looked up in the current binding. When
a new local variable is created, it gets entered into the current
binding. This explains why local variables created inside a block do
not exist once the block exits; the entries for the variables get made
in the block's binding and not in the original binding (which gets
re-installed as the current one when the block is finished).


Method names are resolved in an elaborate way. A method call has the
form "r.m(...)", where "r" is the receiver (which defaults to self if
it is omitted) and "m" is the method name. The search for m starts in
r's class. Each class (or module) contains a table of instance method
names, together with pointers to their implementations. The name m is
looked up in this table. If it is not found there, and if r is itself
a class, then a special case comes into play: m is looked up in r's
superclass's metaclass, then the superclass's superclass's metaclass,
and so on, all the way up to Object's metaclass. (This is how
inheritance of class methods is made to work.) If none of those
searches succeeds, or if r is not a class, then the search continues
in the table for the superclass of r's class, then that class's
superclass, and so on all the way up to the Kernel module. (That's
how inheritance is made to work.)

[That the order of the lookups works as described can be
demonstrated by the following sample code:

class Class
def m
p "Class#m"
end
end

class A
end

class B < A
end

B.m # Prints out "Class#m"

def A.m
p "A.m"
end

B.m # Prints out "A.m"

The first use of m is found in B's class (which is Class). The second
use is found in B's superclass's metaclass, so that must precede B's
class in the search order.]


Finally there are constants. Class objects (and module objects)
contain a table listing the constants defined in that class (-- as
well as one listing the class variables; in fact these tables might
really be the same as the one listing the instance methods for the
class, with just the forms of the names to distinguish the types of
the entries). Constant names get looked up in these tables much like
method names, but with one big difference: The class in which the
search starts is not the same.

For a qualified constant name, like AClass::CONST or ::CONST, the
search starts in AClass or the top-level class (however that gets set;
the top-level class is altered during processing of a file by the
Kernel#load command if the wrap parameter is set to true).
Unadorned constant names (just plain CONST) do not get looked up
starting in the current object's class. Instead, the lookup starts at
a point we might call the current class, which is not the same thing.
The current class is determined statically by the parser, not
dynamically during execution. For code outside a class definition,
the current class is just the top-level class. For code inside a
class definition, the current class is the one being defined. This
has two unexpected consequences. If m is a class method for class A,
that mentions a constant CONST, the choice of where CONST gets looked
up in m will be different depending on how m is defined:

class A
def A.m
... CONST ...
end
end

and

class << A
def m
... CONST ...
end
end

and

def A.m
... CONST ...
end

will look up CONST in three different places. Also, if m is an
instance method of class A that mentions CONST, and B is a class
derived from A that contains its own value for CONST but does not
override the definition of m, and b is an instance of B, then the
method call "b.m" will end up using A's version of CONST, not B's.
The overall effect is that constants behave as though they really do
have a static scope.


All contributions welcome.


Alan Stern

ts

unread,
Feb 12, 2002, 6:50:39 AM2/12/02
to
>>>>> "A" == Alan Stern <st...@rowland.org> writes:

A> First, the source is rather long and hard to understand.

Well, if you really think this then you must look at the source of a P
language :-)

A> Instance variables are nearly as simple. Every object contains a
A> table of instance variable values, and an instance variable name is
A> looked up in the table of the current object (i.e., the value of
A> "self").

instance variables are "private" variables

A> You would think that class variables would be equally simple to
A> explain, but they're not.

class variables are "shared" variables

A> Local variables operate by way of bindings.

local variables are resolved at compile time

A> [That the order of the lookups works as described can be
A> demonstrated by the following sample code:

a class is just an object like any other objects.

A> For a qualified constant name, like AClass::CONST or ::CONST, the
A> search starts in AClass or the top-level class (however that gets set;
A> the top-level class is altered during processing of a file by the
A> Kernel#load command if the wrap parameter is set to true).

Well be carefull with this, even with the wrapper you can retrieve old
constants like ::Array and modify the class if you want.

A> The overall effect is that constants behave as though they really do
A> have a static scope.

This is the intented use, I think.

Guy Decoux

Alan Stern

unread,
Feb 12, 2002, 10:49:46 AM2/12/02
to
Thanks for your response, Guy.

ts <dec...@moulon.inra.fr> wrote in message news:<200202121144...@moulon.inra.fr>...


> >>>>> "A" == Alan Stern <st...@rowland.org> writes:
>
> A> First, the source is rather long and hard to understand.
>
> Well, if you really think this then you must look at the source of a P
> language :-)

I believe you!

>
> A> Instance variables are nearly as simple. Every object contains a
> A> table of instance variable values, and an instance variable name is
> A> looked up in the table of the current object (i.e., the value of
> A> "self").
>
> instance variables are "private" variables

Quite so.

>
> A> You would think that class variables would be equally simple to
> A> explain, but they're not.
>
> class variables are "shared" variables

This is currently under discussion in a separate thread. I think a
consensus is growing that class variables really ought to behave more
like instance variables of the class itself, with appropriate accessor
methods.

>
> A> Local variables operate by way of bindings.
>
> local variables are resolved at compile time

That depends on how you look at it. Since the code for a method is
only parsed once, if the parser resolved the local variables at
compile time then an occurrence of a variable like "i" would refer to
one fixed thing. But when a method is called recursively, an
occurrence of "i" in the inner stack frame refers to an object
different from the one referred to by the same occurrence of "i" in
the outer stack frame.

>
> A> [That the order of the lookups works as described can be
> A> demonstrated by the following sample code:
>
> a class is just an object like any other objects.

While largely true, that's not entirely correct. Ordinary objects and
classes differ in the way their metaclasses are created. For
instance, suppose that x is an ordinary object (not a class) and that
C is a class. Then C always has a metaclass -- it is created at the
same time as C (I think) -- but x only has a metaclass if you create
one explicitly. Also, if C is a subclass of B, then Meta-C is a
subclass of Meta-B. This means that, although Meta-x's superclass is
x's original class, Meta-C's superclass is not C's original class but
instead is C's superclass's metaclass.

>
> A> For a qualified constant name, like AClass::CONST or ::CONST, the
> A> search starts in AClass or the top-level class (however that gets set;
> A> the top-level class is altered during processing of a file by the
> A> Kernel#load command if the wrap parameter is set to true).
>
> Well be carefull with this, even with the wrapper you can retrieve old
> constants like ::Array and modify the class if you want.

Yes. Do you know if there is any way, within the wrapper, to access
the original top-level object and class?

>
> A> The overall effect is that constants behave as though they really do
> A> have a static scope.
>
> This is the intented use, I think.
>
>
>
> Guy Decoux

Alan Stern

ts

unread,
Feb 12, 2002, 11:23:49 AM2/12/02
to
>>>>> "A" == Alan Stern <st...@rowland.org> writes:

A> This is currently under discussion in a separate thread. I think a

I don't think so :-)

A> consensus is growing that class variables really ought to behave more
A> like instance variables of the class itself, with appropriate accessor
A> methods.

Try this

class A
@var = 24
class << self
attr_accessor :var
end
end

p A.var
A.var = 12
p A.var


@var is an _instance variable_ for the class A, you don't need to change
class variable because you have instance variables for class

A> That depends on how you look at it. Since the code for a method is
A> only parsed once, if the parser resolved the local variables at
A> compile time then an occurrence of a variable like "i" would refer to
A> one fixed thing.

The parser resolve the local variables at compile time.

A very simple example

pigeon% ruby -rii
dump
a = 12
c = b + a
^D
eval_tree # this is the nodes created after the compile time
BLOCK
NEWLINE <-:1>
VCALL dump # this is resolved as a method (first time that ruby see it)
NEWLINE <-:2>
LASGN a # it has found an ``='' this mean that `a' is a local var
LIT 12
NEWLINE <-:3>
LASGN c # same here `c' is a local var
CALL +
VCALL b # `b' was never assigned (i.e. the local var `b' don't
# exist), ruby make a method call
ARRAY
LVAR a # `a' was assigned, this is a local var

-:3: undefined local variable or method `b' for #<Object:0x401c6ce0> (NameError)
pigeon%


A> While largely true, that's not entirely correct. Ordinary objects and
A> classes differ in the way their metaclasses are created. For
A> instance, suppose that x is an ordinary object (not a class) and that
A> C is a class. Then C always has a metaclass -- it is created at the
A> same time as C (I think) -- but x only has a metaclass if you create
A> one explicitly. Also, if C is a subclass of B, then Meta-C is a
A> subclass of Meta-B. This means that, although Meta-x's superclass is
A> x's original class, Meta-C's superclass is not C's original class but
A> instead is C's superclass's metaclass.

The meta-class can be seen as the class of the class

Look at the ruby char hierarchy in object.c

A> Yes. Do you know if there is any way, within the wrapper, to access
A> the original top-level object and class?

the top-level in the wrapper is a clone of the original top-level, but
it's easy to access class

pigeon% cat ff
A = ::Array
class A
def A_NEW_METHOD_FOR_ARRAY
end

def clone
raise "no clone for Array"
end
end
pigeon%

pigeon% ruby -e 'load "ff", true; p Array.instance_methods; [].clone'
["<=>", "first", "sort", "==", "nitems", "replace", "fill", "size",
"indices", "delete", "&", "===", "inspect", "flatten", "index", "clone",
"reject!", "reverse_each", "collect", "reverse!", "unshift", "each",
"to_a", "compact", "delete_at", "*", "uniq", "map!", "pop", "include?",
"+", "eql?", "empty?", "sort!", "last", "-", "slice", "assoc", "concat",
"flatten!", "rindex", "clear", "length", "indexes", "join", "at", "[]",
"delete_if", "[]=", "each_index", "reverse", "to_s", "compact!", "<<",
"pack", "frozen?", "uniq!", "filter", "shift", "|",
"A_NEW_METHOD_FOR_ARRAY", "slice!", "rassoc", "to_ary", "hash",
"collect!", "push"]
./ff:7:in `clone': no clone for Array (RuntimeError)
from -e:1
pigeon%

Guy Decoux

Chr. Rippel

unread,
Feb 14, 2002, 12:06:35 AM2/14/02
to
"Alan Stern" <st...@rowland.org> wrote in,
...

> This is currently under discussion in a separate thread. I think a
> consensus is growing that class variables really ought to behave more
> like instance variables of the class itself, with appropriate accessor
> methods.

I wrote something to this affect but this was not quite what I mend.
The current class variable behavior is really very usefull but it is
possible to simulate this behavior with instance and/or local variables
and accessor methods. This has the added advantage of a more fine
tuned control of visibility (and no interpretation headaches). Here is
an example of a public ``class attribute" with a protected writer attribute
that is invisible on the meta level
----
class A
var = "a"

define_method(:var) { var }
protected
define_method(:var=) {|x| var = x }
end

p A.new.var # => "a"

class B < A
def initialize(x)
self.var = x
end
end

B.new(3)
p A.new.var # => 3
class << A
var # raises a NameError exception
end
----

Since we already have an implementation of class variables there is
no point to get rid(t?)e of them (they are definitely faster;-).
However it is at least a theoretical possibility to for go their
implementation in a rewrite like Rite.

>
...


> > a class is just an object like any other objects.
>
> While largely true, that's not entirely correct. Ordinary objects and
> classes differ in the way their metaclasses are created. For
> instance, suppose that x is an ordinary object (not a class) and that
> C is a class. Then C always has a metaclass -- it is created at the
> same time as C (I think) -- but x only has a metaclass if you create
> one explicitly. Also, if C is a subclass of B, then Meta-C is a
> subclass of Meta-B. This means that, although Meta-x's superclass is
> x's original class, Meta-C's superclass is not C's original class but
> instead is C's superclass's metaclass.

This is true but this is not relevant for scoping rules, in fact it is possbile
to define constants on the meta class level or more generally singleton
classes. I appended a script illustrating the Meta-class system (note the use
of class variables;-)

...


> > A> The overall effect is that constants behave as though they really do
> > A> have a static scope.
> >
> > This is the intented use, I think.

Local scope is an illusion created by coding convention on top of Ruby's
static scope - but you can always should yourself in the foot;-)

----
A = Class.new
x = Class.new A
Sub = Class.new x
Sub.const_set :Super ,x

p Sub.ancestors # => [Sub, Sub::Super, A, Object, Kernel]

class Sub
class Super
p Module.nesting # => [Sub::Super, Sub]
end
end

Normal = x
class Normal
# prevent creation of Sub::Super::Sub
Sub = ::Sub
class Sub
p Module.nesting # => [Sub, Sub::Super]
end
end

class A
L = "A"
end

class Sub
L = "Sub"
class Super
K = 1
p L # => "Sub"
end
remove_const :L
p K # => 1
class Super
p L # => "B"
end
end

class Binding
def search_path
nest = eval("Module.nesting",self)
__self =eval("self",self)
if __self.is_a? Module
nest.concat __self.ancestors.select {|m| not nest.include? m}
else
nest.concat __self.type.ancestors.select {|m| not nest.include? m}
end
end
end


class Sub
class Super
p binding.search_path
# => [Sub::Super, Sub, A, Object, Kernel]
end
end


# Search path is not transitive!

class A;
F = "A"


end
class B < A; end

class C < B; end

class C
G = "visible in C::Z"
p Module.constants - Object.constants
# => ["F", "L"]
class X; end
class Y < X;end
class Z < Y
p Module.constants - Object.constants
# => ["G", "Z", "X", "Y"]
p binding.search_path
# => [C::Z, C, C::Y, C::X, Object, Kernel]
end
end
----

/Christoph

----
# A meta class illustrations script
class Class
@@to_s = nil
@@level = nil
attr_reader :inst
def superclasses
res = [self]
tmp = self
res.push tmp while tmp = tmp.superclass
return res
end
def each_superclass
klass = self
yield klass
yield klass while klass = klass.superclass
self
end
def level
@level || 0
end
def singleton?; true end
alias :old_to_s :to_s
private :old_to_s
def to_s
if singleton?
if level.zero?
(old_to_s.sub(/^(#<Class:)/){''})\
.sub(/(>)$/){"_Sing(#{inst})"}
else
@to_s
end
else
old_to_s
end
end
alias :inspect :to_s
protected
def __meta
super
@@to_s = to_s.concat '_Meta'
@@level = level + 1
@meta.instance_eval do
@to_s = @@to_s
@level = @@level
end
superclass.__meta if superclass
if level.nonzero?
def self.__meta; @meta end
end
return @meta
end
end

class Object
@@inst = nil
class << self
def singleton?; false end
undef :inst
end
def meta(level = 1)
return self if level.zero?
return __meta.meta(level-1)
end
def singleton_type
class << self; self end
end
protected
def __meta
@meta = singleton_type
@@inst = self
@meta.instance_eval do
@inst = @@inst
end
@meta
end
end

class A; end
class B < A; end

class C < B
def initialize num
@num = num
end
def inspect; @num.inspect end
alias :to_s :inspect
end

def class_chain klass
unless klass.level.zero? && klass.singleton?
puts klass.superclasses.join(" < ")
else
res = klass.superclasses
puts res.shift.to_s.concat(" << ").concat(res.join(" < "))
end
end

# Examples

class_chain C.meta
class_chain Class.meta
class_chain C.new({}).meta
class_chain Math::E.meta

puts "\n\"Higher\" order\n\n"

class_chain Object.meta(2)
class_chain C.meta(2)
class_chain Math::PI.meta(2)
class_chain Module.meta(3)
class_chain C.meta(3)


n = 0
ObjectSpace.each_object(Class) do |klass| klass
n+=1 if klass.singleton?
end
puts "\nNumber of Singletons controlled by GC == #{n}"

----
C_Meta < B_Meta < A_Meta < Object_Meta < Class < Module < Object
Class_Meta < Module_Meta < Object_Meta < Class < Module < Object
C_Sing({}) << C < B < A < Object
Float_Sing(2.718281828) << Float < Numeric < Object

"Higher" order

Object_Meta_Meta < Class < Module < Object
C_Meta_Meta < Class < Module < Object
Float_Sing(3.141592654)_Meta < Class < Module < Object
Module_Meta_Meta_Meta < Class < Module < Object
C_Meta_Meta_Meta < Class < Module < Object

Number of Singletons controlled by GC == 0
----

Alexander Schofield

unread,
Feb 13, 2002, 7:07:58 PM2/13/02
to
> "Alan Stern" <st...@rowland.org> wrote in,
> ...
> > This is currently under discussion in a separate thread. I think a
> > consensus is growing that class variables really ought to behave more
> > like instance variables of the class itself, with appropriate accessor
> > methods.

Here here. After reading about Self
http://research.sun.com/self/language.html a while back I am in full
agreement. No classes at all. The interesting thing about Self is that
it could easily simulate any class-based OO lang (multiple or single
inheritence, or some other type of mixin facility) without much of a
MOP, and requires no special semantics to practice Subject-Oriented
programming other than an understanding of what it is. Of course the
only current Self implementation has a smalltalk-style workspace, and a
smalltalk-like syntax (along with no conditionals). Is it just me or do
other people feel like they are being strangled when trying to learn
(when most code is trivial) through this? Makes me wonder if the
Smalltalk crowd wouldn't be just a little bit larger today if they had
included something like irb (which set the learning process to
warp-speed for me) in the various standards. Their shells are just too
workspace-oriented; it's hard when you're first learning the language to
have learn a Graphics API to get a console when all you were hoping to
start with was say iterating over a collection; and every time you want
to do something requires you to reach for the mouse or twist your left
hand awkwardly for a key combination. END_RANT

A language which is to Self what Ruby is Smalltalk, that's something I'd
like to see.

Matz, you want to volunteer? :)

--
Alexander Schofield

Chr. Rippel

unread,
Feb 14, 2002, 6:25:10 AM2/14/02
to
"Alexander Schofield" <pc...@mailhost.njit.edu> wrote in
...

> Here here. After reading about Self
> http://research.sun.com/self/language.html a while back I am in full
> agreement. No classes at all. The interesting thing about Self is that
> it could easily simulate any class-based OO lang (multiple or single
> inheritence, or some other type of mixin facility) without much of a
...

Hm, one of the self team member Craig Chambers later became team leader
of the Cecil project http://www.cs.washington.edu/research/projects/cecil/
- a very advanced OO-language and which is extremely class oriented -
kind of interesting isn't it ...


/Christoph

Alexander Schofield

unread,
Feb 13, 2002, 10:07:51 PM2/13/02
to
Allow me to quote from the "Cecil" link on the page you provided:
"Cecil has a classless object model. Objects have methods attached
directly to them, without needing a separate
class to hold their format & behavior. One-of-a-kind objects with
their own behavior (e.g. true, false, nil, and other enumerated
constants) are easy to define."
also it is a, "simple prototype-based Object Model", which is at least
the same terminology that Self uses.

"subclasses" are only mentioned once, with the quotes.

But thank you for the link, I wasn't aware of Cecil's existence and
Vortex in particular looks fascinating. You have given me my, "new
language fix" for the week. :)

--
Alexander Schofield

Alexander Schofield

unread,
Feb 13, 2002, 11:11:19 PM2/13/02
to
Hmmph, but you do get the last laugh. You have destroyed about two
weeks of tinkering on my part. I was actually trying to wrestle
together an Object System along the lines of Self, using a prebuilt GC.
My intention had been to get that working, I've been using *XML* as
source until I could decide on a syntax (which was going to be as Ruby
as applicable and I could make it). Vortex appears to actually *be* a
very large superset of my project, "a language-independent optimizing
compiler infrastructure for object-oriented and other high-level
languages". Now if you take away the, "optimizing", the
"language-independent", and the "other high-level languages", you have
my pathetic foray into the interpreter business down to a tee. If they
could write a Cecil frontend for Vortex (which is itself written in
Cecil), it will certainly be possible for me (intelligence and time
permitting) to write something along the lines of what I had
envisioned-- what is to Self what Ruby is to Smalltalk. With Vortex it
looks like I might actually be able to throw multi-methods into the
mix. My "timetable", such as it was, has been thrown a curve-ball by
Vortex, and there's going to be a big-learning curve here (Cecil &
Vortex), but sometime in the forseeable future I hope to have a simple
interpreter With console and basic file I/O, strings, arrays and hashes,
and numbers (whose default behavior will be along the lines of ANSI CL--
5/2 is 5/2, not 2, since I prefer nice integer arithmetic by default and
realistically this project is only going to be used for my
self-gratification). Whenever I do get around to adding Regexes I'll
probably use something prepackaged like Henry Spencer's implementation,
though depending on how adventerous I'm feeling I might go by the Ruby
source to preserve as much commonality as possible.

So, again thanks for the pointer are probably in order.

Anyone want to help? No I imagine not, "Alex does not play well with
others". Would be nice to be on the other end of the YPIG (You Push
I'll Grunt) system though, makes me see pair programming in a whole new
light :).

And anyways, I've scared you all off with this ramble.

--
Alexander Schofield

Yukihiro Matsumoto

unread,
Feb 13, 2002, 11:07:16 PM2/13/02
to
Hi,

In message "Re: Name resolution in Ruby"


on 02/02/14, Alexander Schofield <pc...@mailhost.njit.edu> writes:

|A language which is to Self what Ruby is Smalltalk, that's something I'd
|like to see.

JavaScript?

|Matz, you want to volunteer? :)

Ruby already has features to prototype based programming, but it's not
practical since it does not allow singleton methods for immediates
(Fixnums, Symbols, Booleans, and nil).

matz.

David Simmons

unread,
Feb 14, 2002, 12:06:46 AM2/14/02
to
Have you looked at SmallScript?

It is a no-cost (free) superset of Smalltalk.

It is fast, modular (capable of building 3-10k apps/components), and the
core system has small footprint.

It has instance-specific behavior for any non-virtual object (which means
anything other than <Character> and <SmallInteger>).

It has multi-methods.

It is a hi-performance jitted language.

It has multiple-inheritance of behavior and mixin-agregation of
structure/fields. It provides first-class instantiatable interfaces on both
the class and per/instance level.

It offers a rich range of syntax including numerous forms for "self" like
usage. This includes a variety of intrinsic VM supported delegation
mechanisms that include virtual fields, AOP services (like around, before,
inner, after) methods, and a generalized facility for enabling per/instance
managed behavior to controlling all aspects of access/message-managed to an
object.

-- Dave S. [www.smallscript.org]

"Alexander Schofield" <pc...@mailhost.njit.edu> wrote in message
news:3C6B38E7...@mailhost.njit.edu...

Alexander Schofield

unread,
Feb 14, 2002, 2:14:57 AM2/14/02
to
David Simmons wrote:
> Have you looked at SmallScript?
<snip>

I'd seen it mentioned in comp.lang.smalltalk, but I hadn't realized it
was a *superset* of Smalltalk. The name's a little deceptive, I had
always thought of it as being more of a lightweight (read PHP). Thank
you for the information, the link, and, unless I'm mistaken, the
language. I will delve into this before I start, to mine for ideas as
well gain familiarity with. But I've gotten so excited about my little
project that I've got to go through with it. Keep in mind that I do not
intend to *use* my project for anything, just for self-improvement and
bragging-rights, and maybe the occasional quick foray into prototype
modelling for small stuff. I predict an early and obscure retirement
for this language, maybe I'll bring it out of mothballs every once in a
while to do some trivial text manipulation task just to prove to myself
it still works.

--
Alexander Schofield

Chr. Rippel

unread,
Feb 14, 2002, 6:29:03 PM2/14/02
to
"Alexander Schofield" <pc...@mailhost.njit.edu> wrote in
>
...
> So, again thanks for the pointer are probably in order.

I am glad you liked the pointer - the sources tree of the project seems to
be bit outdated however. With a bit of tinkering I could to compile
Cecil on cygwin (a couple of month ago) until the build process produced
the first executable in the actually Cecil source which promptly core dumps,
at which point my interest subsisted ....
I probably should try compiling Cecil on linux - please let know if you
have any more luck.

>
> Anyone want to help? No I imagine not, "Alex does not play well with
> others". Would be nice to be on the other end of the YPIG (You Push
> I'll Grunt) system though, makes me see pair programming in a whole new
> light :).

If you would implement my pet multi-object(class) idea I certainly would
not mind the pushing part;-)

>
...


> > Allow me to quote from the "Cecil" link on the page you provided:
> > "Cecil has a classless object model. Objects have methods attached
> > directly to them, without needing a separate
> > class to hold their format & behavior. One-of-a-kind objects with
> > their own behavior (e.g. true, false, nil, and other enumerated
> > constants) are easy to define."
> > also it is a, "simple prototype-based Object Model", which is at least
> > the same terminology that Self uses.
> >
> > "subclasses" are only mentioned once, with the quotes.

Hm, seems like my brain got used to the ``singleton type'' == ``singleton
class''
(also called refinement types) equivalence in Ruby that I forgot that Cecil
is
called ``class-less'' (in particular meta class-less) but not ``type-less''.
I guess a large part of my personal affection for Ruby comes from its clever mix
of regular classes and singleton classes (refinement types) which might be
rather unique in this particular incarnation(?).
There is the vague idea in the back of my mind that it ought to be possible
(disregarding the fact that I am utterly clueless of implementation issues) to
generalize Rubys (meta)class based object model in such why that it captures
Cecil greatest strength (and likely greatest weakness) of a strong multi-method
support.


/Christoph

Chr. Rippel

unread,
Feb 14, 2002, 6:27:12 PM2/14/02
to
"Yukihiro Matsumoto" <ma...@ruby-lang.org> wrote in
>
...

> Ruby already has features to prototype based programming, but it's not
> practical since it does not allow singleton methods for immediates
> (Fixnums, Symbols, Booleans, and nil).

Hm, the following

def x.foo; end

where x == nil,false or true always worked - the interpreter
only starts complaining if I do something like

class << nil; end,

but this is a pretty mood point since the NilClass and Boolean class are
build in OO-Singleton classes anyway - and I can always write

class NilClass
Pointless = "Const"
def each(*args); nil end
class << self;
def each_nil; yield nil end
end
end

/Christoph


Alexander Schofield

unread,
Feb 14, 2002, 10:41:28 PM2/14/02
to
"Chr. Rippel" wrote:
> If you would implement my pet multi-object(class) idea I certainly would
> not mind the pushing part;-)

If you want to experiment with MOP's, then a prototype-based system is
exactly what you are looking for. If you had trouble with Cecil there
is a Linux port of Self I've been using which seems stable enough:
http://www.gliebe.de/self/index.html
The concepts are simple enough, just create objects which behave an
awful lot like classes (and have objects with lots of convenient methods
for creating those "classes"). This is easier than it sounds with
prototypes where inheritence is dynamic.

--
Alexander Schofield

Christoph

unread,
Feb 19, 2002, 4:05:47 PM2/19/02
to
"Alexander Schofield" <pc...@mailhost.njit.edu> wrote in
...
> If you want to experiment with MOP's, then a prototype-based system is
> exactly what you are looking for. If you had trouble with Cecil there
> is a Linux port of Self I've been using which seems stable enough:
> http://www.gliebe.de/self/index.html

Thanks for this pointer.

> The concepts are simple enough, just create objects which behave an
> awful lot like classes (and have objects with lots of convenient methods
> for creating those "classes"). This is easier than it sounds with
> prototypes where inheritence is dynamic.

The nice thing about Cecil (over Self) by the way is that that it is text based,
in fact it is relatively easy to read. Also afaik Self does not support multiple
dispatch which is cutting down a lot on my excitement for the language ...


/Christoph


0 new messages