Python and Ruby

  • Thread starter Jean Guillaume Pyraksos
  • Start date
S

Steven D'Aprano

You don't have to buy my argument, I am not selling it.

It's a figure of speech. You are making an argument others have made
before, and I don't accept the validity of the argument.
 
S

Steven D'Aprano

Yes it can. I *have* seen Python with broken indentation on web pages,
and good luck sorting it out. Blaming it on "broken tools" is just
another straw man.

You're using that term wrong. It looks to me that you don't actually know
what a straw man argument is. A straw man argument is when somebody
responds to a deliberately weakened or invalid argument as if it had been
made by their opponent. You raised the issue that the redundancy which
prettyfiers exploit are a good reason for preferring braces, so it's not
a straw man argument.

It's not a straw man to say that you don't need a code prettyfier if
indentation is significant when you raised the issue of prettyfiers in
the first place.

I certainly accept that braces + indentation do provide redundancy, and
if the norm was noisy channels, that redundancy would be valuable. But
that's not the norm. Most channels don't delete leading whitespace, and
those noisy channels we do deal with (like web forms) tend to introduce
far more noise than merely deleting leading whitespace, e.g. word-
wrapping long lines.

The argument that "web pages break indentation, therefore braces are
better" is a real argument that some people make, but it is very weak.
Suppose there was a web page that arbitrarily deleted braces out of some
misplaced sense of security. Would anyone argue that this proves that
indentation was better and braces were bad? No, of course not -- they
would say "That website is broken".



It happens, and if you're learning Python and
interested in that code you have a problem.

Yes you do.

If you're trying to learn carpentry, and somebody gives you a blunt saw
that causes the wood to break rather than cut cleanly, you have a
problem. If you're learning to cook, and they give you a put with a hole
in it and tell you to make soup in it, you have a problem.

Broken tools lead to problems.

Snipped the rest, because you start to sound like a zealot. I should've
know better.

Yeah, whatever.
 
A

alex23

Steven D'Aprano said:
You're using that term wrong. It looks to me that you don't actually know
what a straw man argument is. A straw man argument is when somebody
responds to a deliberately weakened or invalid argument as if it had been
made by their opponent.

Jeez, Steve, you're beginning to sound like some kind of fallacy
zealot... ;)
 
S

Steven D'Aprano

Jeez, Steve, you're beginning to sound like some kind of fallacy
zealot... ;)

Death to all those who confuse agumentum ad populum with argumentum ad
verecundiam!!!
 
S

Steve Holden

Steven said:
Death to all those who confuse agumentum ad populum with argumentum ad
verecundiam!!!
Yeah, what did the zealots ever do for us?

regards
Steve
 
J

Jonathan Gardner

I'm not familiar with Ruby, but most languages are cleaner than Python
once you get beyond the "10-minute introduction" stage.

