Strong advantages over Python

Greg McIntyre wrote:

would be one focus of the lecture. But I’m interested in specific
examples where the equivalent Python code is significantly more
difficult.

Perhaps situation when you wish to do method run-time optimization.

suppose:

class Foo
def parse()
[…]
def self.data()
@data
end
end

def data()
File.open (“data.txt”) do |file|
self.parse(file.read)
end
end
end

data.txt is read only once per instance, but no run-time check(if @data)
is needed, Foo#parse just rewrites Foo#data at runtime as singleton method.

There no such kind of technique in python AFAIK.

Mauricio Fernández wrote:

[Side question] Is there no access control?

By default, there is no access control. You can make something basically
private by putting __ in its name but in my experience it is better to
put a single underscore and depend upon the common sense of the person
using the class. Even if you use “__” you can get around it using
introspection tricks roughly analogous to Ruby’s instanceEval.

Probably not the forum for a Python lesson, so we can take it offline if
you have deeper questions. Or do it publically if people prefer.

Paul Prescod

···

On Fri, Mar 21, 2003 at 07:08:06AM +0900, Paul Prescod wrote:

There are a lot more than this, but these are just a few things that spring
to mind:

o Super easy to extend with C modules

yes, I know. But I never developed C modules so I omitted it.

o The power of mixing in Enumerable

Already mentioned Iterators, I should have pointed enumerable

o Simplicity of mixins vs multiple inheritance

There are lot of people that lived happyly with multiple inherithance,
you may even think about UML as the standard object thinking, and they
have it.

o A builtin class library small enough to memorize but powerful enough to
do basically anything you want

but they could say we miss lots of things the already have, such has a
(quite) mature application server, a gui builder, and theyr stdlib is
not useles

o Total syntactic consistency(everything is an object)

I think in 2.2 they superseeded he type vs class problem, though
obviously ruby is pure OO and P* is not.

5.times {|num| …}
“foo”.reverse

I love this kind of things, but if you try to say
“hey, you have
5.upto(val){block} in ruby!”
they’ll say you: “well, I use for()”

You have to show someone huge enhancement to buy his
soul^W trust in a new language.

I always remember when I started learning OO, and talking with a
friend with Pascal background:

me: “yeah OO is great, it reflects real world!”
friend: “Sure. How do you make coffe?”
me: “well, I open the coffe machine and put in coffe and water,
put it on fire, wait and drink”
friend: “see, this is just imperative working”

It’s too hard to pass mental locks

(anyway, I feel good using ruby)

···

il Thu, 20 Mar 2003 05:05:25 GMT, Travis Whitton whitton@atlantic.net ha scritto::

Good list. Amalgamated with http://www.ruby-lang.org/en/whats.html, it
should make a concise enough list of advantages.

o Super easy to extend with C modules

Yup. Although with SWIG…

o The power of mixing in Enumerable
o Simplicity of mixins vs multiple inheritance

Debatable but okay. I would think about this point differently. Ruby has
a simple object model - objects are a bunch of variables and methods,
and Ruby gives you the means to add/subtract/edit them with a lot of
power.

o A builtin class library small enough to memorize but powerful enough
to do basically anything you want

This is something I love about Ruby over Python. I hate the Python
library reference – it’s so hard to find what you want to do using
it. Whereas on the off chance you actually need to look something up
while programming Ruby (as most things work by Ruby reading your mind),
you generally know exactly where to look for it.

So yes, that’s an important practical difference, IMO.

o Total syntactic consistency(everything is an object)
5.times {|num| …}
“foo”.reverse
o Stronger typing(everything has a specific type)
1.type => Fixnum

Some examples of the benefits of pure OOP. I use “have a nice day”.split
a fair bit, but Python can do that too so it makes it less enjoyable. :wink:
[‘dir1’, ‘dir2’, ‘filename’].join(File::Separator) might be a better
example.

