Why I chose Python over Ruby

F

Francois

I discovered Python a few months ago and soon decided to invest time in
learning it well. While surfing the net for Python, I also saw the hype
over Ruby and tried to find out more about it, before I definitely
embarked on studying and practicing Python. I recently found two
sufficient answers for choosing Python - which is a personal choice and
others may differ, but I'd like to share it anyway :

1) In Ruby there is a risk of "Variable/Method Ambiguity" when calling
a method with no parameters without using () :

Here is an excerpt from the book "Programming Ruby The Pragmatic
Programmer's Guide".

http://www.rubycentral.com/book/language.html

"When Ruby sees a name such as ``a'' in an expression, it needs to
determine if it is a local variable reference or a call to a method
with no parameters. To decide which is the case, Ruby uses a heuristic.
As Ruby reads a source file, it keeps track of symbols that have been
assigned to. It assumes that these symbols are variables. When it
subsequently comes across a symbol that might be either a variable or a
method call, it checks to see if it has seen a prior assignment to that
symbol. If so, it treats the symbol as a variable; otherwise it treats
it as a method call. As a somewhat pathological case of this, consider
the following code fragment, submitted by Clemens Hintze."

def a
print "Function 'a' called\n"
99
end

for i in 1..2
if i == 2
print "a=", a, "\n"
else
a = 1
print "a=", a, "\n"
end
end

OUTPUTS >>

a=1
Function 'a' called
a=99

"During the parse, Ruby sees the use of ``a'' in the first print
statement and, as it hasn't yet seen any assignment to ``a,'' assumes
that it is a method call. By the time it gets to the second print
statement, though, it has seen an assignment, and so treats ``a'' as a
variable.
Note that the assignment does not have to be executed---Ruby just has
to have seen it. This program does not raise an error."

I tried the code above at the interactive Ruby 1.8.2 interpreter :

http://www.ruby.ch/tutorial/

2) Ruby does not have true first-class functions living in the same
namespace as other variables while Python does :

In Python :

def sayHello (name) :
return "Hello " + name
print sayHello("Mr. Bond")
m = sayHello
print m
print m("Miss Moneypenny")

OUTPUTS >>

Hello Mr. Bond
<function sayHello at 0x0102E870>
Hello Miss Moneypenny

In Ruby you need extra syntax that ruins the "first-class-ness" :

def sayHello (name)
return "Hello " + name
end
puts sayHello("Mr. Bond")
m = Class.method:)sayHello)
puts m
puts m.call("Miss Moneypenny")

OUTPUTS >>

Hello Mr. Bond
#<Method: Class(Object)#sayHello>
Hello Miss Moneypenny

4) Conclusion

Since I did a lot of work in Scheme, rigor and consistency are most
important to me, and Python certainly meets this requirement.

--- Python newbie
 
S

Sybren =?UTF-8?B?U3TDvHZlbA==?=

Francois said:
I discovered Python a few months ago and soon decided to invest time
in learning it well. While surfing the net for Python, I also saw
the hype over Ruby and tried to find out more about it, before I
definitely embarked on studying and practicing Python. I recently
found two sufficient answers for choosing Python - which is a
personal choice and others may differ, but I'd like to share it
anyway

Thanks for sharing that. I had a gut feeling Python would be better
than Ruby, but I never took the time to study Ruby. Now I do have some
nice stones to throw at Ruby-fanatics ;-)

Sybren
 
A

Alex Martelli

Francois said:
Since I did a lot of work in Scheme, rigor and consistency are most
important to me, and Python certainly meets this requirement.

It does pretty well, with some tempering of pragmatism -- but, to play
devil's advocate, Ruby isn't far in this respect. In either case, you
will find more rigor and consistency in good languages of a more
academic bent, such as Haskell, but will surely find a lot in either
Ruby or Python.

