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

Comparison between Python and "Ruby"

22 views
Skip to first unread message

Ian Clarke

unread,
Oct 29, 1999, 3:00:00 AM10/29/99
to
Disclaimer out of the way, I was recently web surfing when I discovered
a link to a language called "Ruby" which seems to be similar to Python
in that it is a scripting language, and has good support for OO. Ruby's
home on the web is at http://www.ruby-lang.org/.

The makers of the language have even done a comparison with Python. In
it they make the following claims (the strange grammar is their's, not
mine):

Problems with Python are:

* incomplete OOP
* Some data (numerical, list, dictionary, string, etc.) are not
genuine
object.
* Extension modules in C don't realize genuine objects.
* Tiresome self. are required when each access to instance variable
* Functions are first class object (Of cource, we know it is not
weak)
del, len, etc. are not Object-Oriented. (There are __len__, etc. but
...)
* Ugly method calling for superclass
* No class method (module functions alternate it)
* No way to automatically convert between long integer and small
integer.
* Because there is no genuine GC, memory leak occur often
* Writing extension modules is bothersome (some betterments in 1.5)
* Tuple and list has overlap functionally (not serious)
* Function objects are accepted as arguments, but iterators are more
elegant.
* After all, declarations are featured (global)
* Slower than Ruby (may be improved?)

I am still trying to download a copy of Ruby to look at it myself,
however do people think these comments are justified?

Ian.

--
Ian Clarke Email: I.Cl...@strs.co.uk
Homepage: http://www.gnu.demon.co.uk/
Also see: http://freenet.on.openprojects.net/
"All we see and all we seem is but a dream within a dream"

Doug Landauer

unread,
Oct 29, 1999, 3:00:00 AM10/29/99
to
> Problems with Python are:
>

> * Tiresome self. are required when each access to instance variable

Not tiresome. I find the requirement of "self." to be
very beneficial whenever *reading* code. It clarifies the
distinction between local variable vs class instance.
A definite keeper for 2.0.


> * Ugly method calling for superclass

Ugly is one opinion.

> * No way to automatically convert between long integer and
> small integer.

Another strong benefit of python. Automatic conversions are
almost always completely evil. In C++, for example.


> * Because there is no genuine GC, memory leak occur often

Hmmm. "often"? I've never personally seen one in any of
my python.


> * Function objects are accepted as arguments, but iterators
> are more elegant.

Hey, scheme might be considered more elegant, too. But it does
*not* follow that programs written in scheme are more elegant.


> * After all, declarations are featured (global)

This one requires a lot more explanation. Anyone know what the
intended meaning of this point is?

> ... do people think these comments are justified?

Maybe some of the other ones might be.
--
Doug Landauer land...@apple.com (work)
land...@scruznet.com (not-work)

Martijn Faassen

unread,
Oct 29, 1999, 3:00:00 AM10/29/99
to
Ian Clarke <I.Cl...@strs.co.uk> wrote:
[quoted from the Ruby documention]
> Problems with Python are:

> * incomplete OOP

This is vague without more elaboration. It's either the class/type
difference they refer to later, or perhaps the lack of advanced
data hiding constructs (which I must say I don't miss).

Can't be interfaces, thought they'd be nice; I don't think they're
part of the Genuine OOP (tm) concept.

> * Some data (numerical, list, dictionary, string, etc.) are not
> genuine
> object.

They are real objects, they're just not real class instantiations. But they
behave like objects. The disadvantage is of course that they don't have classes
you can derive your own stuff from. In practice you don't do this a lot,
and in practice, there are classes like UserDict and UserList to take
care of this problem.

Still, this distinction doesn't feel clear, and it is something that people
want to address for Python 2.0.

> * Extension modules in C don't realize genuine objects.

For certain values of the word 'object', this is true. :) The classless
objects (they have 'types' instead) are implemented in C, while the
classy objects are generally implemented in Python. There are extension
systems muddle this difference, though. Personally I haven't worked
with them, though I know Zope uses ExtensionClasses.

> * Tiresome self. are required when each access to instance variable

Opinions differ on this one. The 'self.' prefix makes it very clear you
are dealing with a class variable. It also makes it clear that this is
actually exactly the same as an 'other.' prefix; the symmetry here is nice.

> * Functions are first class object (Of cource, we know it is not
> weak)

If it's not a weakness, what's the problem? :)

> del, len, etc. are not Object-Oriented. (There are __len__, etc. but
> ...)

There's a good reason for the 'del'; it removes a variable from
a namespace. Conceptually it works on the reference, not on the thing that
the reference refers to. Sort of like '=' for assignment, and we don't
complain about that one either. This is a FAQ.

len is a FAQ too; the idea is that the len() function is generic. Also that
it can be applied on object that don't have any methods.
But I'd agree one could argue about this one.

> * Ugly method calling for superclass

Agreed. Though fairly simple and flexible. But something nicer (what?) would
be nicer.

> * No class method (module functions alternate it)

Python's strong namespace support and module functions almost make class
methods unnecessary. (although this is helped by the fact that 'private'
data members (__foo) are not so commonly used in Python). Anyway, they'd
be nice to have, but it's certainly not terrible they're not there.



> * No way to automatically convert between long integer and small
> integer.

I'll leave this to someone else. Is this a problem? A feature?

> * Because there is no genuine GC, memory leak occur often

I'd say 'often' is an exaggaration, but of course GC is on lots of people's
wishlist for Python, so no argument here; this is a problem.

> * Writing extension modules is bothersome (some betterments in 1.5)

People more experienced with this can comment on this. Using SWIG certainly
isn't very difficult, though..

> * Tuple and list has overlap functionally (not serious)

No, not serious. The distinction is sometimes useful.

> * Function objects are accepted as arguments, but iterators are more
> elegant.

You can implement iterators in Python, though?
Better core level iterator support would be nice for Python 2.0, though
(for instance for loops could use them).

> * After all, declarations are featured (global)

Only if you want to change a global variable (which you're not supposed to
have lots of anyway, usually). If you want to use one it's no problem. But
agreed that the whole 'global' business is tricky.

> * Slower than Ruby (may be improved?)

Quite possible' don't know. Benchmarks..

> I am still trying to download a copy of Ruby to look at it myself,

> however do people think these comments are justified?

Most of them have a point, but the problems caused by these things are
generally not big. Some of these problems are seen by others as advantages.
All in all, if this is the worst list of problems one can come up with
for Python..it could've done far worse. :)

Regards,

Martijn
--
History of the 20th Century: WW1, WW2, WW3?
No, WWW -- Could we be going in the right direction?

Andrew Csillag

unread,
Oct 29, 1999, 3:00:00 AM10/29/99
to pytho...@python.org
Martijn Faassen wrote:
> > * No way to automatically convert between long integer and small
> > integer.
>
> I'll leave this to someone else. Is this a problem? A feature?

I rarely have problems with this since you can do 1+1L and get 2L....

> > * Writing extension modules is bothersome (some betterments in 1.5)
>
> People more experienced with this can comment on this. Using SWIG certainly
> isn't very difficult, though..

In my experience, unless ruby's extension interfaces is like tcl's which
while simple, isn't terribly powerful, Python's is simple enough (I've
been known for doing simple extension modules in about 3 minutes -- no
SWIG). But even complicated ones with SWIG aren't hard. Actually, even
without SWIG it isn't really hard, just boring since most of it is
boilerplate.

> > * Function objects are accepted as arguments, but iterators are more
> > elegant.
>
> You can implement iterators in Python, though?
> Better core level iterator support would be nice for Python 2.0, though
> (for instance for loops could use them).