Probably too little, too late (haven't read all of the replies yet...)

I judge a language's simplicity by how long it takes to explain the
complete language. That is, what minimal set of documentation do you
need to describe all of the language? With a handful of statements,
and a very short list of operators, Python beats out every language in
the Algol family that I know of.

I can think of only one language (or rather, a class of languages)
that can every hope to be shorter than Python. I doubt you've heard of
it based on your comments, but I suggest you look into it.
Unfortunately, to fully appreciate that language, you're going to have
to study a textbook called "SICP". At the end of that textbook, you
are blessed to not only see but understand the complete compiler for
the language, in the language itself.
 
J

Jonathan Gardner

yuck! wrapping the arg list with parenthesis (python way) makes the
most sense. Its to easy to misread somthing like this

onetwothree four five six

onetwothree(four, five, six) #ahhh... plain english.

In Lisp-ish languages, you have a list of stuff that represents a
function call:

(a b c d)

means: Call "a" with values (b, c, d)

While this certainly doesn't agree with what you learned in Algebra,
it is a reasonable syntax that exposes the code-data duality of
programs. There is, however, one fatal flaw. Why is the first element
so different than the rest? This is inconsistent with what people who
are unfamiliar with the language would expect. Indeed, in teaching
Lisp, learners have to be reminded about how the evaluator looks at
lists and processes them.

I would expect a clear, simple language to have exactly one way to
call a function. This calling notation would clearly distinguish
between the function and its parameters. There are quite a few
options, and it turns out that "function(arg, arg, arg)" is a really
good compromise.

One of the bad things with languages like perl and Ruby that call
without parentheses is that getting a function ref is not obvious. You
need even more syntax to do so. In perl:

foo(); # Call 'foo' with no args.
$bar = foo; # Call 'foo; with no args, assign to '$bar'
$bar = &foo; # Don't call 'foo', but assign a pointer to it to '$bar'
# By the way, this '&' is not the bitwise-and '&'!!!!
$bar->() # Call whatever '$bar' is pointing at with no args

Compare with python:

foo() # Call 'foo' with no args.
bar = foo() # 'bar' is now pointing to whatever 'foo()' returned
bar = foo # 'bar' is now pointing to the same thing 'foo' points to
bar() # Call 'bar' with no args

One is simple, consistent, and easy to explain. The other one requires
the introduction of advanced syntax and an entirely new syntax to make
function calls with references.

Note that the Algebra notation of functions allows for an obvious,
simple way to refer to functions without calling them, leading to
syntax such as "f o g (x)" and more.
 
J

Jonathan Gardner

If it was common-place to use Curried functions and partial application in
Python, you'd probably prefer "f a b c" to "f(a)(b)(c)" as well.

That's just the point. It isn't common to play with curried functions
or monads or anything like that in computer science today. Yes,
Haskell exists, and is a great experiment in how such a language could
actually work. But at the same time, you have to have a brain the size
of the titanic to contain all the little details about the language
before you could write any large-scale application.

Meanwhile, Python's syntax and language is simple and clean, and
provides tremendous expressiveness without getting in the way of the
programmer.

Comparing Python's syntax to Haskell's syntax, Python is simpler.
Comparing what Python can do to what Haskell can do, Haskell is much
faster at certain tasks and allows the expression of certain things
that are difficult to express in Python. But at the end of the day,
the difference really doesn't matter that much.

Now, compare Python versus Language X along the same lines, and the
end result is that (a) Python is extraordinarily more simple than
Langauge X, and (b) Python is comparable in expressiveness to Language
X. That's the #1 reason why I like Python, and why saying Ruby and
Python are similar isn't correct.
 
C

Chris Rebert

In Lisp-ish languages, you have a list of stuff that represents a
function call:

 (a b c d)

means: Call "a" with values (b, c, d)

While this certainly doesn't agree with what you learned in Algebra,
it is a reasonable syntax that exposes the code-data duality of
programs. There is, however, one fatal flaw. Why is the first element
so different than the rest? This is inconsistent with what people who
are unfamiliar with the language would expect. Indeed, in teaching
Lisp, learners have to be reminded about how the evaluator looks at
lists and processes them.

I would expect a clear, simple language to have exactly one way to
call a function. This calling notation would clearly distinguish
between the function and its parameters. There are quite a few
options, and it turns out that "function(arg, arg, arg)" is a really
good compromise.

One of the bad things with languages like perl and Ruby that call
without parentheses is that getting a function ref is not obvious. You
need even more syntax to do so. In perl:

 foo();       # Call 'foo' with no args.
 $bar = foo;  # Call 'foo; with no args, assign to '$bar'
 $bar = &foo; # Don't call 'foo', but assign a pointer to it to '$bar'
             # By the way, this '&' is not the bitwise-and '&'!!!!
 $bar->()     # Call whatever '$bar' is pointing at with no args

Compare with python:

 foo()       # Call 'foo' with no args.
 bar = foo() # 'bar' is now pointing to whatever 'foo()' returned
 bar = foo   # 'bar' is now pointing to the same thing 'foo' points to
 bar()       # Call 'bar' with no args

One is simple, consistent, and easy to explain. The other one requires
the introduction of advanced syntax and an entirely new syntax to make
function calls with references.

Ruby isn't nearly as bad as Perl in this regard; at least it doesn't
introduce extra syntax (though there are extra method calls):

foo # Call 'foo' with no args.
bar = foo # Call 'foo; with no args, assign to bar
bar = method:)foo) # 'bar' is now referencing the 'foo' "function"
bar.call # Call 'bar' (i.e. 'foo') with no args

Cheers,
Chris
 
P

Paul Rubin

Jonathan Gardner said:
I judge a language's simplicity by how long it takes to explain the
complete language. That is, what minimal set of documentation do you
need to describe all of the language? With a handful of statements,
and a very short list of operators, Python beats out every language in
the Algol family that I know of.

Python may have been like that in the 1.5 era. By now it's more
complex, and not all that well documented. Consider the different
subclassing rules for new and old style classes, the interaction of
metaclasses and multiple inheritance, the vagaries of what operations
are thread-safe without locks, the inter-thread signalling mechanism
that can only be invoked through the C API, the mysteries of
generator-based coroutines, etc. I've never used Ruby and I think its
syntax is ugly, but everyone tells me it's more uniform.