The trick about distinguishing a name's exact nature based on whether
the compiler sees an assignment to that name in some part of code is
found in both languages, albeit in different ways. In Ruby, as you've
pointed out, it's the heuristic used to disambiguate local variable
access from zero-argument method calls, and the "part of code" is the
function up to the point of access. In Python, it's used to disambiguate
local from global or free variables, and the "part of code" is the body
of the whole function (Ruby does not need to make this latter
distinction because it strops global names with a leading sigil -- $a is
always the global variable a, just like @a is always the instance
attribute a, which we'd write self.a in Python). Another subtle case in
Ruby is whether an assignment such as a=23 _within a block_ is meant to
be local to the block or meant to rebind local name 'a' within the
enclosing function; again, the heuristic is similar, depending only on
whether the compiler had seen another assignment to a before it saw the
block (Python forbids the rebinding of variables coming from an
enclosing but non-global scope, to avoid facing this issue).

All in all, Python is more likely with these heuristics to respect the
principles (from the "zen of python", import this at an interactive
prompt): in face of ambiguity, refuse the temptation to guess; errors
should not pass silently, unless explicitly silenced. I.e., any Python
code which accidentally runs afoul of these heuristics is likely to
raise an exception, alerting you to the situation. Ruby strives rather
for a "do what I mean" ethos, and obviously some people prefer that.

I also share your preference for a single namespace for callable and
non-callable values, as in Python (and Scheme, Lisp, C++, ...), rather
than disjoint namespaces as in Ruby (and Smalltalk), but I do not see it
as a question of rigor and consistency at all -- e.g., I do not perceive
Smalltalk as less rigorous or consistent than C++, on the contrary.

So, I agree with your choice, and I think I understand your motivations,
but I do not entirely share your motivations, personally speaking.


Alex
 
F

Francois

Alex said:
I also share your preference for a single namespace for callable and
non-callable values, as in Python (and Scheme, Lisp, C++, ...), rather
than disjoint namespaces as in Ruby (and Smalltalk), but I do not see it
as a question of rigor and consistency at all -- e.g., I do not perceive
Smalltalk as less rigorous or consistent than C++, on the contrary.

So, I agree with your choice, and I think I understand your motivations,
but I do not entirely share your motivations, personally speaking.

Thanks Alex for your excellent explanations. I have the Python Cookbook
2nd Ed., and I highly appreciate your knowledge and experience.

I guess my choice of words "rigor and consistency" was not very good.
In this context "rigor" meant enforcing rules (for example having to
use parentheses to call a method) to prevent ambiguity rather than
depending on heuristics. Also "consistency" meant doing things as
uniformly as possible (for example always call a method with the same
syntax, whether the variable referencing it is the original name or an
alias).

-- Francois
 
M

mensanator

Francois said:
I discovered Python a few months ago and soon decided to invest time in
learning it well. While surfing the net for Python, I also saw the hype
over Ruby and tried to find out more about it, before I definitely
embarked on studying and practicing Python. I recently found two
sufficient answers for choosing Python - which is a personal choice and
others may differ, but I'd like to share it anyway :

1) In Ruby there is a risk of "Variable/Method Ambiguity" when calling
a method with no parameters without using () :
2) Ruby does not have true first-class functions living in the same
namespace as other variables while Python does :
4) Conclusion
Since I did a lot of work in Scheme, rigor and consistency are most
important to me,

What happened to 3)?
 
F

Francois

Alex said:
I also share your preference for a single namespace for callable and
non-callable values, as in Python (and Scheme, Lisp, C++, ...), rather
than disjoint namespaces as in Ruby (and Smalltalk), but I do not see it
as a question of rigor and consistency at all -- e.g., I do not perceive
Smalltalk as less rigorous or consistent than C++, on the contrary.

So, I agree with your choice, and I think I understand your motivations,
but I do not entirely share your motivations, personally speaking.

Thanks Alex for your excellent explanations. I have the Python Cookbook
2nd Ed., and I highly appreciate your knowledge and experience.

I guess my choice of words "rigor and consistency" was not very good.
In this context "rigor" meant enforcing rules (for example having to
use parentheses to call a function) to prevent ambiguity rather than
depending on heuristics. Also "consistency" meant doing things as
uniformly as possible (for example always call a function with the same
syntax, whether the variable referencing it is the original name or an
alias).

-- Francois
 
A

Alex Martelli

Francois said:
I guess my choice of words "rigor and consistency" was not very good.
In this context "rigor" meant enforcing rules (for example having to
use parentheses to call a method) to prevent ambiguity rather than
depending on heuristics. Also "consistency" meant doing things as
uniformly as possible (for example always call a method with the same
syntax, whether the variable referencing it is the original name or an
alias).