I argue that simplicity is better than elegance most of the time, thus
function objects over iterators. Besides who wants to make an iterator
when you just want to pass a function you already have? Reminds me of
how you pass methods around in Java (make an instance of (usually) an
inner class that inherits from some interface that just calls the outer
class's method)... Grr...

>
> > I am still trying to download a copy of Ruby to look at it myself,
> > however do people think these comments are justified?
>
> Most of them have a point, but the problems caused by these things are
> generally not big. Some of these problems are seen by others as advantages.
> All in all, if this is the worst list of problems one can come up with
> for Python..it could've done far worse. :)

From what I saw, it looks like they tried to mix python and perl by
sticking the python down the camel's throat and got camel puke. You
have whitespace for indentation, but all the regexy crap and extraneous
?'s and $'s that make it ugly.

-lets-make-a-language-named-perl-so-we-can-cast-it-to-swine-ly yours,
Drew
--
import string,sys;t=string;f=t.index;j=t.join;print(lambda
s:j(map(lambda
x,s=s:x[:f(x,':')+2]+j(map(lambda y:'%02X'%ord(y),x[f(x,':')+2:]),'
'),map
(lambda i,s=s:("%04X: "%
i)+s[i:i+16],range(0,len(s),16))),'\n'))(open(sys.
argv[1]).read())

Ivan Van Laningham

unread,
Oct 29, 1999, 3:00:00 AM10/29/99
to Python Mailing List
Hi All--

Martijn Faassen wrote:
>
> Ian Clarke <I.Cl...@strs.co.uk> wrote:
> [quoted from the Ruby documention]
> > Problems with Python are:
>

[bobbitt]

> > * No way to automatically convert between long integer and small
> > integer.
>
> I'll leave this to someone else. Is this a problem? A feature?
>

I'll only address this issue, because it affects my Mayan code.

To me, it's a problem. It's a great big pain to have to be constantly
on the lookout for overflows and to remove 'L's from string
representations of longs. Sure, I could work completely with longs, but
a great deal of Mayan mathematics is done with small constant integers
(7, 13, 9, 260, 365, 819, 18980 and so on). I'm reluctant to convert
and lose the speed advantage for numbers in the range -MAXINT to
MAXINT. Someone else complained about transparent conversions being a
bad thing (tm), but for me they would be a *big* win. My code would
become much clearer.

At the same time, I can certainly see that others wouldn't like the
behavior that I would; not everyone is working with numbers and dates
large enough to take up significant amounts of memory (beside which mere
trillions of years pale). However, built in support for Very Large
Numbers is one of the reasons I *love* Python.

<one-person's-gigayear-is-another's-nanosecond>-ly y'rs,
Ivan
----------------------------------------------
Ivan Van Laningham
Callware Technologies, Inc.
iva...@callware.com
iva...@home.com
http://www.pauahtun.org
See also:
http://www.foretec.com/python/workshops/1998-11/proceedings.html
Army Signal Corps: Cu Chi, Class of '70
----------------------------------------------

Dirk Leas

unread,
Oct 29, 1999, 3:00:00 AM10/29/99
to LS, Python
I used to have a boss who'd say, "If I can't walk into 'da bookstore and
find at least two books on it, you ain't usin' it!".

Later,
D


Clemens Hintze

unread,
Oct 31, 1999, 2:00:00 AM10/31/99
to
>>>>> "Andrew" == Andrew Csillag <and...@starmedia.net> writes:

Andrew> Martijn Faassen wrote:

[...]

Andrew> In my experience, unless ruby's extension interfaces is
Andrew> like tcl's which while simple, isn't terribly powerful,

Ahem... I have written extensions in both Python *and* Ruby. Would you
please enlight me, why do you think Ruby interface isn't powerful
compared with Python's one? I had the opposite impression. :-/

Andrew> Python's is simple enough (I've been known for doing
Andrew> simple extension modules in about 3 minutes -- no
Andrew> SWIG). But even complicated ones with SWIG aren't hard.
Andrew> Actually, even without SWIG it isn't really hard, just
Andrew> boring since most of it is boilerplate.

All that is also true for Ruby! And you have forgot to compare garbage
collection issues which have to be addressed both in Python and
Ruby. While Python use a refcount scheme, where you have to address
that issue yourself, Ruby use true garbage collection (mark and sweep
scheme), so that you have not to deal with it at all.

Under some circumstances, you have to provide up to two function in your
Ruby extension. One function that mark Ruby objects, stored in your
extension, alive (if there are some), one that free the memory of your
own occupied memory (normally 'free' is enough). I wish Python would
be so easy here!

>> > * Function objects are accepted as arguments, but iterators
>> are more > elegant.
>>
>> You can implement iterators in Python, though? Better core
>> level iterator support would be nice for Python 2.0, though
>> (for instance for loops could use them).

Andrew> I argue that simplicity is better than elegance most of
Andrew> the time, thus function objects over iterators. Besides
Andrew> who wants to make an iterator when you just want to pass a

That doesn't score very well, IMHO. My question to your question would
be: who likes to write an own function for something that is only used
one time and therefor better be stick into an block. Perhaps there is
a misunderstanding for iterators. The word was a little bit misleading
used in the Ruby documentation, IMHO. But now they have correct the
usage.

Andrew> function you already have? Reminds me of how you pass
Andrew> methods around in Java (make an instance of (usually) an
Andrew> inner class that inherits from some interface that just
Andrew> calls the outer class's method)... Grr...

It reminds me, more of the way how Smalltalk pass methods! Ruby is
(except syntax) more like Smalltalk, than like Java!

[...]

Andrew> From what I saw, it looks like they tried to mix python
Andrew> and perl by sticking the python down the camel's throat

What?!? Do you really saw it? Can it be that you have only had a
glance to the syntax, and therefore decided it's like Perl => crap!

Andrew> and got camel puke. You have whitespace for indentation,

Okay! Now I am convinced that you never have really looked at Ruby too
close. Perhaps only a small blink on it! Ruby *does*not* use
whitespaces (unfortunately, cause I like them :-)!

Ruby has in common with Python its consistent behavior, its simplicity
and its easy extension writing. It shares with Perl the speed and much
of the syntax; but not the context dependend behavior, that makes it
so diffcult for beginners to learn Perl.

There is e.g. a syntax for creating regexps, but these are objects
then, like in Python. And it also has many many things in common with
Smalltalk (Ruby is totally OOL). Even a '1' is an instance of class
Fixnum *unlike* Python & Perl!

Andrew> but all the regexy crap and extraneous ?'s and $'s that
Andrew> make it ugly.

I don't think, that the regexp stuff is crab! If you want, you can
also use the Python way:

regex = Regexp.new("^(S+)") # Or use: regex = /^(\S+)/
regex =~ "hello world" # Or use "hello world" =~ regex

Perl is (whether we like it or not) the most used language for
sysadmin and web purposes till today. So there are many programs and
modules already available. To ease the port of them, was one of the
issues, why matz has decided to introduce these ugly variables. I
don't like them, but I can live with them. Hey, there are also things
I don't like in Python, but they doesn't necessarily make the language
worse for me.

Andrew> -lets-make-a-language-named-perl-so-we-can-cast-it-to-swine-ly
Andrew> yours, Drew

-be-not-so-biased-towards-one-language-
-there-is-no-only-one-
-all-is-a-matter-of-taste-ly yours Clemens.

[...]

Dale Nagata

unread,
Oct 31, 1999, 2:00:00 AM10/31/99
to
Ian Clarke wrote:
> * No way to automatically convert between long integer and small
> integer.

C:\>python
Python 1.5.1 (#0, Oct 14 1998, 20:14:21) [MSC 32 bit (Intel)] on win32
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> int(1L)
1
>>> long(1)
1L


--
Dale Nagata | tel : +1 604.451.2700 ext. 2254 (UTC-0800)
Software Developer | fax : +1 604.437.9891
Creo Products Inc. | pgr : +1 604.691.8279
Burnaby BC Canada | http://www.creo.com/

Yukihiro Matsumoto

unread,
Nov 1, 1999, 3:00:00 AM11/1/99
to
Hi,

Ian Clarke <I.Cl...@strs.co.uk> writes:

|Problems with Python are:

They are intended to be differences, not problems, OK?

Python is good enough to satisfy many, but some (including me, the
designer of the Ruby language) perfer Ruby. TMTOWTDI.

matz.

Hrvoje Niksic

unread,
Nov 1, 1999, 3:00:00 AM11/1/99
to
Dale Nagata <dna...@creo.com> writes:

> Ian Clarke wrote:
> > * No way to automatically convert between long integer and small
> > integer.
>
> C:\>python
> Python 1.5.1 (#0, Oct 14 1998, 20:14:21) [MSC 32 bit (Intel)] on win32
> Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
> >>> int(1L)
> 1
> >>> long(1)
> 1L

That doesn't look "automatically" to me.

>>> sys.maxint + 1
Traceback (innermost last):
File "<stdin>", line 1, in ?
OverflowError: integer addition
>>> (long(sys.maxint) + 1) - 1
2147483647L

I've never seen Ruby so I don't know what it does, but in these cases
Lisp will do the right thing. Example using CLISP:

[1]> (type-of most-positive-fixnum)
FIXNUM
[2]> (type-of (1+ most-positive-fixnum))
BIGNUM
[3]> (type-of (1- (1+ most-positive-fixnum)))
FIXNUM
[4]> (1+ 99999999999999999)
100000000000000000

In Lisp, you can use fixnums (Python ints) and bignums (Python longs)
interchangeably. Which is a very nice feature.

Martijn Faassen

unread,
Nov 1, 1999, 3:00:00 AM11/1/99
to
Yukihiro Matsumoto <ma...@netlab.co.jp> wrote:
> Ian Clarke <I.Cl...@strs.co.uk> writes:

> |Problems with Python are:

> They are intended to be differences, not problems, OK?

Ok. :) Ruby sounds cool enough. It's received attention from several
Pythoneers in the past, I think, looking at its implementation of classes
for everything, and at its garbage collection system.

From what I hear in this thread its C interfacing would also be interesting
to compare with Python's, especially since Ruby uses garbage collection,
which is something Python's looking at using in the future, in some
way.

> Python is good enough to satisfy many, but some (including me, the
> designer of the Ruby language) perfer Ruby. TMTOWTDI.

Agreed. This isn't a flamewar anyway. Ian Clarke chose a far more civilized
title to his post than he did a while back in comp.lang.perl. ;)

What-does-TMTOWTDI-stand-for?-ly yours,

Gordon McMillan

unread,
Nov 1, 1999, 3:00:00 AM11/1/99
to Martijn Faassen, pytho...@python.org
Martijn Faassen asks:

> What-does-TMTOWTDI-stand-for?-ly yours,

That's the Perler's war cry. Snort. As if there was only one
way to have more than one way to do it.

(As used by Matz, of course, it does not qualify as an
oxymoron.)

- Gordon

Aahz Maruch

unread,
Nov 1, 1999, 3:00:00 AM11/1/99
to
In article <7vjtrc$hmm$1...@newshost.accu.uu.nl>,
Martijn Faassen <m.fa...@vet.uu.nl> wrote:
>
>What-does-TMTOWTDI-stand-for?-ly yours,

It's the Perl motto: "There's More Than One Way To Do It"
--
--- Aahz (@netcom.com)

Androgynous poly kinky vanilla queer het <*> http://www.rahul.net/aahz/
Hugs and backrubs -- I break Rule 6 (if you want to know, do some research)

Yukihiro Matsumoto

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to

Greg Ewing <greg....@compaq.com> writes:

|Okay, so the Python war cry should be TMTOWTHMTOWTDI
|(There's More Than One Way To Have More Than One Way
|To Do It).

According to Guido's Foreword from Programming Python:

Readability is often enhanced by reducing unnecessary variability.
When possible, there's single, obvious way to code a particular
construct. This reduces the number of the choices facing the
programmer who is writing the code, and increases the chance that
it will appear familiar to a second programmer reading it.

I guess he loves reducing variablity, if possible, which is totally
against TMTOWTDI. I don't judge whether it is good or bad.

matz.

Fredrik Lundh

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to Yukihiro Matsumoto
Yukihiro Matsumoto <ma...@netlab.co.jp> wrote:
> I guess he loves reducing variablity, if possible, which is totally
> against TMTOWTDI. I don't judge whether it is good or bad.

you're confusing syntax with semantics.

there are MANY ways to solve any given problem
in Python, but when you've decided that you want
to use a certain pattern (be it a loop, an iterator,
an object factory, or any other pydiom) in your
solution, there's usually ONE way to write the
code.

think about it.

</F>

<!-- (the eff-bot guide to) the standard python library:
http://www.pythonware.com/people/fredrik/librarybook.htm
-->


Ian Clarke

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to

> Agreed. This isn't a flamewar anyway. Ian Clarke chose a far more civilized
> title to his post than he did a while back in comp.lang.perl. ;)

Ugh, me civilized? Now there is flamebait if I ever saw it ;-)

Gerrit Holl

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to pytho...@python.org
Yukihiro Matsumoto wrote:
>
> I guess he loves reducing variablity, if possible, which is totally
> against TMTOWTDI. I don't judge whether it is good or bad.
>

Are there people who see TMTOWTDI [1] as an advantage?

[1]
There's more than one way to do it.

regards,
Gerrit.
--
linuxgames.nl.linux.org All about games on Linux in Dutch (under construction).
www.nl.linux.org The Dutch resource for Dutch Linux documentation.
www.nl.linux.org/discoverb Learn foreign words and definitions.
www.nl.linux.org/~gerrit/asperger I'm an Asperger, go here for more info.
www.nl.linux.org/~gerrit About me and pictures of me.