This also relates to the fact that you generally know where to look for
a particular method in Ruby. In Python, join is a function defined in
the string module. How I was supposed to know that without popping up
the huuuge index page of the library reference and searching for ‘join’,
I don’t know.

o Truly private data instead of name mangling

Yes! There can be some excellent examples of this too.

o No equivalent of a do … while statement

Ah! I didn’t know that. How… Eiffelish.

o self.myvar vs @myvar

Not necessarily an advantage…

o No closures in Python?

Okay. I’m no Python expert, but…

Python 2.2 is a bit better. They’re still not the same however. AFAIK
you use lambdas in Python to create closures (assigning the lambdas to
variables and calling them later on). But lambdas expect ‘expressions’
not ‘statements’ meaning you can only do a very limited number of things
in your Python closure. Also, you cannot assign to a variable which is
in a closure’s context but outside its direct scope (e.g. something
assigned just above a Ruby block). There are dirty tricks to get around
it but they’re difficult and ugly. Hrm… there might be some other
differences too.

In Python you can assign function names to variables and then call them
through those variables, however AFAIK this relies on separate function
definitions and global variables in order to achieve the same level of
context manipulation possible with a Ruby block, so it certainly isn’t
as clean and easy.

I’d appreciate it if the more Python-inclined could correct or confirm
all that.

···

Travis Whitton whitton@atlantic.net wrote:


Greg McIntyre
greg@puyo.cjb.net
http://puyo.cjb.net

I don’t know much about Python, but . . . I have read about the feature
set of Python over time and it seems like Python has added many
features over the years to make it more like Ruby. Maybe they’ll
eventually become completely like Ruby :slight_smile:

I do believe that Ruby’s implementation of object orientation is more
pure than Python’s implementation. I think this is important.

···

On Thursday, March 20, 2003, at 11:36 PM, Jim Weirich wrote:

It sounds to me as if the original poster is looking for a “slam dunk”
for Ruby (compared to Python), and I’m not sure he’s going to find one.
Ruby and Python have far more in common than they have differences.
What differences there are more more differences in preferences than
real differences in language power.

Jim Weirich wrote:

[snip]

It sounds to me as if the original poster is looking for a “slam dunk”
for Ruby (compared to Python), and I’m not sure he’s going to find one.
Ruby and Python have far more in common than they have differences.
What differences there are more more differences in preferences than
real differences in language power.

Well, one can always fall back on the argument that they’re all
Turing-complete, and therefore equally “powerful,” but I tend to agree
that Python and Ruby are in the same general ballpark at least as far as
power and conciseness are concerned.

The truth is that I was on the verge of making a real effort to learn
Python when I read a posting by Dave Thomas (perhaps on the XP mailing
list?) mentioning Ruby. If it weren’t for that fortuitous posting, I
might be a Python advocate today (shudder :-).

I was a serious Python advocate when it was my primary
scripting/automation/prototyping tool, and continue to highly recommend
it as a teaching/learning language. Much of the real power of Ruby isn’t
immediately apparent to inexperienced developers, and the Python
community and documentation are definitely larger and more polished.
Plus, for learning purposes, there’s just more Python code out there for
people to read, even if most of it isn’t that interesting to us
hardcore-types. :wink:

I actually came to Ruby (and away from Python) because I was trying
very, very hard, and yet failing, to become a Perl hacker. The bizarre
scalar/list/hash distinction, typeglobs, etc., just turned me off, while
Ruby borrowed just enough of the conciseness and UNIX/POSIX savvy of
Perl to take care of the trivial stuff that made up so much of my
regular development effort.

Personally, I can still see a number of circumstances in which I’d use
Python instead of Ruby:

  1. Complex web application development (Zope just kicks the crap out of
    most of the other app server options out there)

  2. Java application scripting (Jython is one of the better, if not best,
    scripting options for Java)

  3. Basic programming education (though this is more because of the
    availability of complete tutorials and libraries than the quality of the
    language itself)

Until recently, I might have included “sandboxed” code in this list, but
from what I understand, the ‘rexec’ functionality in Python 2.3 is
seriously broken, and is not necessarily going to be fixed any time soon.