Simplicity is not necessarily such a good thing anyway. Consider FORTH.
 
N

Nobody

That's just the point. It isn't common to play with curried functions
or monads or anything like that in computer science today. Yes,
Haskell exists, and is a great experiment in how such a language could
actually work. But at the same time, you have to have a brain the size
of the titanic to contain all the little details about the language
before you could write any large-scale application.

No, not really. Haskell (and previously ML) are often used as introductory
languages in Comp.Sci. courses (at least in the UK).

You don't need to know the entire language before you can use any of it
(if you did, Python would be deader than a certain parrot; Python's dark
corners are *really* dark).

The lack of mutable state (or at least, the isolation of it within monads)
eliminates a lot of potential problems. How many Python novices get
tripped up by "x = y = [] ; x.append(...); # now y has changed"?

And in spite of the category theory behind monads, Haskell's I/O system
really isn't any more complex than that of any other language, beyond the
constraint that you can only use it in "procedures" (i.e. something
returning an IO instance), not in functions. Which for the most part, is a
net win, as it forces you to maintain a reasonable degree of structure.

Now, if you actually want to use everything the language has to offer, you
can run into some fairly hairy error messages. But then I've found that to
be a common problem with generic programming in general. E.g. error
messages relating to the C++ STL can be quite insanely complex
(particularly when the actual error is "there are so many nested templates
that the mangled function name is longer than the linker can handle" and
it's trying to explain *where* the error is).
 
J

John Bokma

Jonathan Gardner said:
One of the bad things with languages like perl

FYI: the language is called Perl, the program that executes a Perl
program is called perl.
without parentheses is that getting a function ref is not obvious. You
need even more syntax to do so. In perl:

foo(); # Call 'foo' with no args.
$bar = foo; # Call 'foo; with no args, assign to '$bar'
$bar = &foo; # Don't call 'foo', but assign a pointer to it to '$bar'
# By the way, this '&' is not the bitwise-and '&'!!!!

It should be $bar = \&foo
Your example actually calls foo...

[..]
One is simple, consistent, and easy to explain. The other one requires
the introduction of advanced syntax and an entirely new syntax to make
function calls with references.

The syntax follows that of referencing and dereferencing:

$bar = \@array; # bar contains now a reference to array
$bar->[ 0 ]; # first element of array referenced by bar
$bar = \%hash; # bar contains now a reference to a hash
$bar->{ key }; # value associated with key of hash ref. by bar
$bar = \&foo; # bar contains now a reference to a sub
$bar->( 45 ); # call sub ref. by bar with 45 as an argument

Consistent: yes. New syntax? No.

Also, it helps to think of

$ as a thing
@ as thingies indexed by numbers
% as thingies indexed by keys
 
N

Nobody

I judge a language's simplicity by how long it takes to explain the
complete language. That is, what minimal set of documentation do you
need to describe all of the language?

That's not a particularly good metric, IMHO.

A simple "core" language doesn't necessarily make a language simple to
use. You can explain the entirety of pure lambda calculus or combinators
in five minutes, but you wouldn't want to write real code in either (and
you certainly wouldn't want to read such code which was written by someone
else).

For a start, languages with a particularly simple "core" tend to delegate
too much to the library. One thing which puts a lot of people off of
lisp is the lack of infix operators; after all, (* 2 (+ 3 4)) works fine
and doesn't require any additional language syntax. For an alternative,
Tcl provides the "expr" function which essentially provides a sub-language
for arithmetic expressions.

A better metric is whether using N features has O(N) complexity, or O(N^2)
(where you have to understand how each feature relates to each other
feature) or even O(2^N) (where you have to understand every possible
combination of interactions).
With a handful of statements,
and a very short list of operators, Python beats out every language in
the Algol family that I know of.

Not once you move beyond the 10-minute introduction, and have to start
thinking in terms of x + y is x.__add__(y) or maybe y.__radd__(x) and also
that x.__add__(y) is x.__getattribute__('__add__')(y) (but x + y *isn't*
equivalent to the latter due to __slots__), and maybe .__coerce__() gets
involved somewhere, and don't even get me started on __metaclass__ or
__init__ versus __new__ or ...

Yes, the original concept was very nice and clean, but everything since
then has been wedged in there by sheer force with a bloody great hammer.
 
J

John Bokma

Nobody said:
No, not really. Haskell (and previously ML) are often used as introductory
languages in Comp.Sci. courses (at least in the UK).