Robin Becker

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to
In article <1999110215...@optiplex.palga.uucp>, Gerrit Holl
<gerri...@pobox.com> writes

>Yukihiro Matsumoto wrote:
>>
>> I guess he loves reducing variablity, if possible, which is totally
>> against TMTOWTDI. I don't judge whether it is good or bad.
>>
>
>Are there people who see TMTOWTDI [1] as an advantage?
>
>[1]
>There's more than one way to do it.
>
>regards,
>Gerrit.
well I guess if the mathematica guys are right, having every known
programming language simultaneously available allows you to just learn
mathematica
-symbolically confused-ly yrs-
Robin Becker

Gordon McMillan

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to Yukihiro Matsumoto, pytho...@python.org
Yukihiro Matsumoto wrote:

> "Fredrik Lundh" <fre...@pythonware.com> writes:
>
> |> I guess he loves reducing variablity, if possible, which is
> totally |> against TMTOWTDI. I don't judge whether it is good or

> bad. | |you're confusing syntax with semantics.
>
> I don't think so. I don't believe anyone can reduce semantic
> variability. Thus TMTOWTDI applies to semantics AND syntax.

Did you mean to write what you wrote? From your premise, I
would reach the opposite conclusion. Or are you saying that
Guido also failed to reduce syntactic variability?

The problem with TMTOWTDI as used by Perlers is that they
assume that because it is rare in Python for a given syntactic
element to have an alternate form, that all successful attempts
to solve a problem will have the same form.

A few years ago there were 19 different solutions posted to the
problem of removing duplicates from a list, employing at least
a half dozen distinctly different algorithms.

The same contest on c.l.pl.* might yield hundreds of
solutions, but I doubt that the underlying algorithms would
expand beyond that half dozen.

So I'd tend to agree with "I don't believe anyone can reduce
semantic variability", but I would conclude that there's no
connection between the syntactic and semantic levels.

> But it's OK. I'm not Larry Wall nor Perl freak.
>
> I just felt weird when Pythoneers say about TMTOWTDI or even
> TMTOWTHMTOWTDI.
> matz.
>
> --
> http://www.python.org/mailman/listinfo/python-list

- Gordon

Clemens Hintze

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to
>>>>> "Gerrit" == Gerrit Holl <gerri...@pobox.com> writes:

Gerrit> Yukihiro Matsumoto wrote:
>> I guess he loves reducing variablity, if possible, which is
>> totally against TMTOWTDI. I don't judge whether it is good or
>> bad.
>>

Gerrit> Are there people who see TMTOWTDI [1] as an advantage?

Normally ... yes, I do! I do not like Python, because it only offers
one way. I don't try to avoid Perl, because it offers more than one
way. :-)

Gerrit> [1] There's more than one way to do it.

[...]

Clemens

Thomas A. Bryan

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to
Gerrit Holl wrote:
>
> Yukihiro Matsumoto wrote:
> >
> > I guess he loves reducing variablity, if possible, which is totally
> > against TMTOWTDI. I don't judge whether it is good or bad.
> >
>
> Are there people who see TMTOWTDI [1] as an advantage?
> [1]
> There's more than one way to do it.

Yes, there are. Larry Wall's speeches (Wall is the Guido of Perl)
often proclaim that the problem with many programming languages
is that they enforce too many restrictions on the programmer and
his code. Thus, given a problem, the programmer first has to map
that problem onto what is permitted by the language. The less
flexibility the language offers, the more difficult this mapping
process can be for more problems. Perl is supposed to reduce the
amount of mapping that a programmer has to do before implementation.

It's an interesting concept, but I don't know whether I agree that
this aspect of Perl is a "feature." I haven't been programming long
enough to decide. Some experienced C/C++ software engineers that
I've known complain that Larry Wall is ignoring the years of industry
and academic wisdom in software engineering when he says things like
that. Code typically spends a lot of time in maintenance by a lot
of different people. (If it doesn't, it simply dies.) If a language
offers too much flexibility, then it doesn't matter if you know the
language. You still may have a really hard time understanding someone
else's code in that language. If you think about it, a lot of people's
Python code looks very similar in structure and syntax. I don't think
that's as true in the Perl world.

In my own personal experience, I've never had trouble reading other
people's Python code. I often have to struggle through other people's
Perl code. Even when I knew more Perl than Python, this statement was
still true. When I read Perl code, I spent too much of the time
figuring out *how* the code worked instead of figuring out *what* the
code was doing. I suspect that this difficulty was due in part to
the fact that Perl has more Perl hackers than Python has Pythonistas.
Thus, it also has more *bad* programmers producing *bad* code.

To keep myself from rambling too much, I'll summarize by simply saying
that if Python is more restrictive than Perl, I've never noticed it, and
I've never felt that my options were limited in Python. On the other
hand, when I go to the more flexible world of Perl, I seem to spend a
lot of time just dealing with the language. Python gives me sufficient
power and flexibility but then stays out of my way and lets me think
about data structures, algorithms, and design patterns.

I'll close with something Tim Peters posted once about "The Python Way."
Note the item about "only one obvious way." There might be other ways,
but they're usually non-obvious and not often used in Python.

"""Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those! """

---Tom

Mike Fletcher

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to pytho...@python.org
Okay, that reminds me, when is this going to make it into the official
documentation? If it were me, I'd put it right onto the first page
(doc/index.html) of the official docs, right under the listing of available
documents ;) . It does such a great job of getting people into the "frame"
of Python (at least those with some background in computer programming).

So, how about it? And lets start a Python monastery somewhere, I'd look
great in a black-and-green robe ;) ,
Mike

...


Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

-- Tim Peters


Greg Ewing

unread,
Nov 3, 1999, 3:00:00 AM11/3/99
to
Gordon McMillan wrote:
>
> That's the Perler's war cry. Snort. As if there was only one
> way to have more than one way to do it.

Okay, so the Python war cry should be TMTOWTHMTOWTDI
(There's More Than One Way To Have More Than One Way
To Do It).

Greg

Yukihiro Matsumoto

unread,
Nov 3, 1999, 3:00:00 AM11/3/99
to
"Fredrik Lundh" <fre...@pythonware.com> writes:

|> I guess he loves reducing variablity, if possible, which is totally
|> against TMTOWTDI. I don't judge whether it is good or bad.
|

|you're confusing syntax with semantics.

I don't think so. I don't believe anyone can reduce semantic
variability. Thus TMTOWTDI applies to semantics AND syntax.

But it's OK. I'm not Larry Wall nor Perl freak.

Neel Krishnaswami

unread,
Nov 3, 1999, 3:00:00 AM11/3/99
to
Thomas A. Bryan <tbr...@python.net> wrote:
>
>Yes, there are. Larry Wall's speeches (Wall is the Guido of Perl)
>often proclaim that the problem with many programming languages
>is that they enforce too many restrictions on the programmer and
>his code. Thus, given a problem, the programmer first has to map
>that problem onto what is permitted by the language. The less
>flexibility the language offers, the more difficult this mapping
>process can be for more problems. Perl is supposed to reduce the
>amount of mapping that a programmer has to do before implementation.

The only languages that have taken this idea seriously is the Lisp
family, which have macro systems that basically allow the programmer
to extend the language. In short: the Lisps have an extensible syntax,
where Perl just has an extensive syntax.

Python (and Ruby, for that matter) remind me more of Smalltalk than
anything else -- ie, they have extensive libraries, a community with a
love of elegance but not of purity[*], and a greater focus on practical
applications than on academic research.

The differences are that there's less of a closed-world attitude in
Python than in the ST world, though -- Python can be used for sysadmin
work where ST (even Squeak) wouldn't be a natural fit. But on the flip
side Smalltalk has always had a stronger focus on UI and dev
environments. This is changing, though -- the ST culture is beginning
to value the ability to deal with the world outside the system image,
and Guido's latest enthusiasm is "computer programming for everybody"
(which is a very ST-ish sort of idea).


Neel

Dave Cole

unread,
Nov 3, 1999, 3:00:00 AM11/3/99
to

> * The mechanism for associating methods with object types
> is somewhat simpler in Ruby. In Python, some methods live
> in slots in the type object, while others live in a method
> table or are somehow otherwise accessed through the getattr
> method. In Ruby, all methods, including the ones for built
> in operations, are attached to the object's class, which seems
> to play the role of both the Python type object and method
> table. The initialisation function of the Ruby dbm module
> starts off like this:
>
> void
> Init_dbm()
> {
> cDBM = rb_define_class("DBM", rb_cObject);
> rb_include_module(cDBM, rb_mEnumerable);
>
> rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1);
> rb_define_singleton_method(cDBM, "new", fdbm_s_open, -1);
> rb_define_method(cDBM, "close", fdbm_close, 0);
> rb_define_method(cDBM, "[]", fdbm_fetch, 1);
> rb_define_method(cDBM, "[]=", fdbm_store, 2);
> rb_define_method(cDBM, "indexes", fdbm_indexes, -1);
>
> etc. There is no need to declare and initialise a type object
> or method table as in the Python version, which makes things
> somewhat more direct and easier to follow.

Couldn't you achieve the same thing in Python with an API that
allocated the PyTypeObject on the heap and returned a handle/pointer
to that. It could also provide an internal tp_getattr which scanned
the method table you built up via method registration functions in the
same API.

- Dave

Jim Althoff

unread,
Nov 3, 1999, 3:00:00 AM11/3/99
to ne...@alum.mit.edu, pytho...@python.org
At 03:42 AM 11/3/99 +0000, Neel Krishnaswami wrote:
. . .

>
>The differences are that there's less of a closed-world attitude in
>Python than in the ST world, though -- Python can be used for sysadmin
>work where ST (even Squeak) wouldn't be a natural fit. But on the flip
>side Smalltalk has always had a stronger focus on UI and dev
>environments. This is changing, though -- the ST culture is beginning
>to value the ability to deal with the world outside the system image,
>and Guido's latest enthusiasm is "computer programming for everybody"
>(which is a very ST-ish sort of idea).

Absolutely right. Part of the original dream of the Smalltalk development
team was to build a programming language/environment that would be so
easy that anybody -- even kids -- could use it. Hence the name "Smalltalk".

Jim


Paul Prescod

unread,
Nov 3, 1999, 3:00:00 AM11/3/99
to ne...@alum.mit.edu
Neel Krishnaswami wrote:
>
> Python (and Ruby, for that matter) remind me more of Smalltalk than
> anything else -- ie, they have extensive libraries, a community with a
> love of elegance but not of purity[*], and a greater focus on practical
> applications than on academic research.