Lennon

“Peter Hickman” peter@semantico.com schrieb im Newsbeitrag
news:3E7AD9E0.3080805@semantico.com

Or perhaps teach them OO in Ruby for it’s simplicity and then switch to
Java and watch their hair fall out.

Peter,

my hair fell out because of C++, colleagues and customers. Thanks to Java
I still have some left. (Of course this might be more, if it would have
been Ruby in the first place…)
:slight_smile:

Regards

robert

Thanks Paul. Sometimes its easy for those of us who are very familiar
with Ruby to neglect features of a language we are less familiar with.

Yes, this was the case. I do not want to propagate misinformation.

It sounds to me as if the original poster is looking for a “slam dunk”
for Ruby (compared to Python), and I’m not sure he’s going to find
one.

Well, in my defense, it wasn’t me who was looking for such a thing. I’m
a much more subtle person. :wink: My lecterer wanted a “slam dunk” and was
perhaps using a straw-man tactic to argue Python’s equivalence. What I
want are a few benefits Ruby has in practice over Python. Not
necessarily technical capabilities (which are usually obscure) but
features which are frequently taken advantage of by its programmers
where the equivalent Python is not impossible, but significantly more
difficult.

Ruby and Python have far more in common than they have
differences. What differences there are more more differences in
preferences than real differences in language power.

They are very similar but since researching the differences I’ve found
that there are significant differences in common practice adopted by
Ruby and Python programmers. Ruby’s learning curve is decidedly easier,
for example, due he POLS and its small, powerful and reasonably
consistent standard library which owes a lot to Ruby’s more pure
O-O-ness. Ruby blocks also lend themselves to so many useful things,
and are used so extensively in Ruby, I think it’s very significant.

That is, in terms of what the languages can do, they’re almost exactly
the same. In terms of the nature of the code frequently written in each
language, they’re quite different.

···

Jim Weirich jweirich@one.net wrote:


Greg McIntyre
greg@puyo.cjb.net
http://puyo.cjb.net

Oh! if only I could! :slight_smile: Unfortunately I have no power to do such things.
I’ve been given permission to give one lecture on Ruby, well after the
students have been introduced to Python.

···

Peter Hickman peter@semantico.com wrote:

Irregardless of the benefits of Ruby over Python I do not believe that
dissing one language to make another look good is any way to promote
that language. It is the sort of trick that politicians with weak
arguments are wont to use.

If you want to show how good Ruby is give them some programming
exercises in Java for a term and then switch over to Ruby. When they
see that they can write the program without all that ‘scaffolding’
they will be impressed.

Or perhaps teach them OO in Ruby for it’s simplicity and then switch
to Java and watch their hair fall out.


Greg McIntyre
greg@puyo.cjb.net
http://puyo.cjb.net

Hi –

[re: Greg’s slides]

On Philosophy:

Is this really how a Ruby programmer would characterize POLS? To be
honest, the way you state it, I wouldn’t be interested in either
Python or Ruby. A language that tries to cater to everyone’s tastes is
doomed to failure. Sounds like the popular image of Ada!

According to Matz, POLS is the principle of least surprise to Matz :slight_smile:
It definitely isn’t about catering to all tastes. To quote Matz:

I may surprise you, or even make mistake (often). But still, since
everyone has different background, I can not satisfy everyone. From
this reason, I don’t count POLS as the rationale for any RCR.

and, also perhaps relevant:

I also admit that Ruby offers bunch of surprises when you meet it
for the first time. But once you become familiar with it, you will
feel comfortable programming in it.

POLS has definitely been overworked and overextended as a concept
applying generally to every encounter everyone has, or should expect
to have, with Ruby. In this connection, the “cater to everybody’s
tastes” characterization might inadvertently suggest that Ruby is a
kind of idiom grab-bag and/or designed, chameleon-like, to resemble
any or all of its antecedents depending on who’s using it.