Ah yes, these are definitely valid nuances for the terms you've used, I
admit that. Python's yearning for "only one obvious way" to do
something, even though it's a goal to aim for rather than a reality in
every case, surely does play towards these preferences, while Ruby (not
quite as much as Perl, but still) has a more exhuberant approach, where
having multiple obvious ways to do the same thing is seen as a plus, not
a minus (a classic tiny example is the ability to get the number of
items of an array a by EITHER a.size or a.length, just like for a C++
std::string, with no difference whatsoever among the two synonyms).

So, I'm NOT saying your word choice was not very good: you used words
who do mean what you intend (among other meanings, but then, that's the
curse AND blessing of natural language;-). But anyway, thanks for the
clarification! Maybe "uniformity" (though it, too, may suggest
different and not accurate things) could be usefully added to help
communicate your intended meaning (or maybe, for most people, if they
hear all of "rigor, consistency, uniformity", would think of some Nazi
language woefully constraining their expression...?-)


Alex
 
X

Xavier Morel

I'll just play the devil's advocate here
1) In Ruby there is a risk of "Variable/Method Ambiguity" when calling
a method with no parameters without using () :
Yes, but that's in my opinion a programmer error, not necessarily a
language error.
2) Ruby does not have true first-class functions living in the same
namespace as other variables while Python does :

In Ruby you need extra syntax that ruins the "first-class-ness" :
The extra syntax is a side-effect of the parensless call of method, it
doesn't mean that methods are not first-class objects.

And Ruby solved this issue with blocks/procs (that and closures are the
only reasons I found for blocks to exist in ruby). In python you pass
functions around, Ruby's equivalent of unbound functions are
blocks/procs, what your code created here is a ruby method, equivalent
to a bound method in Python, the semantics are really different (and in
Python using this bound method would also require extra work).
 
G

Guest

Francois said:
I discovered Python a few months ago and soon decided to invest time in
learning it well. While surfing the net for Python, I also saw the hype
over Ruby and tried to find out more about it, before I definitely
embarked on studying and practicing Python. I recently found two
sufficient answers for choosing Python - which is a personal choice and
others may differ, but I'd like to share it anyway :

I use both Python and Ruby and I think You are a little bit unfair in
your judgements.

1) In Ruby there is a risk of "Variable/Method Ambiguity" when calling
a method with no parameters without using () :
def a
print "Function 'a' called\n"
99
end

for i in 1..2
if i == 2
print "a=", a, "\n"
else
a = 1
print "a=", a, "\n"
end
end

OUTPUTS >>

a=1
Function 'a' called
a=99

Yes, I agree with that, but being aware of that I have never had any
problems. And this problem a arises only in method bodies. When a
receiver is specified, there is no ambiguousity (Ruby objects dont have
public fields)
2) Ruby does not have true first-class functions living in the same
namespace as other variables while Python does :

Wrong! Ruby has first class functions and unlike Python Ruby supports
_true_ closures (Python supports only readonly closures). The first
class Ruby functions are the _blocks_.
In Python :

def sayHello (name) :
return "Hello " + name
print sayHello("Mr. Bond")
m = sayHello
print m
print m("Miss Moneypenny")

OUTPUTS >>

Hello Mr. Bond
<function sayHello at 0x0102E870>
Hello Miss Moneypenny

In Ruby you need extra syntax that ruins the "first-class-ness" :

No, blocks again...
def sayHello (name)
return "Hello " + name
end
puts sayHello("Mr. Bond")
m = Class.method:)sayHello)
puts m
puts m.call("Miss Moneypenny")

OUTPUTS >>

Hello Mr. Bond
#<Method: Class(Object)#sayHello>
Hello Miss Moneypenny

4) Conclusion

Since I did a lot of work in Scheme, rigor and consistency are most
important to me, and Python certainly meets this requirement.

--- Python newbie

Depends, I like Pythons constructs consistency, but I also like Rubys
object model constency

lopex
 
?

=?ISO-8859-1?Q?Sch=FCle_Daniel?=

Hi Alex