Isn't the Smalltalk community pretty enamored of purity? I mean "if" is
an object that takes messages, right?

Paul Prescod

Guido van Rossum

unread,
Nov 3, 1999, 3:00:00 AM11/3/99
to
Greg Ewing <greg....@compaq.com> writes:

> * The names of the Ruby interface routines are often
> shorter than the equivalent Python ones.

Python used to have short names too, and in fact the current naming
scheme was intruduced with great reluctance. Unfortunately the
realities of embedding Python in other apps required the current
longer names, to avoid name clashes between Python macros, types and
externals and ditto defined by the embedding app. Extension modules
wrapping large existing libraries also ran into this.

> * Ruby seems to be able to raise exceptions without
> having to explicitly propagate them back out of routines,
> which eliminates a lot of result testing and returning of
> -1's and None's that goes on in Python extension code.

Does it use longjmp to do this? Or is it written in C++ and using C++
exceptions? Note that longjmp is a frequent cause of nasty
portability problems (e.g. recently a bug reported on FreeBSD when
combining threads and readline was discovered to be caused by a bug in
the longjmp implementation).

Or perhaps it has macros containing return statements? (Yuck!)

> Some other observations, in no particular order:
>
> * In Ruby, routines with a fixed number of arguments can
> be defined so that they are received as separate C
> arguments instead of a vector, e.g.
>
> static VALUE
> fdbm_store(obj, keystr, valstr)
> VALUE obj, keystr, valstr;
>
> This doesn't actually save much code, however, since you
> still have to test and convert each argument.

How does Ruby know how many arguments the C code has???

> * Ruby's method of representing an extension type is a
> whisker more complicated. Instead of allocating a single
> object, you have to create an object of type DATA, which
> contains a pointer to a class and a pointer to a C
> structure.


>
> * The mechanism for associating methods with object types
> is somewhat simpler in Ruby. In Python, some methods live
> in slots in the type object, while others live in a method
> table or are somehow otherwise accessed through the getattr
> method. In Ruby, all methods, including the ones for built
> in operations, are attached to the object's class, which seems
> to play the role of both the Python type object and method
> table.

I agree that this would be a desirable design for a future Python
implementation.

--Guido van Rossum (home page: http://www.python.org/~guido/)

Bijan Parsia

unread,
Nov 3, 1999, 3:00:00 AM11/3/99
to
Paul Prescod <pa...@prescod.net> wrote:

Close. Boolean's are objects which take the messages ifTrue:, ifFalse:,
ifTrue:ifFalse:, ifFalse:ifTrue:, whileTrue:, etc.

All control structures are messages (typically taking blocks--aka
anonymous functions arguments):

4 timesRepeat: [self beep]. "This is a message to an Integer."
#(1 2 3) do: [:item | Transcript cr; show: item printString].
"do: is sent to the array (the sharp parens is the literal). The block
has one parameter, internally know as 'item'). The semi-colon means to
send the next message to the same object, i.e., Transcript. Thus
Transcript gets two messages, cr and show:."

Etc.

The only non-message type thing I can think of off-hand is the
assignment operator. Well, and the cascade.

Cheers,
Bijan Parsia.

Greg Ewing

unread,
Nov 4, 1999, 3:00:00 AM11/4/99
to
Martijn Faassen wrote:
>
> From what I hear in this thread its C interfacing would also be interesting
> to compare with Python's, especially since Ruby uses garbage collection,
> which is something Python's looking at using in the future, in some
> way.

Okay, here are some thoughts following a brief time looking
at and comparing the "dbm" module implementations from Ruby
and Python.

The first observation is that the Ruby version is 13K in
size, whereas the Python version is only about 7.5K.
However, this is not a fair comparison, because the Ruby
version defines more methods.

Eyeballing the code, I must say that the Ruby version
generally looks neater and tidier. Some reasons for this
seem to be:

* The names of the Ruby interface routines are often
shorter than the equivalent Python ones.

* Checking types of arguments and raising errors seems to
be easier in the Ruby version, e.g. Ruby

Check_Type(keystr, T_STRING);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;

vs. Python

if ( !PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
PyErr_SetString(PyExc_TypeError,
"dbm mappings have string indices only");
return -1;
}

The Ruby version isn't all that much shorter, but it
looks neater. On the other hand, the Python version manages
to produce a more specific error message; if the Ruby
version did that too, it would be longer.

* Since Ruby has mark-and-sweep garbage collection, there
is no manipulation of reference counts. There weren't
actually any examples of this in the Python dbm module,
though.

* Ruby seems to be able to raise exceptions without
having to explicitly propagate them back out of routines,
which eliminates a lot of result testing and returning of
-1's and None's that goes on in Python extension code.

Some other observations, in no particular order:

* In Ruby, routines with a fixed number of arguments can
be defined so that they are received as separate C
arguments instead of a vector, e.g.

static VALUE
fdbm_store(obj, keystr, valstr)
VALUE obj, keystr, valstr;

This doesn't actually save much code, however, since you
still have to test and convert each argument.

* Ruby's method of representing an extension type is a


whisker more complicated. Instead of allocating a single
object, you have to create an object of type DATA, which
contains a pointer to a class and a pointer to a C
structure.

* The mechanism for associating methods with object types
is somewhat simpler in Ruby. In Python, some methods live
in slots in the type object, while others live in a method
table or are somehow otherwise accessed through the getattr
method. In Ruby, all methods, including the ones for built
in operations, are attached to the object's class, which seems
to play the role of both the Python type object and method

table. The initialisation function of the Ruby dbm module
starts off like this:

void
Init_dbm()
{
cDBM = rb_define_class("DBM", rb_cObject);
rb_include_module(cDBM, rb_mEnumerable);

rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1);
rb_define_singleton_method(cDBM, "new", fdbm_s_open, -1);
rb_define_method(cDBM, "close", fdbm_close, 0);
rb_define_method(cDBM, "[]", fdbm_fetch, 1);
rb_define_method(cDBM, "[]=", fdbm_store, 2);
rb_define_method(cDBM, "indexes", fdbm_indexes, -1);

etc. There is no need to declare and initialise a type object
or method table as in the Python version, which makes things
somewhat more direct and easier to follow.

Summary:

Ruby extension modules seem to be slightly easier to write and
read than Python ones. The main reasons for this are the lack
of reference counting, a less obtrusive exception propagation
mechanism, and a more uniform notion of types and classes.
There are also some minor conveniences, such as C methods which
take an ordinary argument list instead of a vector. The
broad approach to exension writing is, however, fairly similar
in both systems.

Tomorrow I may take a deeper look at how Ruby unifies types
and classes and see whether there is anything there that
Python could learn from.

Greg

Doug Way

unread,
Nov 4, 1999, 3:00:00 AM11/4/99
to
In article <slrn81ve6m...@brick.cswv.com>,

ne...@alum.mit.edu wrote:
>
> Python (and Ruby, for that matter) remind me more of Smalltalk than
> anything else -- ie, they have extensive libraries, a community with a
> love of elegance but not of purity[*], and a greater focus on
practical
> applications than on academic research.
>
> The differences are that there's less of a closed-world attitude in
> Python than in the ST world, though -- Python can be used for sysadmin
> work where ST (even Squeak) wouldn't be a natural fit. But on the flip
> side Smalltalk has always had a stronger focus on UI and dev
> environments. This is changing, though -- the ST culture is beginning
> to value the ability to deal with the world outside the system image,
> and Guido's latest enthusiasm is "computer programming for everybody"
> (which is a very ST-ish sort of idea).
>
> Neel

Smalltalk is sort of on the "other side" of Python from Perl in a lot of
ways. Smalltalk's syntax is considerably pared down from even Python's
not-too-complex syntax. In other words, if you hate Perl, you might
really like Smalltalk. :-) (Randal Schwartz might disagree with me
here, 'cause I know he's on the Squeak list...)

I agree with Neel about the differences that exist. Python does
interact with the outside world better, but Smalltalk's dev tools really
are great, and are easy to tweak to suit your own needs, since
everything's written in Smalltalk and the source is right there.

From a historical point of view, Smalltalk is a little like Lisp, in
that it's a little outside of the mainstream, but it has enough new
ideas in it that will give it a very long lifespan. Smalltalk will
still be relevant 20 years from now, just as Lisp-based languages are
still reasonably relevant today, after 40 years. I suppose "having a
lot of new ideas" and "being a little outside of the mainstream" go hand
in hand. (Smalltalk isn't *that* obscure, though... there are more
Smalltalk programming jobs available than, say, Python or Lisp jobs.)

Contrast this with a mainstream language like Java, which will have a
huge spike in popularity for a few years, but since it's mostly just a
cleaned-up version of another language (C++), it won't be cutting-edge
for very long. Which isn't to say that it will dissappear, just that it
will be easier to replace with something better as the new "King of the
Mainstream Programming Languages" in a few years.

In any case, Smalltalk is definitely worth exploring if you're looking
at programming languages similar to Python. See http://squeak.org,
http://www.goodstart.com/dialects.html, etc.

- Doug Way
EAI/Transom Technologies, Ann Arbor, MI
http://www.transom.com
dw...@mat.net, @eai.com


Sent via Deja.com http://www.deja.com/
Before you buy.

Greg Ewing

unread,
Nov 4, 1999, 3:00:00 AM11/4/99
to
Fernando Pereira wrote:
>
> What's the effect of this on portability? For instance, how are
> pointers to live objects from the C stack handled? As is well-known,
> this cannot be done portably.

It scans the whole C stack and marks anything that looks like
it might be a pointer to a Ruby object. It assumes that setjmp()
saves any registers that might contain such pointers. There are
a few special cases coded in. Porting to a new system might
require this piece of code to be adjusted, although it looks
to me like it should work under most sensible architectures.

Global variables in C extensions which contain Ruby pointers
have to be explicitly made known during initialisation.

> > * Ruby seems to be able to raise exceptions without
> > having to explicitly propagate them back out of routines,

> Same comment. There is no portable way of unwinding the C stack. What
> does that mean for Ruby's portability?

It uses setjmp/longjmp. Presumably these work correctly on
any system where they are implemented. Porting Ruby to a
system where they're not implemented could be difficult.

Greg

Yukihiro Matsumoto

unread,
Nov 4, 1999, 3:00:00 AM11/4/99
to
Fernando Pereira <per...@research.att.com> writes:

|> * Since Ruby has mark-and-sweep garbage collection, there
|> is no manipulation of reference counts. There weren't
|> actually any examples of this in the Python dbm module,
|> though.