Besides, as many have said before me, Ruby is full of surprises; they
just happen to be pleasant surprises :slight_smile:

David

···

On Mon, 24 Mar 2003, Paul Prescod wrote:


David Alan Black
home: dblack@superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

On Philosophy:

Is this really how a Ruby programmer would characterize POLS? To be
honest, the way you state it, I wouldn’t be interested in either
Python or Ruby. A language that tries to cater to everyone’s tastes is
doomed to failure. Sounds like the popular image of Ada!

Does Ada try to please everyone, or does it rather just try to irk everyone
equally?

(half =)

Paul, Again … good comments. I have just a few comments on your
blocks section.

On Blocks

You say that Python has generators which are equivalent to Ruby’s
blocks. I think that blocks and generators are mostly unrelated. […]

Yes and no. Although they are entirely different things, they both are
used for do “iteration-like” stuff in their respective languages. That
and the fact they both use the keyword “yield” (although with complete
different semantics!) leads people to confuse the two.

Ruby Blocks are nothing more than a little syntactical sugar for
anonyous functions/closures. The Ruby yield is nothing more than a
function call to a special anonymous function attached to a method.

A Python generator is really a form of coroutine. The Python yield
statement doesn’t follow function call/return semantics at all, but
allows the generator to switch between the main code and the generator
code in coroutine style.

But generators do allow you to do something that is very difficult
without them. Consider this code:

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66316

Actually, this code is easy to duplicate with blocks …

def fib
x = 0
y = 1
proc {
x, y = y, x + y
x
}
end

g = fib
9.times { print g.call, " " }
puts

This problem is was easy to convert because the basic loop is easy to
unroll. If the algorithm were more deeply nested, or used yield in
multiple locations, the conversion would be more obscure. For example,
a generator that returned the leaves of a tree data structure would be
fairly easy using generators, but more difficult without.

For those tougher problems, a Ruby programmer might resort to using
continuations. Continuations are much more powerful than generators,
but also much harder to use and understand.

So, in summary, this is how I see it. Ruby uses blocks/closures for
most of its iteration needs, switching to continuations or other
mechanisms for the hard cases. Python uses a more powerful technique
that handles the common case and some of the harder cases.

One more minor thing …

[…] but you can only pass one block (unless you wrap it in a
function!). I think.

No, you would simply pass a proc object instead …

def upload(handle_data_proc, output_proc, print_error_proc, etc)

upload(proc{|data| blocks.append(data)},
proc{|data| logger.write_msg(data)},
proc{ logger.write_err(data)},
5)

···

On Sun, 2003-03-23 at 16:17, Paul Prescod wrote:


– Jim Weirich jweirich@one.net http://w3.one.net/~jweirich

“Beware of bugs in the above code; I have only proved it correct,
not tried it.” – Donald Knuth (in a memo to Peter van Emde Boas)

You can write that almost exactly the same in Ruby of course: substitute
proc { |foo| … } for lambda foo:

But Ruby gives you other choices. You could pass a method of an existing
object, e.g. $stdout.method(:write) and $stderr.method(:write)

If I were writing the above, rather than passing in two functions, I’d
probably just pass in two IO-like objects, and call output_obj.write and
error_obj.write respectively. Ruby’s convention that things you can write to
have a method called ‘write’ is pretty simple, and you can always add a
‘write’ object to something which doesn’t already have one.

I skipped over a lot of this discussion, but did anyone mention space-
sensitive syntax? It’s so nice to be able to put

if false

end

around a piece of code, and not have to re-indent the whole lot!

Regards,

Brian.

···

On Mon, Mar 24, 2003 at 06:17:49AM +0900, Paul Prescod wrote:

The nice thing about blocks (compared to straightforward higher order
functions) is that they have a nice syntax. But I think that they are
more limited in that you can pass many higher order functions to a
procedure but you can only pass one block (unless you wrap it in a
function!). I think.

e.g.