At least in the early 90's this was also the case in the Netherlands, at
the University of Utrecht. We got Miranda/Gofer, and in a different,
more advanced course Linda (Miranda for parallel machines). Also the
inner workings of functional programming languages was a course. (Can't
recall the name of the book that was used, but it was quite good IMO).

I want to start (re)learning Haskell later this year, because I liked
Miranda/Gofer a lot back then.
 
P

Paul Rubin

Nobody said:
A better metric is whether using N features has O(N) complexity, or O(N^2)
(where you have to understand how each feature relates to each other
feature) or even O(2^N) (where you have to understand every possible
combination of interactions).

M. Felleisen wrote a paper trying to formalize some metric on the
expressive power of programming languages. I skimmed through it for
about a minute and wasn't convinced, but it apparently has gathered some
respect. I want to read it more carefully sometime:

http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.51.4656
 
W

waku

Steven said:
]
The very idea of using a number of blanks to identify your block level
is as insane as it gets.

Not at all. People do it all the time. The very idea of expecting people
to count nested braces to identify block level is what is crazy, which is
why in languages with braces people still indent the blocks.

for reading written code, it's surely helpful to have the code
indented, though for *human* reading, the count of blanks seems rather
inessential, as long as intended difference in indents is more
pronounced than incidental difference between same-level lines.

for writing new code, it's not necessarily that helpful to be *forced*
to keep with strict indenting rules. in early development phases,
code is often experimental, and parts of it may need to be blocked or
unblocked as the codebase grows, and for experimentation, the need to
carefully and consistently indent and de-indent large chunks of code
can easily lead to a mess (blame it on the programmer, not the
language, but still). yes, there are editors that help you indent
chunks of code, but see below.