|What's the effect of this on portability? For instance, how are
|pointers to live objects from the C stack handled? As is well-known,
|this cannot be done portably.

See Greg Ewing's article at <38215CE7...@compaq.com>.
In summary, Ruby is fairly portable, but if your first
priority is the portability, Python wins.

matz.

Yukihiro Matsumoto

unread,
Nov 4, 1999, 3:00:00 AM11/4/99
to
Guido van Rossum <gu...@cnri.reston.va.us> writes:

|Does it use longjmp to do this? Or is it written in C++ and using C++
|exceptions? Note that longjmp is a frequent cause of nasty
|portability problems (e.g. recently a bug reported on FreeBSD when
|combining threads and readline was discovered to be caused by a bug in
|the longjmp implementation).
|
|Or perhaps it has macros containing return statements? (Yuck!)

It's using longjmp. We haven't met longjmp's nasty portability
problems yet, for 6 years.

|> This doesn't actually save much code, however, since you
|> still have to test and convert each argument.
|

|How does Ruby know how many arguments the C code has???

It's part of the method attribute. C functions are registered with
the number of arguments they accept.

|> * The mechanism for associating methods with object types
|> is somewhat simpler in Ruby. In Python, some methods live
|> in slots in the type object, while others live in a method
|> table or are somehow otherwise accessed through the getattr
|> method. In Ruby, all methods, including the ones for built
|> in operations, are attached to the object's class, which seems
|> to play the role of both the Python type object and method
|> table.
|

|I agree that this would be a desirable design for a future Python
|implementation.

Surely.
matz.

Yukihiro Matsumoto

unread,
Nov 4, 1999, 3:00:00 AM11/4/99
to
"Gordon McMillan" <gm...@hypernet.com> writes:

|> I don't think so. I don't believe anyone can reduce semantic
|> variability. Thus TMTOWTDI applies to semantics AND syntax.
|

|Did you mean to write what you wrote? From your premise, I
|would reach the opposite conclusion. Or are you saying that
|Guido also failed to reduce syntactic variability?

No. I think he succeeded to reduce syntactic variability.

But TMTOWTDI (in other words: the more, the merrier) is the slogan to
emphasize maximum variability in ALL AREAS, so that I felt weird to
see Pythoneers talking TMTOWTDI or even TMTOWTHMTOWTDI in positive
attitude. Reducing variablility in ANY AREA contradict against
TMTOWTDI, I think.

As I stated before, I don't judge whether it is good or bad.
Personally, I feel Perl went too far, though.

matz.

Yukihiro Matsumoto

unread,
Nov 4, 1999, 3:00:00 AM11/4/99
to

Fernando Pereira <per...@research.att.com> writes:

|In my experience, there's a big difference between what you and I call
|"sensible" and what compiler and OS developers try to get away with,
|not to mention the vagaries of particular hardware. For example, what
|is the state of the stack, registers, etc. when a Unix signal handler
|is called? What if that handler (maybe by calling back into the
|higher-level language) forces a GC?

I implemented Ruby to avoid GC (and longjmp) during handlers.
See code for detail, if you are interested. We haven't met such
problems, yet.

Fredrik Lundh

unread,
Nov 4, 1999, 3:00:00 AM11/4/99
to Python Mailing List
Yukihiro Matsumoto <ma...@netlab.co.jp> wrote:
> But TMTOWTDI (in other words: the more, the merrier) is the slogan to
> emphasize maximum variability in ALL AREAS, so that I felt weird to
> see Pythoneers talking TMTOWTDI or even TMTOWTHMTOWTDI in positive
> attitude. Reducing variablility in ANY AREA contradict against
> TMTOWTDI, I think.

well, I can think of many areas where Perl
doesn't give you maximum variability when
compared to other languages (of all kinds).

(in other words, the TMTOWTDI argument is
nonsense, just as I've always suspected).

</F>


Hrvoje Niksic

unread,
Nov 4, 1999, 3:00:00 AM11/4/99
to
Guido van Rossum <gu...@cnri.reston.va.us> writes:

> Does it use longjmp to do this? Or is it written in C++ and using
> C++ exceptions? Note that longjmp is a frequent cause of nasty
> portability problems

Well. Emacs uses longjmp() for signaling errors and throwing
exceptions, and it's ported to quite a number of platforms. Not that
I say that longjmp() is nice or anything -- it's slow and ugly -- but
I don't think it's unportable.

Martijn Faassen

unread,
Nov 4, 1999, 3:00:00 AM11/4/99
to
Yukihiro Matsumoto <ma...@netlab.co.jp> wrote:
[snip]

> But TMTOWTDI (in other words: the more, the merrier) is the slogan to
> emphasize maximum variability in ALL AREAS, so that I felt weird to
> see Pythoneers talking TMTOWTDI or even TMTOWTHMTOWTDI in positive
> attitude. Reducing variablility in ANY AREA contradict against
> TMTOWTDI, I think.

But there are more ways to have more ways to do it, which is I think what
TMTOWTHMTOWTDI stands for. :) Python does it by reducing syntactic variability,
while still having a large semantic variability; and because it's so
easy to use, it arguably has a larger semantic variability than C. Of course
this is nonsense because Python is written in C, but it's just *easier*
to use different programming styles in Python (procedural, object oriented,
functional, etc). More inviting. In this sense Python may even invite
*more* semantic ways to do it than Perl (for instance people sometimes
complain about the OO implementation of Perl).

So there are more ways to have multiple solutions than just Perl's way. As
I'm sure you'll agree with. :)

There-are-more-ways-to-understand-TMTOWTDI-ly yours,

Martijn
--
History of the 20th Century: WW1, WW2, WW3?
No, WWW -- Could we be going in the right direction?

Robin Becker

unread,
Nov 4, 1999, 3:00:00 AM11/4/99
to
I'm fairly sure all of these languages are turing complete and if so
they're equivalent at the semantic level. To defeat TC once and for all
let's implement a PyPerl module etc etc etc. Greg is at least doing some
interesting comparisons all this n ways to babylon and back stuff or how
many T's H's etc is a bit of a waste.
--
Robin Becker

William Tanksley

unread,
Nov 4, 1999, 3:00:00 AM11/4/99
to
On 5 Nov 1999 01:22:23 GMT, Neel Krishnaswami wrote:
>Greg Ewing <greg....@compaq.com> wrote:
>>Here are some random observations from studying the Ruby
>>source code:

>>* It doesn't use bytecode. The evaluator seems to operate
>> directly on a parse tree. I don't know what implications
>> this has for execution speed.

>I was under the impression that Ruby did tail-recursion elimination,
>and since continuation-passing forms are just a hair away from
>bytecode, I am a bit surprised by this news. I'm not saying this is
>impossible (witness the scm Scheme interpreter), mind, just a little
>surprised.

>Are there any syntax-tree munging phases to do stuff like common
>subexpression elimination and loop hoisting? I guess that could yield
>enough speedups to make a VM not yet necessary.

Parse trees tend to evaluate faster than bytecode when both have only
primitive optimizations. They are also much, much easier to optimize. In
general, I would expect a parse tree implementation to outperform a
bytecode implementation given equivalent work.

>Neel

--
-William "Billy" Tanksley

Greg Ewing

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to
Here are some random observations from studying the Ruby
source code:

* It seems to have a notion of "tainted" strings, and can
be run in various security modes where certain operations
using tainted strings are disallowed.

* It doesn't use bytecode. The evaluator seems to operate
directly on a parse tree. I don't know what implications
this has for execution speed.

* Here is an interesting little diagram I came across. Note
that Ruby appears to have metaclasses of some flavour or
other.

/*
* Ruby's Class Hierarchy Chart
*
* +------------------+
* | |
* Object---->(Object) |
* ^ ^ ^ ^ |
* | | | | |
* | | +-----+ +---------+ |
* | | | | |
* | +-----------+ | |
* | | | | |
* +------+ | Module--->(Module) |
* | | ^ ^ |
* OtherClass-->(OtherClass) | | |
* | | |
* Class---->(Class) |
* ^ |
* | |
* +----------------+
*
* + All metaclasses are instances of the class `Class'.
*/

Greg

Neel Krishnaswami

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to
Greg Ewing <greg....@compaq.com> wrote:
>Here are some random observations from studying the Ruby
>source code:
>
>* It doesn't use bytecode. The evaluator seems to operate
> directly on a parse tree. I don't know what implications
> this has for execution speed.

I was under the impression that Ruby did tail-recursion elimination,


and since continuation-passing forms are just a hair away from
bytecode, I am a bit surprised by this news. I'm not saying this is
impossible (witness the scm Scheme interpreter), mind, just a little
surprised.

Are there any syntax-tree munging phases to do stuff like common
subexpression elimination and loop hoisting? I guess that could yield
enough speedups to make a VM not yet necessary.


Neel

Yukihiro Matsumoto

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to
ne...@brick.cswv.com (Neel Krishnaswami) writes:

|Are there any syntax-tree munging phases to do stuff like common
|subexpression elimination and loop hoisting? I guess that could yield
|enough speedups to make a VM not yet necessary.

No. It's pretty hard to optimize a dynamic language like Ruby, in
which even integer addition can be re-defined. The optimizer can't
tell whether a subexpression has side effect or not.

Optimization ideas are welcome, though. :-)
matz.

Bjorn Pettersen

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to Paul Prescod, ne...@alum.mit.edu

> Neel Krishnaswami wrote:
> >
> > Python (and Ruby, for that matter) remind me more of Smalltalk than
> > anything else -- ie, they have extensive libraries, a
> community with a
> > love of elegance but not of purity[*], and a greater focus
> on practical
> > applications than on academic research.
>
> Isn't the Smalltalk community pretty enamored of purity? I
> mean "if" is
> an object that takes messages, right?
>
> Paul Prescod

Almost. A comparison creates a boolean object that takes ifTrue: and
ifFalse: (and whileTrue: etc.) messages. Quite elegant...

-bjorn

Toby Dickenson

unread,
Nov 5, 1999, 3:00:00 AM11/5/99
to
Greg Ewing <greg....@compaq.com> wrote:

>Fernando Pereira wrote:
>>
>> Same comment. There is no portable way of unwinding the C stack. What
>> does that mean for Ruby's portability?
>
>It uses setjmp/longjmp. Presumably these work correctly on
>any system where they are implemented. Porting Ruby to a
>system where they're not implemented could be difficult.
>

Presumably this makes it difficult for Ruby extensions to use C++?


Toby Dickenson

Wostenberg