def upload(handle_data_func, output_func, print_error_func, block_limit)
for blocknum in 0, block_limit
try:
block = read_block_from_network()
output_func("block received " + blocknum)
handle_data_func(block)
except:
print_error_func(“something screwed up”)

upload(handle_data_func = lambda data: blocks.append(data),
output_func = lambda data: logger.write_msg(data),
print_error_func = lambda: logger.write_err(data),
block_limit = 5)

My only quibble is when you say that in Ruby, types and classes are
the same thing.

I don’t know any Python, so maybe you are trying to say that the role
of"types" in Python is taken care of by classes in Ruby… i.e. there
is another kind of thing in Python called a “type”, but Ruby unifies
that concept with the “class” concept. Maybe that’s what you mean…
I don’t know.

Yes, I was referring to the fact that Python has both ‘types’ and
‘classes’.

So I have implicity “defined” a duck type without ever making a Duck
class. In Java I would need a class or an interface or something, but
in Ruby that’s all behond the scenes.

Er… in this example you have an object of class String with an extra
method. IMO, this is still of class String. I don’t address singleton
methods in the lecture. Should I? I’ve never used them and I very rarely
see others using them. Are they that important to be included in a quick
intro of Ruby?

···

“Chris Pine” nemo@hellotree.com wrote:


Greg McIntyre
greg@puyo.cjb.net
http://puyo.cjb.net

It’s very nice. I hope it ends up on the ruby-lang site or somewhere
comparable.

Thankyou. So do I.

One minor problem. In recent versions of ruby,

“hello”.gsub(“[^aeiou]”) …

will not treat “[^aeiou]” as a regex but as a literal string, and
there will be a warning. So for compatibility this should be

“hello”.gsub(/[^aeiou]/) …

Thanks. I’ll fix that.