there are languages where indentation can be either enforced and allow
one to omit some syntactic nuissance like braces or begin-end clauses,
or made optional, requiring other syntactic means for delimiting
blocks etc. (consider f# with its #light declaration, for example.)

[...]
In any case, if your IDE mixes tabs and spaces, your IDE is broken and
you should fix your tools rather than blame the language.

as long as you are limited to your own code, sure. but if many work
on the same bit, and use different editors and indentation policies,
blanks-tabs indentation issues are not unlikely. you can have blanks
converted to tabs and vice versa automatically, but that's clearly a
nuisance.

Nonsense. For the compiler, both are equally reliable, and for the human
reader, indents beat braces easily.

if blanks and tabs are mixed together as indentation, the setting of
your ide can easily mess up the indentation, making the structure
unclear. in some editors, you can have braces highlighted, so that
it's even easier to see where a block ends or starts. and more
advanced editors help one see the structure of the code, whereby both
indentation and braces are made less important for the reader.

but yes, indentation surely helps in reading the code.
Really? So a "sane compiler" sees no difference between:

for x in mylist:

and

forxinmylist:


I'm glad I don't have to program using a compiler you consider "sane".

the point here was, i think, that blanks may have no syntactic
meaning, though they can still be essential at the lexical level.
your example targeted the lexical level, and that's rather irrelevant
to the problem of syntactically meaningful indentation discussed here.

vQ
 
B

bartc

Jonathan said:
One of the bad things with languages like perl and Ruby that call
without parentheses is that getting a function ref is not obvious. You
need even more syntax to do so. In perl:

foo(); # Call 'foo' with no args.
$bar = foo; # Call 'foo; with no args, assign to '$bar'
$bar = &foo; # Don't call 'foo', but assign a pointer to it to '$bar'
# By the way, this '&' is not the bitwise-and '&'!!!!
$bar->() # Call whatever '$bar' is pointing at with no args

Compare with python:

foo() # Call 'foo' with no args.
bar = foo() # 'bar' is now pointing to whatever 'foo()' returned
bar = foo # 'bar' is now pointing to the same thing 'foo' points to
bar() # Call 'bar' with no args

One is simple, consistent, and easy to explain. The other one requires
the introduction of advanced syntax and an entirely new syntax to make
function calls with references.

If you get rid of the syntax specific to Perl, then having to explicitly
obtain a function reference, or to dereference the result, is not such a big
deal:

foo # Call 'foo' with no args.
bar = foo # Call 'foo; with no args, assign to 'bar'
bar = &foo # Don't call 'foo', but assign a pointer to it to 'bar'
bar^ # Call whatever 'bar' is pointing at with no args

(Here I use ^ instead of -> to dereference.) Compared with Python, it saves
3 lots of (), but needs & and ^ added. Still a net saving.
One of the bad things with languages like perl and Ruby that call
without parentheses is that getting a function ref is not obvious.

I'd say that having this "&" symbol in front of "foo" makes it more obvious
than just foo by itself. But I agree not quite as clean.

Another thing is that you have to know whether "bar" is a function, or a
function ref, and use the appropriate syntax. Sometimes this is helpful,
sometimes not.
 
J

Jonathan Gardner

for writing new code, it's not necessarily that helpful to be *forced*
to keep with strict indenting rules.  in early development phases,
code is often experimental, and parts of it may need to be blocked or
unblocked as the codebase grows, and for experimentation, the need to
carefully and consistently indent and de-indent large chunks of code
can easily lead to a mess (blame it on the programmer, not the
language, but still).  yes, there are editors that help you indent
chunks of code, but see below.

there are languages where indentation can be either enforced and allow
one to omit some syntactic nuissance like braces or begin-end clauses,
or made optional, requiring other syntactic means for delimiting
blocks etc.  (consider f# with its #light declaration, for example.)

If you're writing "experimental code", you're doing it wrong. Every
line of code you write may end up on the space shuttle one day (so to
speak!) Why not write the code well-formatted in the first place, so
that any bugs you introduce are as easily visible as possible?

The only reason why you may want to write crap code without proper
formatting is because your text editor is stupid. If that's the case,
get rid of your text editor and find some tools that help you do the
right thing the first time.
as long as you are limited to your own code, sure.  but if many work
on the same bit, and use different editors and indentation policies,
blanks-tabs indentation issues are not unlikely.  you can have blanks
converted to tabs and vice versa automatically, but that's clearly a
nuisance.

If you're text editor has a problem with indenting, you have a
terrible text editor. Period, end of sentence.

You can't screw in bolts with a hammer, and you can't level with a
saw. Don't try to write code in any language without a real text
editor that can do proper indentation. Don't let your teammates use
deficient text editors either. I wouldn't appreciate it if I delivered
precision components that my teammates tried to install with
sledgehammers.

This is the 21st Century. Good text editors are not hard to find on
any platform.
 
J

Jonathan Gardner

You don't need to know the entire language before you can use any of it
(if you did, Python would be deader than a certain parrot; Python's dark
corners are *really* dark).

I'm curious. What dark corners are you referring to? I can't think of
any. Especially with the direction Python 3 is going, it seems like
even the slightly dim corners are being rounded away.

I can explain, in an hour, every single feature of the Python language
to an experienced programmer, all the way up to metaclasses,
__getattribute__, __new__ and __get__. These are the darkest corners I
know of, and these are not at all dark. It takes a few paragraphs of
documentation to explain all the details of each these features. I
hold the entire Python language in my head, and I can still remember
when my next meeting is.

Compare that to something like Haskell, where you have to read entire
books before you truly understand what monads are actually doing
behind the scenes, and how Haskell actually interprets and runs your
program, or to understand what the esoteric error messages that crop
up are actually caused be.

Yes, there are people that know how to do stuff in Haskell. These are
really smart people, the cream of the crop, so to speak. But that
doesn't make Haskell a simple language.
 
J

Jonathan Gardner

FYI: the language is called Perl, the program that executes a Perl
program is called perl.



It should be $bar = \&foo
Your example actually calls foo...

I rest my case. I've been programming perl professionally since 2000,
and I still make stupid, newbie mistakes like that.
One is simple, consistent, and easy to explain. The other one requires
the introduction of advanced syntax and an entirely new syntax to make
function calls with references.

The syntax follows that of referencing and dereferencing:

$bar = \@array;       # bar contains now a reference to array
$bar->[ 0 ];          # first element of array referenced by bar
$bar = \%hash;        # bar contains now a reference to a hash
$bar->{ key };        # value associated with key of hash ref. by bar
$bar = \&foo;         # bar contains now a reference to a sub
$bar->( 45 );         # call sub ref. by bar with 45 as an argument

Consistent: yes. New syntax? No.

Except for the following symbols and combinations, which are entirely
new and different from the $@% that you have to know just to use
arrays and hashes.

\@, ->[ ]
\%, ->{ }
\&, ->( )

By the way:
* How do you do a hashslice on a hashref?
* How do you invoke reference to a hash that contains a reference to
an array that contains a reference to a function?

Compare with Python's syntax.

# The only way to assign
a = b

# The only way to call a function
b(...)

# The only way to access a hash or array or string or tuple
b[...]
Also, it helps to think of

$ as a thing
@ as thingies indexed by numbers
% as thingies indexed by keys

I'd rather think of the task at hand than what each of the funky
symbols on my keyboard mean.
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,176
Messages
2,570,950
Members
47,503
Latest member
supremedee

Latest Threads

Top