unread,
Nov 6, 1999, 3:00:00 AM11/6/99
to

Doug Way wrote:

> From a historical point of view, Smalltalk is a little like Lisp, in
> that it's a little outside of the mainstream, but it has enough new
> ideas in it that will give it a very long lifespan. Smalltalk will
> still be relevant 20 years from now, just as Lisp-based languages are
> still reasonably relevant today, after 40 years. I suppose "having a
> lot of new ideas" and "being a little outside of the mainstream" go hand
> in hand. (Smalltalk isn't *that* obscure, though... there are more
> Smalltalk programming jobs available than, say, Python or Lisp jobs.)

Intersting observation. Perhaps it comes down to those of us who are
comfortable with niche languages (Python, Smalltalk, Lisp) and those who
suffer Java-envy . Do Python people, Ada advocates, or little Lispers wring
there hands about the fact "we are not the most used language?" Why should
Smalltalkers?

-Alan


Patrick Phalen

unread,
Nov 6, 1999, 3:00:00 AM11/6/99
to pytho...@python.org
[Wostenberg, on Sat, 06 Nov 1999]:

:: Intersting observation. Perhaps it comes down to those of us who are


:: comfortable with niche languages (Python, Smalltalk, Lisp) and those who
:: suffer Java-envy . Do Python people, Ada advocates, or little Lispers wring
:: there hands about the fact "we are not the most used language?" Why should
:: Smalltalkers?


Speaking of Java envy, Barry Warsaw pointed out the other day on the
JPython list that www.netbeans.com is running a survey to pick the best
scripting language to be integrated with NetBeans. (You'll find the form
in their left navbar.)

I won't reveal the *overwhelming* winner, thus far. Find out for
yourself. ;)

I-swear-I-only-voted-twice-ly-y'rs -patrick

Mark Hamstra

unread,
Nov 6, 1999, 3:00:00 AM11/6/99
to
Patrick Phalen <pytho...@teleo.net> writes:


Just curious, why not Bean Scripting Framework, since it allows for JPython
and any other scripting language that has been hooked into the BSF?

--
Mark Hamstra
Bentley Systems, Inc.

Paul Prescod

unread,
Nov 7, 1999, 3:00:00 AM11/7/99
to pytho...@python.org
Wostenberg wrote:
>
> Intersting observation. Perhaps it comes down to those of us who are
> comfortable with niche languages (Python, Smalltalk, Lisp) and those who
> suffer Java-envy . Do Python people, Ada advocates, or little Lispers wring
> there hands about the fact "we are not the most used language?" Why should
> Smalltalkers?

Programmers of minority languages do often wring their hands for the
simple reason that they are often forced to program in majority
languages.

--
Paul Prescod - ISOGEN Consulting Engineer speaking for only himself
http://itrc.uwaterloo.ca/~papresco

"Some of Disney's older properties, such as Peter Pan, Winnie the Pooh,
and Alice in Wonderland, came out of books. But the authors' names are
rarely if ever mentioned, and you can't buy the original books at the
Disney store. If you could, they would all seem old and queer, like very
bad knockoffs of the purer, more authentic Disney versions."
- http://www.cryptonomicon.com/beginning.html

Yukihiro Matsumoto

unread,
Nov 8, 1999, 3:00:00 AM11/8/99
to

Toby Dickenson <htr...@zepler.org> writes:

|>It uses setjmp/longjmp. Presumably these work correctly on
|>any system where they are implemented. Porting Ruby to a
|>system where they're not implemented could be difficult.
|>
|
|Presumably this makes it difficult for Ruby extensions to use C++?

I don't think so. Some extensions for Ruby are written in C++
(e.g. MySQL interface) without problems.

matz.

Greg Ewing

unread,
Nov 9, 1999, 3:00:00 AM11/9/99
to
Neel Krishnaswami wrote:
>
> and since continuation-passing forms are just a hair away from
> bytecode, I am a bit surprised by this news.

I don't see how continuation-passing and bytecode have anything
to do with each other.

> Are there any syntax-tree munging phases to do stuff like common
> subexpression elimination and loop hoisting?

I haven't seen any so far, although I haven't really looked
for these things.

I get the impression that speed isn't a major design goal in
this implementation of Ruby, at least not as much as it is
in CPython. All of Ruby's built-in operations go through a
method lookup, for example, even adding two integers.

Greg

Greg Ewing

unread,
Nov 9, 1999, 3:00:00 AM11/9/99
to
Guido van Rossum wrote:
>
> Python used to have short names too, and in fact the current naming
> scheme was intruduced with great reluctance. Unfortunately the
> realities of embedding Python in other apps required the current
> longer names

I know, I didn't mean that as a criticism of Python.
I understand the importance of keeping namespaces
under control!

In fact, I'm not very impressed with Ruby's naming
scheme, which seems rather inconsistent. Most Ruby-related
names start with "rb_", but some just start with "R",
and some don't have any unique prefix at all.

Also it's not entirely clear what the rational is behind
the various uses of lowercase, uppercase, mixedcase,
embedded underscores, etc. There probably is one, but
it all looks a bit haphazard at first sight.

Greg

Paul Eggert

unread,
Nov 12, 1999, 3:00:00 AM11/12/99
to
Jim Althoff <ji...@aspectdv.com> writes:

>Absolutely right. Part of the original dream of the Smalltalk development
>team was to build a programming language/environment that would be so
>easy that anybody -- even kids -- could use it.

Kids? Kids?? You think _kids_ were the target!?
No way. The PARC developers were much more ambitious than that.
Smalltalk's design goal was to be so easy
that even _secretaries_ could use it.

Jim Althoff

unread,
Nov 15, 1999, 3:00:00 AM11/15/99
to Paul Eggert, pytho...@python.org

I see.

Well, what can I say? I was merely expressing my opinion based
on actually having been a member of the Smalltalk development
team at PARC. (And, yes, we _did_ want secretaries to be able to
use the applications.)

Although I assume the "_secretaries_ vs _kids_" bit above was meant
to be humorous, for the historically curious, here is what Alan had to say:

>>>>>>>>>>>>>>>>>>>>>>

Why is this collection of objects called Smalltalk?

The name actually appeared before the first Smalltalk design, which was
created in 1971. I had mentioned to someone that the "prose" of then
current programming languages was lower than a cocktail party conversation,
and that great progress would have been made if we could even get to the
level of making "smalltalk". It then occured to me that this word was also
a great pun for a language aimed at the world of small children.

As for hype: Another motive for "smalltalk" was the practice at the time of
naming operating, and other, systems (which hardly did anything) after
mighty indo-european gods, such as Thor, Zeus, Odin, etc. I figured that if
Smalltalk ever did something neat, then people would be pleasantly surprised.

As related in the Early History of Smalltalk (in HOPL II, Addison Wesley,
1995), the actual start of today's Smalltalk was kind of accidental and was
partly the result of a bet. -- Alan Kay

<<<<<<<<<<<<<<<<<<<<<

Jim


>--
>http://www.python.org/mailman/listinfo/python-list

Greg Ewing

unread,
Nov 17, 1999, 3:00:00 AM11/17/99
to
I've been looking into the way types and classes are
unified in Ruby.

As I mentioned earlier, all objects in Ruby are associated
with an object of class Class, which plays the role of
both the PyTypeObject and PyClassObject. Consequently,
it is possible to define subclasses of any of the built
in types and add or override methods. It's even possible
to add instance variables -- I'll explain how that works
below.

Each of the built-in types is represented by a unique
C structure, as in Python. Therefore it is important that
when a subclass of a built-in class is instantiated, the
right kind of C structure is created, since all the
built-in methods of its superclass expect to get that
kind of structure.

This is guaranteed by two characteristics of Ruby that
differ from Python:

1) Instantiation of a class is done by calling a class
method of that class. (Ruby has real class methods and
variables, like Smalltalk. In fact, Ruby's internals are
very Smalltalk-like in many ways.)

2) A class can only inherit from at most one other
class.

The only methods which actually create C structures are
the built-in instantiation methods of the built-in
classes, so even if you define your own instantiation
method in your subclass, it eventually has to call a
built-in one somewhere up its inheritance chain, which
knows what kind of C structure is needed.

This scheme will fail if you somehow manage to extract
a built-in method out of one class and stuff it into
another. However there doesn't seem to be any obvious
way to do this (nothing like myClass.__dict__["foo"] in
Python). So it seems to be safe.

Now, what happens if you assign to a new instance variable
in a method of your subclass of a built-in class? At first
sight it seems that this can't possibly work, because the
C structs of built-in types don't have any place to store
arbitrary instance variables.

When I tried it, however, to my surprise, it worked!
It turns out that there is a global table whose purpose
is to hold the values of these instance variables (in
Python terms it is a dictionary of dictionaries, indexed
by [object][variable_name]). Python might be able to
use a similar solution, although it might cause ref
counting problems.

As a final note, some built-in classes, such as Fixnum,
don't have any instantiation method, so although you can
subclass them, there's no point because you can never
create an instance of your subclass.

Others, however, such as Array (Ruby's version of ListType)
do have an instantiation method, and subclasses work
just the way you'd expect.

Hoping this has been enlightening,
Greg

Clemens Hintze

unread,
Nov 17, 1999, 3:00:00 AM11/17/99
to
Hi,

Greg, you have done a great analyze! I wish you would have done it
sooner ;-) It would have spare me some time to fiddle that out on my
own. This part of Ruby is, unfortunately, not too well documented. :-(

But in addition to your analyze, may I add some remarks?

>>>>> "Greg" == Greg Ewing <greg....@compaq.com> writes:

[...]

Greg> 2) A class can only inherit from at most one other class.

This is, in fact, true. But it is worth mentioning, that Ruby features
single inheritance *by*purpose*. Not because of the implementation
details!

If it would implement multi-inheritance, the class structure could
e.g. use an array of pointer to all such C structs, not only one
pointer, as implemented now!

Greg> The only methods which actually create C structures are the
Greg> built-in instantiation methods of the built-in classes, so
Greg> even if you define your own instantiation method in your
Greg> subclass, it eventually has to call a built-in one somewhere
Greg> up its inheritance chain, which knows what kind of C
Greg> structure is needed.

That is not totally true (or, perhaps, I misunderstood you). You have
to differ two kind of class-building. you seem to describe, how Ruby's
built-in classes are implemented. But there is also a second way, that
should be used by own extensions. *Only* Ruby built-in (means built
into the interpreter) classes, should use the way you have described.

The second (preferred) way is, to build instances of class DATA
wrapping the C struct you have allocated for your extension. That DATA
instance is marked as beeing not a DATA instance, but an instance of
your extension class! So that means, that *you* would allocate your
instance!