[...]
The trick about distinguishing a name's exact nature based on whether
the compiler sees an assignment to that name in some part of code is
found in both languages, albeit in different ways. In Ruby, as you've
pointed out, it's the heuristic used to disambiguate local variable
access from zero-argument method calls, and the "part of code" is the
function up to the point of access. In Python, it's used to disambiguate
local from global or free variables, and the "part of code" is the body
of the whole function (Ruby does not need to make this latter
distinction because it strops global names with a leading sigil -- $a is
always the global variable a, just like @a is always the instance
attribute a, which we'd write self.a in Python). Another subtle case in
Ruby is whether an assignment such as a=23 _within a block_ is meant to
be local to the block or meant to rebind local name 'a' within the
enclosing function; again, the heuristic is similar, depending only on
whether the compiler had seen another assignment to a before it saw the
block (Python forbids the rebinding of variables coming from an
enclosing but non-global scope, to avoid facing this issue).

I am not sure what you mean here
can you elaborate on this please
.... q = []
.... def b(x):
.... def c(y):
.... def d(z):
.... q.append(x)
.... q.append(y)
.... q.append(z)
.... d(1)
.... c(2)
.... b(3)
.... return q
....[3, 2, 1]

As far as I know this snippet would work only from version 2.2
maybe you are talking about older versions of Python

Regards, Daniel
 
T

Terry Reedy

Schüle Daniel said:
block (Python forbids the rebinding of variables coming from an
enclosing but non-global scope, to avoid facing this issue).

I am not sure what you mean here
can you elaborate on this please
... q = []
... def b(x):
... def c(y):
... def d(z):
... q.append(x)
... q.append(y)
... q.append(z)
... d(1)
... c(2)
... b(3)
... return q
...[3, 2, 1]

You are mutating q, not rebinding it. As another poster discovered,
replacing the appends by the nominally equivalent augmented assignments:

q += [x] #etc

does not work. Since the compiler does not know the type of q, it assumes
that it needs to be rebound and compiles code to do so, even though here is
would be to the same object. That makes q an (uninitialized) local.

Terry Jan Reedy
 
R

Roy Smith

Xavier Morel said:
Yes, but that's in my opinion a programmer error, not necessarily a
language error.

In Python, you can make exactly the opposite error. Both of these are
perfectly legal and reasonable things to write, where foo is a function:

a = foo
a = foo()

Actually, if you want to have a little fun, try:

def foo:
return foo

then you can write:

a = foo
a = foo()
a = foo()()
a = foo()()()
a = foo()()()()
etc.
 
B

Bil Kleb

Xavier said:
The extra syntax is a side-effect of the parensless call of method, it
doesn't mean that methods are not first-class objects.

The parensless calls also allow one to write beautiful
DSLs with Ruby.
 
X

Xavier Morel

Bil said:
The parensless calls also allow one to write beautiful
DSLs with Ruby.
Yes, they're a tradeoff, they have both advantages and inconvenients.

Matz decided that the advantages were more than worth the inconvenients,
and it is often true indeed for Matz built the language with this very
feature (and some others) in mind.
 
G

Guest

Roy said:
What's a DSL?

Domain Specific Language. It is easy to tweak Rubys syntax and semantics
into something that looks like another language designed for a specific
task.

lopex
 
T

Torsten Bronger

Hallöchen!

Marcin Mielżyński said:
Domain Specific Language. It is easy to tweak Rubys syntax and
semantics into something that looks like another language designed
for a specific task.

Yes, however, this is also true for Python in my opinion. It boils
down to a matter of taste. I deliberately left C++ one year ago. I
looked at various alternatives.

After a short time I concentrated on Ruby v. Python. I read a lot
of language comparisons (with both biases). Well, my conclusion
was: All "this language has this, and this language has that" is
pretty pointless because both languages are very similar and equally
sophisticated. I found the appearance of Python code more
appealing, that was all. The "fits my brain" argument is much more
useful than all discussions about things like continuatons or
multiple inheritance.

The actual reason to choose Python was its set of tools, modules,
and Usenet participants. I don't want to do something manually in
Ruby which I could have had ready-for-use in Python just for
infinitesimally nicer syntax. Probably I'm just too old for
language adventures. Ruby might be good enough for me in three
years but I want to have the full fun now.

Tschö,
Torsten.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top