Also, something you might want to point out that would appeal even to
people who are still going to use Python for general purpose
programming: Ruby, like Perl, is great for one-liners. (This was
pointed out as an advantage over Python in http://ruby-talk.org/45398)
I’m sure folks on this list will come up with many examples, if you
want them…

Mmm… that’s true although I was going to vaguely refer to that in the
lecture (that Ruby generally allows you to chain methods together on an
object, and that sometimes your entire Ruby program ends up one line as
a result). I’ll make it clearer that this lets you do powerful
one-liners from the command line… maybe give a little demonstration
with

ruby -pe ‘…’

···

Joel VanderWerf vjoel@PATH.Berkeley.EDU wrote:


Greg McIntyre
greg@puyo.cjb.net
http://puyo.cjb.net

On Philosophy:

Is this really how a Ruby programmer would characterize POLS? To be
honest, the way you state it, I wouldn’t be interested in either
Python or Ruby. A language that tries to cater to everyone’s tastes is
doomed to failure. Sounds like the popular image of Ada!

Hrm… perhaps the description I’ve given is a little silly. It’s one
thing to be flexible and expressive, but another to try to please
everybody.

As far as “Only One Way To Do It.” I’m sure that the way you describe
Python is not how a Python programmer would! :wink: Let me try:

“Only one way to do it.”

“Also known in computer science literature as “orthogonality”, Python
attempts to reduce to a minimum the variant ways of “spelling” a
common construct. This improves the regularity of code, reduces the
size of the Python language and makes reading other people’s code
easier.”

But I don’t expect you to put in such a Python-positive spin!

I’m happy to give a Python-positive spin. I’m sorry if you feel I’ve
been negative about it. I’ll redo the philosophy bit after more
comments here (so I get it right).

If Python is “rigid” what does that say about Java, COBOL, Pascal, C
and other similar languages that are much more strict than Python?

They’re horribly strict. :slight_smile:

Re: type and class. Consistency of method use is unrelated to the
issue of type and class. It has always been the case that Python types
could have methods. The array type has always had methods. If you want
to knock Python for being inconsistent about functions versus methods
it would be more straightforward just to do so.

True. I’ll fix that.

···

Paul Prescod paul@prescod.net wrote:


Greg McIntyre
greg@puyo.cjb.net
http://puyo.cjb.net

dblack@superlink.net wrote:

Overall it looks good to me (though I say that as a Python
know-nothing – mainly focusing on the Ruby stuff). There’s one
example I think is misleading:

Private attribute x of class A in Ruby:

class A
def initialize; @x = 0; end
end
a = A.new; a.x = 1 # exception!

The problem here is that there is no method x, private or otherwise.

Well, that’s kind of the point. These slides don’t attempt to explain
everything in detail (otherwise there’d be a lot more of them). That’s
my job as a lecturer. I don’t want to make myself superfluous. :slight_smile:

(This might also have implications for the equivalence you draw
between"self.attribute" in Python and “@attribute” in Ruby, but I’m
not sure exactly what’s going on on the Python side there.)

‘self’ is the first parameter in a Python method. Because Ruby doesn’t
do things this way, (perhaps something I should note on the slides),
it has to define ‘self’ as a special constant, but also has the @
prefix as a shortcut (for ‘self.’).

class A:
def method(self, arg0, arg1, …, argN):
self.x = something

a = A()
a.method(1,2,3) # arg0, arg1, arg2 = 1,2,3

class A
def method(arg0, arg1, …, argN)
@x = something
self.x = something # also valid
end
end

···


Greg McIntyre
greg@puyo.cjb.net
http://puyo.cjb.net

Slide 3, bullet point 1: Ruby is strongly typed (all objects have a
type) and dynamically typed (type is determined at run time).

Hrm… let’s ask the trusty old FOLDOC…

http://foldoc.doc.ic.ac.uk/foldoc/foldoc.cgi?strongly+typed
http://foldoc.doc.ic.ac.uk/foldoc/foldoc.cgi?weakly+typed

It seems Ruby is neither, although there is no definition for “loosely
typed” which I may have invented. :\

Perhaps this is a matter of whose definition you use.

Slide 4, POLS: Ruby syntax is familiar to those who have programmed in
C, Lisp, Perl (especially as to regular expressions) or SmallTalk, but
is accessible to those who have never programmed before. The initial
learning curve for Ruby is very easy for almost anyone first
encountering the language.

Mmm… with all due respect, I think this is something I can discuss
during the lecture without it being on the slides.

This is another outstanding addition to the resources introducing Ruby
to new users.

Woa, thanks. :slight_smile:

···

Mark Wilson mwilson13@cox.net wrote:


Greg McIntyre
greg@puyo.cjb.net
http://puyo.cjb.net

Problems:

  • ports? more like wrappers (“port” implies it has been
    reimplemented in Ruby)

s/ports/wrappers/ it is.

  • “nearly all” common C/C++ libraries? I doubt it, although
    I could be wrong

Okay okay. It was a bit of a vague statement deliberately. What do you
suggest I write? Many common C/C++ libraries?

···

Gavin Sinclair gsinclair@soyabean.com.au wrote:


Greg McIntyre
greg@puyo.cjb.net
http://puyo.cjb.net

Idan Sofer wrote:

Greg McIntyre wrote:

would be one focus of the lecture. But I’m interested in specific
examples where the equivalent Python code is significantly more
difficult.

Perhaps situation when you wish to do method run-time optimization.

data.txt is read only once per instance, but no run-time check(if @data)
is needed, Foo#parse just rewrites Foo#data at runtime as singleton method.

There no such kind of technique in python AFAIK.

I think that the more straightforward way of coding this is cleaner, but
you can do it this way in Python too. (probably since Python 1.0, though
you would use def instaead of lambda)

class Foo:
def parse(self, filehandle):
# …
print “parsing”
data = filehandle.read()
Foo.data = lambda(self): data
return data

 def data(self):
     filehandle = open("/tmp/test.txt")
     return self.parse(filehandle)

a = Foo()
print a.data()
print a.data()
print a.data()
print a.data()
print a.data()

I’m not promoting Python but I’m going to correct inaccuracies I see!

Paul Prescod