Deriving a Ruby class coded in C from another one also coded in C,
seems to be the only right tricky part of that language, IMHO. :-)

Greg> This scheme will fail if you somehow manage to extract a
Greg> built-in method out of one class and stuff it into
Greg> another. However there doesn't seem to be any obvious way to
Greg> do this (nothing like myClass.__dict__["foo"] in Python). So
Greg> it seems to be safe.

Good derivation! I have also missed it for some time. But as Ruby
features closures, I had learned to use them instead of extraced
methods. Anyway Ruby has no functions, only methods.

You could extract a method object (means a method implementation). But
you would not be able to use it out-of-context of the class it was
taken from! As matz (the author of Ruby) has told me, methods are too
strong connected to the class they belongs to (performance reasons).

Greg> Now, what happens if you assign to a new instance variable
Greg> in a method of your subclass of a built-in class? At first
Greg> sight it seems that this can't possibly work, because the C
Greg> structs of built-in types don't have any place to store
Greg> arbitrary instance variables.

;-)))))))

Greg> When I tried it, however, to my surprise, it worked! It
Greg> turns out that there is a global table whose purpose is to
Greg> hold the values of these instance variables (in Python terms
Greg> it is a dictionary of dictionaries, indexed by
Greg> [object][variable_name]). Python might be able to use a

That was a great idea from matz, IMHO! :-)

Greg> similar solution, although it might cause ref counting
Greg> problems.

Once again, thanks for Ruby's true garbage collection! :-)

Greg> As a final note, some built-in classes, such as Fixnum,
Greg> don't have any instantiation method, so although you can
Greg> subclass them, there's no point because you can never create
Greg> an instance of your subclass.

In addition to your analyze: in the past, at least the classes of
Numeric and childs had instanstiation methods. But some user of Ruby
have convinced matz, that it would make no sense to derive another
numeric type from them. So the methods were delete. The big exception,
AFAIK, was class Fixnum. It never had any instanciation method, as it
doesn't wrap any struct. The pointer-to-struct is 'misused' as
contents of Fixnum. If I remember right, Smalltalk has also chosen
that way for implementing SmallInteger.

Greg> Others, however, such as Array (Ruby's version of ListType)
Greg> do have an instantiation method, and subclasses work just
Greg> the way you'd expect.

It is worth mentioning too, that it is often not necessary to derive
something from e.g. Array. Often it is better to use the module
mechanism to add methods to class Array or some of its instances
during runtime.

You can do that also in your extension. So if Ruby's Array would not have
'push' and 'pop' methods, I would not derive a class Stack from Array,
but I would implement a module Stack (implementing 'push' and 'pop')
and simply add them to class Array, whenever I need them ... :-)))

Greg> Hoping this has been enlightening, Greg

We would need more of such ... :-)

Clemens.

Greg Ewing

unread,
Nov 19, 1999, 3:00:00 AM11/19/99
to
Clemens Hintze wrote:
>
> But it is worth mentioning, that Ruby features
> single inheritance *by*purpose*. Not because of the implementation
> details!

I wasn't making a value judgement, only pointing out that
Ruby's solution is as simple as it is because of this
restriction.

> If it would implement multi-inheritance, the class structure could
> e.g. use an array of pointer to all such C structs, not only one
> pointer, as implemented now!

Sure, Python could do something like that too. But it would
get very hairy and complicated and probably slow everything
down a lot, casting doubt on whether it's worth the effort.

A middle ground might be to allow inheriting from any number
of user-defined classes, but at most one built-in type.

> The second (preferred) way is, to build instances of class DATA
> wrapping the C struct you have allocated for your extension.

Yes, I know, but what I was saying still applies in that case.
All the methods of the extension class expect the DATA object
to be pointing to their own particular kind of struct, and
because of the inheritance structure, this is always true --
so they don't need to bother checking.

> Deriving a Ruby class coded in C from another one also coded in C,
> seems to be the only right tricky part of that language, IMHO. :-)

I think it will work as long as the derived class makes sure
that its C structure is an exension of the superclass's C
structure.

> Greg> [global instance var dict] might cause ref counting


> Greg> problems.
>
> Once again, thanks for Ruby's true garbage collection! :-)

Garbage collection alone doesn't actually solve the problem;
the references from the global dict need to be treated as
weak references somehow under either scheme. I haven't
looked, but presumably Ruby must be ignoring the global dict
refs when marking, and cleaning them up whenever a builtin
or extension object is deallocated. Python could be made to
do the equivalent.

> The big exception,
> AFAIK, was class Fixnum. It never had any instanciation method, as it
> doesn't wrap any struct.

Yes, that's the one class you really can't instantiate a
subclass of, since its class is totally implicit.

But it's not clear whether it's any use having something
like a UserFlonum, either, even though technically it could
be done. Unless you override every method, any arithmetic
on it would return an ordinary Flonum. And if you are going
to override every method, it might as well be a totally
new class!

> Often it is better to use the module
> mechanism to add methods to class Array or some of its instances
> during runtime.

You mean you can add methods to an *existing* class that
way? Not sure if I like that idea...

Greg

Greg Ewing

unread,
Nov 19, 1999, 3:00:00 AM11/19/99
to
Clemens Hintze wrote:
>
> But it is worth mentioning, that Ruby features
> single inheritance *by*purpose*. Not because of the implementation
> details!

I wasn't making a value judgement, only pointing out that


Ruby's solution is as simple as it is because of this
restriction.

> If it would implement multi-inheritance, the class structure could


> e.g. use an array of pointer to all such C structs, not only one
> pointer, as implemented now!

Sure, Python could do something like that too. But it would


get very hairy and complicated and probably slow everything
down a lot, casting doubt on whether it's worth the effort.

A middle ground might be to allow inheriting from any number
of user-defined classes, but at most one built-in type.

> The second (preferred) way is, to build instances of class DATA


> wrapping the C struct you have allocated for your extension.

Yes, I know, but what I was saying still applies in that case.


All the methods of the extension class expect the DATA object
to be pointing to their own particular kind of struct, and
because of the inheritance structure, this is always true --
so they don't need to bother checking.

> Deriving a Ruby class coded in C from another one also coded in C,


> seems to be the only right tricky part of that language, IMHO. :-)

I think it will work as long as the derived class makes sure


that its C structure is an exension of the superclass's C
structure.

> Greg> [global instance var dict] might cause ref counting


> Greg> problems.
>
> Once again, thanks for Ruby's true garbage collection! :-)

Garbage collection alone doesn't actually solve the problem;


the references from the global dict need to be treated as
weak references somehow under either scheme. I haven't
looked, but presumably Ruby must be ignoring the global dict
refs when marking, and cleaning them up whenever a builtin
or extension object is deallocated. Python could be made to
do the equivalent.

> The big exception,


> AFAIK, was class Fixnum. It never had any instanciation method, as it
> doesn't wrap any struct.

Yes, that's the one class you really can't instantiate a


subclass of, since its class is totally implicit.

But it's not clear whether it's any use having something
like a UserFlonum, either, even though technically it could
be done. Unless you override every method, any arithmetic
on it would return an ordinary Flonum. And if you are going
to override every method, it might as well be a totally
new class!

> Often it is better to use the module


> mechanism to add methods to class Array or some of its instances
> during runtime.

You mean you can add methods to an *existing* class that

Dirk-Ulrich Heise

unread,
Nov 19, 1999, 3:00:00 AM11/19/99
to
Greg Ewing schrieb in Nachricht <38356C74...@compaq.com>...

>You mean you can add methods to an *existing* class that
>way? Not sure if I like that idea...
>
>Greg

It could be useful for sophisticated debug instrumentation
of certain classes or instances during runtime of
a system. It's also useful if you write an IDE and want
to give it a feature to update one methods implementation
without having to interrupt your programs run.
(imagine you just had a traceback from an exception
while trying one of the features of the app you're developing.
Now you switch into the IDE and fix the buggy method and
reload it without stopping your apps run. Then you retry
the feature)
(debugging and letting it run at the same time)
(I do this in Python a lot and i haven't used Ruby by now)
Maybe (IMHO, rather certainly) it's not important or *shouldn't* be
important
for a release to be shipped to the customer, but i think
it's enormously valuable during development.
It *shouldn't* be necessary for the release version because
it's a feature which isn't found in a lot of languages,
so if an app relies on it, it's a solution unportable to
other languages. Basically, i try to use the weird parts
of C++ and Python for increasing dev speed and not
use them for release versions because they're too weird
-- YMMV. (off topic: And C++ seems to develop a new weird part each day
now when i look into a C++ NG ;-))
--
Dipl.Inform. Dirk-Ulrich Heise
h...@adtranzsig.de
dhe...@debitel.net


Greg Ewing

unread,
Nov 20, 1999, 3:00:00 AM11/20/99
to
Clemens Hintze wrote:
>
> But it is worth mentioning, that Ruby features
> single inheritance *by*purpose*. Not because of the implementation
> details!

I wasn't making a value judgement, only pointing out that


Ruby's solution is as simple as it is because of this
restriction.

> If it would implement multi-inheritance, the class structure could


> e.g. use an array of pointer to all such C structs, not only one
> pointer, as implemented now!

Sure, Python could do something like that too. But it would


get very hairy and complicated and probably slow everything
down a lot, casting doubt on whether it's worth the effort.

A middle ground might be to allow inheriting from any number
of user-defined classes, but at most one built-in type.

> The second (preferred) way is, to build instances of class DATA


> wrapping the C struct you have allocated for your extension.

Yes, I know, but what I was saying still applies in that case.


All the methods of the extension class expect the DATA object
to be pointing to their own particular kind of struct, and
because of the inheritance structure, this is always true --
so they don't need to bother checking.

> Deriving a Ruby class coded in C from another one also coded in C,


> seems to be the only right tricky part of that language, IMHO. :-)

I think it will work as long as the derived class makes sure


that its C structure is an exension of the superclass's C
structure.

> Greg> [global instance var dict] might cause ref counting


> Greg> problems.
>
> Once again, thanks for Ruby's true garbage collection! :-)

Garbage collection alone doesn't actually solve the problem;


the references from the global dict need to be treated as
weak references somehow under either scheme. I haven't
looked, but presumably Ruby must be ignoring the global dict
refs when marking, and cleaning them up whenever a builtin
or extension object is deallocated. Python could be made to
do the equivalent.

> The big exception,


> AFAIK, was class Fixnum. It never had any instanciation method, as it
> doesn't wrap any struct.

Yes, that's the one class you really can't instantiate a


subclass of, since its class is totally implicit.

But it's not clear whether it's any use having something
like a UserFlonum, either, even though technically it could
be done. Unless you override every method, any arithmetic
on it would return an ordinary Flonum. And if you are going
to override every method, it might as well be a totally
new class!

> Often it is better to use the module


> mechanism to add methods to class Array or some of its instances
> during runtime.

You mean you can add methods to an *existing* class that

Clemens Hintze

unread,
Nov 20, 1999, 3:00:00 AM11/20/99
to
>>>>> "Dirk-Ulrich" == Dirk-Ulrich Heise <h...@adtranzsig.de> writes:

Dirk-Ulrich> Greg Ewing schrieb in Nachricht
Dirk-Ulrich> <38356C74...@compaq.com>...


>> You mean you can add methods to an *existing* class that way?
>> Not sure if I like that idea...
>>
>> Greg

[...]

Dirk-Ulrich> haven't used Ruby by now) Maybe (IMHO, rather
Dirk-Ulrich> certainly) it's not important or *shouldn't* be
Dirk-Ulrich> important for a release to be shipped to the
Dirk-Ulrich> customer, but i think it's enormously valuable during

Why should it not be important for releases? The customer will not
consider that. And if it can help me, why not?

Dirk-Ulrich> development. It *shouldn't* be necessary for the
Dirk-Ulrich> release version because it's a feature which isn't
Dirk-Ulrich> found in a lot of languages, so if an app relies on

But it is, for instance, in Objective-C. And there it is widely used.

Dirk-Ulrich> it, it's a solution unportable to other
Dirk-Ulrich> languages. Basically, i try to use the weird parts of

But this would mean, you couldn't use special languages for developing
your app. Take C++, for instance. It features templates and
function/method overloading. These features are also not common in
very much compiled languages. Does that mean, I shouldn't use C++?

Or Prolog? Prolog programs are not very portable to other
languages... so forget about it? Lisp... ?

I think, if I write a program, I do not think in terms of portability
to another languages, only portability between platforms!

Dirk-Ulrich> C++ and Python for increasing dev speed and not use
Dirk-Ulrich> them for release versions because they're too weird
Dirk-Ulrich> -- YMMV. (off topic: And C++ seems to develop a new
Dirk-Ulrich> weird part each day now when i look into a C++ NG
Dirk-Ulrich> ;-)) -- Dipl.Inform. Dirk-Ulrich Heise
Dirk-Ulrich> h...@adtranzsig.de dhe...@debitel.net


Clemens Hintze

unread,
Nov 20, 1999, 3:00:00 AM11/20/99
to
>>>>> "Greg" == Greg Ewing <greg....@compaq.com> writes:

Greg> Clemens Hintze wrote:

[...]

>> Often it is better to use the module mechanism to add methods
>> to class Array or some of its instances during runtime.

Greg> You mean you can add methods to an *existing* class that
Greg> way? Not sure if I like that idea...

Yes, I mean exactly that! I am sure, I like it very much... Many OOL
could do that. For instance: Smalltalk, Objective-C, Self, ...

Furthermore Ruby cannot only do this for *existing* classes, but also
for *existing* instances; and that without interfering *other*
existing instances or even the class, they are build from (this is a
little bit like Self's OO-modell).

Ruby is indeed very dynamic. And I like its features! If I had, e.g.,
written the module Stack, I could include to the existing Array
class, or even to one of its instances. This second possibility, IMHO,
is more preferred. So following would be possible:

stk = Array.new
stk.extend Stack
stk.push ...
:

Here only the instances referred by 'stk' would become a stack! All
other Array instances, would remain Arrays. Very useful in my
opinion. :-)

Of course, that example is meaningless, as Array has already 'push'
and 'pop' methods :-/

Greg> Greg

\cle

skaller

unread,
Nov 21, 1999, 3:00:00 AM11/21/99
to
This post really relates to the thread Type/Class unification in Ruby.
I have some comments and a description.

First, I do not think type/class unification in python is
desirable. Some types, such as numbers, are not naturally
suited to subclassing, and making them classes is pointless.
The only python type which really should be a class is the file
object (and in Viper, it is).

Second, here again is a description of the Viper type system.
I believe it meets the goals of Type/Class unification,
but by a slightly different (and much better) route.

In Viper, all objects have type objects, which can be any object.
When an object.attribute lookup fails to find the attribute
in the object, the search continues in the type object of the object,
unless that object is self.

You can view the type object of an object as the 'class' of the object,
and say that Viper requires all objects to be singly inherited
from some object (possibly self). However, this is an abstraction:
the lookup rule stated above is what the implementation actually does.

Viper _also_ supports normal python classes. This is completely
independent
of the dynamic typing system. What this means is that every class
instance
has TWO kinds of type: its class, and its type. Note also that
classes have a type!

In Viper, all the standard kinds of objects have type objects which
are classes. Any functions def'ed in these classes are available
as method of the objects. For example the type of an integer (1)
is the class 'py_types.PyIntType', given below:

class PyIntType:
def succ(self): return self+1
def prec(self): return self-1


which means that the expression

(1).succ()

has value 2.

In the current implementation, the standard types have the names of
their type object fixed, and it must be located in the module
py_types. I plan to allow instance and class objects to have mutable
type objects, that is, to dynamically change the type object
of an object (called 'metamorphosis').

This technology was implemented to eliminate complexity;
in some sense, to get rid of object orientation from the implementation.
In particular, methods of the builtin types are entirely implemented by
functions, and they're made to look like 'methods' by making
them class attributes. This also allows any method, even of builtin
types, to be written in python: native and python functions can be
freely
mixed. For example:

class PyListType:
append = list_append
def extend(self, value): ....

Here 'list_append' is a normal builtin function, and

x.append(y)

is exactly equivalent to

list_append(x,y)

So, in Viper, there is no Type/Class unification.
Instead, there is a Type/Object unification;
any object can be the type object of any other.
[Circular lists of length > 1 are a bad idea!]

[Finally: Viper now executes interscript, except
for __del__ methods. This means I am ready to
start preparing a release. Don't hold your breath though,
I'm currently integerating GUI into the system]

--
John Skaller, mailto:ska...@maxtal.com.au
10/1 Toxteth Rd Glebe NSW 2037 Australia
homepage: http://www.maxtal.com.au/~skaller
voice: 61-2-9660-0850

Aahz Maruch

unread,
Nov 21, 1999, 3:00:00 AM11/21/99
to
In article <38373EC3...@maxtal.com.au>,

skaller <ska...@maxtal.com.au> wrote:
>
>First, I do not think type/class unification in python is
>desirable. Some types, such as numbers, are not naturally suited to
>subclassing, and making them classes is pointless. The only python
>type which really should be a class is the file object (and in Viper,
>it is).

Hmmm? What about lists and dicts? I can also easily imagine
subclassing the string type.
--
--- Aahz (@netcom.com)

Androgynous poly kinky vanilla queer het <*> http://www.rahul.net/aahz/
Hugs and backrubs -- I break Rule 6 (if you want to know, do some research)

Dirk-Ulrich Heise

unread,
Nov 22, 1999, 3:00:00 AM11/22/99
to
Clemens Hintze schrieb in Nachricht ...

>I think, if I write a program, I do not think in terms of portability
>to another languages, only portability between platforms!

I'm just lazy. I know about certain things that work in all (or most of)
the OO languages, and these are the things i use mostly.
Just because they're the most relevant parts of OO, IMHO.
I'm making no statement about functional languages;
i never understood them.

Greg Ewing

unread,
Nov 23, 1999, 3:00:00 AM11/23/99
to
Clemens Hintze wrote:
>
> But it is worth mentioning, that Ruby features
> single inheritance *by*purpose*. Not because of the implementation
> details!

I wasn't making a value judgement, only pointing out that


Ruby's solution is as simple as it is because of this
restriction.

> If it would implement multi-inheritance, the class structure could


> e.g. use an array of pointer to all such C structs, not only one
> pointer, as implemented now!

Sure, Python could do something like that too. But it would


get very hairy and complicated and probably slow everything
down a lot, casting doubt on whether it's worth the effort.

A middle ground might be to allow inheriting from any number
of user-defined classes, but at most one built-in type.

> The second (preferred) way is, to build instances of class DATA


> wrapping the C struct you have allocated for your extension.

Yes, I know, but what I was saying still applies in that case.


All the methods of the extension class expect the DATA object
to be pointing to their own particular kind of struct, and
because of the inheritance structure, this is always true --
so they don't need to bother checking.

> Deriving a Ruby class coded in C from another one also coded in C,


> seems to be the only right tricky part of that language, IMHO. :-)

I think it will work as long as the derived class makes sure


that its C structure is an exension of the superclass's C
structure.

> Greg> [global instance var dict] might cause ref counting


> Greg> problems.
>
> Once again, thanks for Ruby's true garbage collection! :-)

Garbage collection alone doesn't actually solve the problem;


the references from the global dict need to be treated as
weak references somehow under either scheme. I haven't
looked, but presumably Ruby must be ignoring the global dict
refs when marking, and cleaning them up whenever a builtin
or extension object is deallocated. Python could be made to
do the equivalent.

> The big exception,


> AFAIK, was class Fixnum. It never had any instanciation method, as it
> doesn't wrap any struct.

Yes, that's the one class you really can't instantiate a


subclass of, since its class is totally implicit.

But it's not clear whether it's any use having something
like a UserFlonum, either, even though technically it could
be done. Unless you override every method, any arithmetic
on it would return an ordinary Flonum. And if you are going
to override every method, it might as well be a totally
new class!

> Often it is better to use the module


> mechanism to add methods to class Array or some of its instances
> during runtime.

You mean you can add methods to an *existing* class that


way? Not sure if I like that idea...

Greg

Barry A. Warsaw

unread,
Nov 25, 1999, 3:00:00 AM11/25/99
to Greg Ewing

>>>>> "GE" == Greg Ewing <greg....@compaq.com> writes:

GE> A middle ground might be to allow inheriting from any number
GE> of user-defined classes, but at most one built-in type.

And in fact, this is exactly the JPython restriction. Because Java
has only single inheritance, a JPython class can only have a single
Java base class, but any number of pure Python base classes.

-Barry

William Tanksley

unread,
Nov 27, 1999, 3:00:00 AM11/27/99
to

Another possibility would be to borrow from Sather by making all
inheritance actually act like interface inheritance with delegation.

In other words, JPython creates an interface for every class, and when you
inherit you actually implement and then add a member data thingie.

>-Barry

--
-William "Billy" Tanksley

0 new messages