Python and Ruby

8 views
Skip to first unread message

Jean Guillaume Pyraksos

unread,
Jan 27, 2010, 8:01:40 AM1/27/10
to
What are the arguments for choosing Python against Ruby
for introductory programming ? Python has no provisions
for tail recursion, Ruby is going to... So what ?
Thanks,

JG

Stefan Behnel

unread,
Jan 27, 2010, 8:04:41 AM1/27/10
to
Jean Guillaume Pyraksos, 27.01.2010 14:01:

> What are the arguments for choosing Python against Ruby
> for introductory programming ?

PEP 20:

http://www.python.org/dev/peps/pep-0020/

Stefan

Simon Brunning

unread,
Jan 27, 2010, 8:47:25 AM1/27/10
to pytho...@python.org
2010/1/27 Jean Guillaume Pyraksos <wis...@hotmail.com>:

> What are the arguments for choosing Python against Ruby
> for introductory programming ?

Frankly, either would be a good choice.

I think Python is a little cleaner, but I'm sure you'd find Ruby fans
who'd argue the complete opposite. Both have good ecosystems, (i.e.
good communities, and plenty of good libraries and frameworks) - but
Python is probably a bit ahead here having been around a bit longer.

> Python has no provisions
> for tail recursion, Ruby is going to... So what ?

This would be a very strange reason to pick one language over the
other - it's a very minor point.

--
Cheers,
Simon B.

Roald de Vries

unread,
Jan 27, 2010, 9:56:24 AM1/27/10
to pytho...@python.org

I think the main difference is in culture, especially for
*introductory* programming. For example, I have the impression that
Rubyists like to write the same thing in as many ways as possible
(example: rubyquiz.com), Python prefers one obvious way; this
(arguably) makes Ruby more writable and Python more readable.

Jonathan Gardner

unread,
Jan 27, 2010, 6:29:05 PM1/27/10
to
On Jan 27, 5:47 am, Simon Brunning <si...@brunningonline.net> wrote:
>
> I think Python is a little cleaner, but I'm sure you'd find Ruby fans
> who'd argue the complete opposite.
>

Are you sure about that?

There's a lot of line noise in Ruby. How are you supposed to pronounce
"@@"? What about "{|..| ... }"?

There's a lot of "magic" in Ruby as well. For instance, function calls
are made without parentheses. Blocks can only appear as the first
argument. There's a lot more, if you put your mind to it.

Indentation is also optional in Ruby. You can quickly fool a newbie by
not indenting your code properly, which is impossible in Python.

Python is much, much cleaner. I don't know how anyone can honestly say
Ruby is cleaner than Python.

Jonathan Gardner

unread,
Jan 27, 2010, 6:31:18 PM1/27/10
to
On Jan 27, 6:56 am, Roald de Vries <r...@roalddevries.nl> wrote:
> On Jan 27, 2010, at 2:01 PM, Jean Guillaume Pyraksos wrote:
>
> > What are the arguments for choosing Python against Ruby
> > for introductory programming?
>
> I think the main difference is in culture, especially for  
> *introductory* programming.

To add to that, Python is the type of language where experienced
programmers can pick it up by reading code, and newbies won't get
hopelessly lost. I've taught less-than-formal introductory programming
classes to people who are new to programming. Python gets out of the
way, and allows you to focus on the programming concepts, such as
variable, functions, parameters, classes, and algorithms.

Message has been deleted

hackingKK

unread,
Jan 27, 2010, 11:12:22 PM1/27/10
to rantingrick, pytho...@python.org
On Thursday 28 January 2010 08:11 AM, rantingrick wrote:
> On Jan 27, 5:31 pm, Jonathan Gardner<jgard...@jonathangardner.net>

> wrote:
>
>
>> To add to that, Python is the type of language where experienced
>> programmers can pick it up by reading code, and newbies won't get
>> hopelessly lost. I've taught less-than-formal introductory programming
>> classes to people who are new to programming. Python gets out of the
>> way, and allows you to focus on the programming concepts, such as
>> variable, functions, parameters, classes, and algorithms.
>>
> Well said Jonathan!! Well said!! (both posts)
>

I share the same experience.
As pointed out in the "how to think like a computer scientist in Python"
I found that when I was teaching first time programmers, Python was the
best choice.

Not just the clean syntax but preciseness of the language itself was
very helpful.
as I callit "get in get your work done and get out!" methodology works
very well for absolute beginner students for programming.
new comers to this list might be happy to note that python reads very
closely to spoken English.
But I want to add more. while it is great tool for beginners, it is a
power box for advanced users who have the attitude of "cut the crap off
and come to the point" For such programmers python is extremly good,
I teach all types of students and now have convinced a few univercities
here in India to include python in engineering curriculam.


Happy hacking.
Krishnakant.

Nobody

unread,
Jan 30, 2010, 11:43:18 AM1/30/10
to
On Wed, 27 Jan 2010 15:29:05 -0800, Jonathan Gardner wrote:

> There's a lot of "magic" in Ruby as well. For instance, function calls are
> made without parentheses.

That's also true for most functional languages, e.g. Haskell and ML, as
well as e.g. Tcl and most shells. Why require "f(x)" or "(f x)" if "f x"
will suffice?

> Python is much, much cleaner. I don't know how anyone can honestly say
> Ruby is cleaner than Python.

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

tanix

unread,
Jan 30, 2010, 11:58:34 AM1/30/10
to

I'd have to agree. The only ones that beat Python in that department
are Javascript and PHP. Plus CSS and HTML if you can call those languages.

The very idea of using a number of blanks to identify your block level
is as insane as it gets. First of all, combinations of blanks and tabs,
depending on how your ide is setup to expand tabs, may get you bugs,
you'd never imagine in your wild dreams.

Braces is the most reliable way to identify blocks.

Sane compilers ignore blanks altogether.

--
Programmer's Goldmine collections:

http://preciseinfo.org

Tens of thousands of code examples and expert discussions on
C++, MFC, VC, ATL, STL, templates, Java, Python, Javascript, PHP,
organized by major topics of language, tools, methods, techniques.

All collections are fully searchable down to specific chapter.

Ed Keith

unread,
Jan 30, 2010, 12:06:26 PM1/30/10
to pytho...@python.org
--- On Sat, 1/30/10, Nobody <nob...@nowhere.com> wrote:

> From: Nobody <nob...@nowhere.com>
> > Python is much, much cleaner. I don't know how anyone
> can honestly say
> > Ruby is cleaner than Python.
>
> I'm not familiar with Ruby, but most languages are cleaner
> than Python
> once you get beyond the "10-minute introduction" stage.

You need to be clear about what you mean by "clean". Is Python scoping "clean"? I suspect lots of people would argue either side.

-EdK

Ed Keith
e_...@yahoo.com

Blog: edkeith.blogspot.com


Steven D'Aprano

unread,
Jan 30, 2010, 2:16:04 PM1/30/10
to
On Sat, 30 Jan 2010 16:58:34 +0000, tanix wrote:

> In article <pan.2010.01.30....@nowhere.com>, Nobody
> <nob...@nowhere.com> wrote:
>>On Wed, 27 Jan 2010 15:29:05 -0800, Jonathan Gardner wrote:
>>
>>> There's a lot of "magic" in Ruby as well. For instance, function calls
>>> are made without parentheses.
>>
>>That's also true for most functional languages, e.g. Haskell and ML, as
>>well as e.g. Tcl and most shells. Why require "f(x)" or "(f x)" if "f x"
>>will suffice?
>>
>>> Python is much, much cleaner. I don't know how anyone can honestly say
>>> Ruby is cleaner than Python.
>>
>>I'm not familiar with Ruby, but most languages are cleaner than Python
>>once you get beyond the "10-minute introduction" stage.
>
> I'd have to agree. The only ones that beat Python in that department are
> Javascript and PHP. Plus CSS and HTML if you can call those languages.

Your sentence makes no sense. You agree that "most" languages are cleaner
than Python, and then in the very next sentence, out of the hundreds if
not thousands of languages invented, you can only list TWO that are
better than Python -- and those are Javascript and PHP!!!

That's like saying "most things are harder than diamond -- the only
things that beat diamond are jelly and talc".


> 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.


> First of all, combinations of blanks and tabs,
> depending on how your ide is setup to expand tabs, may get you bugs,
> you'd never imagine in your wild dreams.

Not really. The bugs are quite simple, and generally easy to fix. To
describe them as unimaginable is stupid.

>>> for x in [1, 2, 3]:
... print x
... print x+1
File "<stdin>", line 3
print x+1
^
IndentationError: unexpected indent


If you can't imagine getting an IndentationError from making an
indentation error, there's something wrong with you.

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.


> Braces is the most reliable way to identify blocks.

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


> Sane compilers ignore blanks altogether.

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".


--
Steven

Message has been deleted
Message has been deleted

Steven D'Aprano

unread,
Jan 31, 2010, 6:35:10 AM1/31/10
to
On Sun, 31 Jan 2010 03:01:51 -0800, rantingrick wrote:

> On Jan 30, 10:43 am, Nobody <nob...@nowhere.com> wrote:
>
>> That's also true for most functional languages, e.g. Haskell and ML, as
>> well as e.g. Tcl and most shells. Why require "f(x)" or "(f x)" if "f
>> x" will suffice?
>

> 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.

I think the readability factor is mostly down to what you're familiar
with. But consistency is also important: in Python, you always refer to
an object the same way. Given an object called x, you ALWAYS refer to the
object itself as x. In languages that don't use parentheses, x refers to
the object, unless the object is a function, in which case x refers to
the result of calling the object with no arguments.

Other languages need special syntax to get access to the function object
itself. Because it's hard to do, people don't do it often. But in Python,
getting the function object is easy, and so treating functions as first-
class objects is easy.


--
Steven

Ed Keith

unread,
Jan 31, 2010, 7:28:41 AM1/31/10
to pytho...@python.org
--- On Sun, 1/31/10, Steven D'Aprano <st...@REMOVE-THIS-cybersource.com.au> wrote:

In most functional languages you just name a function to access it and you do it ALL the time.

for example, in if you have a function 'f' which takes two parameters to call the function and get the result you use:

f 2 3

If you want the function itself you use:

f

The reason no parentheses are used is to support Currying (http://en.wikipedia.org/wiki/Currying). To get a new function which is equivalent to f with the first parameter set to a constant 2 you use:

f 2

this give you a function which take only one parameter. Using parenthesis make currying more complicated, so most functional languages do not use them. It did take me a LONG time to get used to this, but it is only syntax, I do not let syntax bother me. Semantics on the other hand, are a big deal.

Nobody

unread,
Jan 31, 2010, 3:14:47 PM1/31/10
to
On Sat, 30 Jan 2010 16:58:34 +0000, tanix wrote:

>>I'm not familiar with Ruby, but most languages are cleaner than Python
>>once you get beyond the "10-minute introduction" stage.
>
> I'd have to agree. The only ones that beat Python in that department are
> Javascript and PHP. Plus CSS and HTML if you can call those languages.
>
> The very idea of using a number of blanks to identify your block level is
> as insane as it gets.

I don't have a problem with layout (indentation level as a syntax element).

> First of all, combinations of blanks and tabs,
> depending on how your ide is setup to expand tabs, may get you bugs, you'd
> never imagine in your wild dreams.

If you IDE places tab stops other than every 8 columns, it's broken.

Configurable tab stops in a text editor is one of those "features" that
differentiates a "coder" from a software engineer. A coder implements it
because it's easy to implement, without giving a moment's thought to the
wider context (such as: how to communicate the non-standard tab stops to
any other program which needs to read the file).

Even so, it's quite simple to implement layout in a way which doesn't
care about tab widths:

1. If the current line begins with exactly the same sequence of whitespace
characters as the last non-blank line, it's part of the same block.

2. If the sequence of whitespace characters at the beginning of the
current line is an extension of that for the last non-blank line
(i.e. it starts with the previous sequence, then adds some more
whitespace), then it's the first line of a inner block.

3. If the current line begins with a left substring of the sequence for
the last non-blank line, then it belongs to an outer block (whichever one
has that sequence).

4. If none of the above are true, it's a syntax error.

> Braces is the most reliable way to identify blocks.

No they aren't. Indentation is much easier for humans to process than
scanning the file for braces (and not missing any). If you have any
indentation in the code, humans will interpret it as indicating the
nesting, even if the compiler doesn't. E.g.:

if(x) {
if(y)
foo();
else
bar();
}

See the problem? The compiler will match the else with if(y), but a human
will tend to match it with if(x).

Layout ensures that a human sees what the compiler "sees".

Given that any sane program uses indentation to reflect the program's
structure, braces (or "begin", or "end" (or endif/endwhile/etc)) are
redundant.

Nobody

unread,
Jan 31, 2010, 3:43:03 PM1/31/10
to
On Sun, 31 Jan 2010 03:01:51 -0800, rantingrick wrote:

>> That's also true for most functional languages, e.g. Haskell and ML, as
>> well as e.g. Tcl and most shells. Why require "f(x)" or "(f x)" if "f x"
>> will suffice?
>

> 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.

Note: Functional languages allow:

f (a,b,c)

but that means something else, i.e. calling a function with a tuple as its
argument (in functional languages, a function always has exactly one
argument).

The syntax:

f a b c

is equivalent to the Python expression:

f(a)(b)(c)

i.e. each argument is applied in turn, with all applications except the
last yielding a function.

Defining f as:

f a b c = <expression>

is shorthand for:

f = \a -> (\b -> (\c -> <expression>))

or, in Python syntax:

f = lambda a: (lambda b: (lambda c: <expression>))

This style (known as Currying, or a Curried function, after the
mathematician Haskell Curry) is common in functional languages, as it
allows you to partially apply functions, e.g.:

map (f a b) someList

whereas an uncurried function would require a lambda expression:

map (\c -> f (a,b,c)) someList

IOW, while the uncurried form is allowed, it has no advantages and one
disadvantage, so it's seldom used (and where it is used, it's normally
a case of a function whose sole argument is a naturally-occurring tuple,
rather than one which is constructed simply to satisfy the mechanics of
a function call).

Partial application is common enough that Haskell supports it for infix
operators as well, e.g.

map (/ 2) someList -- (/ 2) => \x -> x / 2, i.e. halve
map (1 /) someList -- (1 /) => \x -> 1 / x, i.e. reciprocal

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.

John Bokma

unread,
Jan 31, 2010, 3:47:08 PM1/31/10
to
Nobody <nob...@nowhere.com> writes:

> Configurable tab stops in a text editor is one of those "features" that
> differentiates a "coder" from a software engineer. A coder implements it
> because it's easy to implement, without giving a moment's thought to the
> wider context (such as: how to communicate the non-standard tab stops to
> any other program which needs to read the file).

[..]

> if(x) {
> if(y)
> foo();
> else
> bar();
> }
>
> See the problem?

Nope, because a good editor will format this correctly. One written by
software engineers ;-)

> Given that any sane program uses indentation to reflect the program's
> structure, braces (or "begin", or "end" (or endif/endwhile/etc)) are
> redundant.

An editor can correct the indenting of the braces example but can't with
this one.

if x:
if y:
foo()
else:
bar()

While braces might be considered redundant they are not when for one
reason or another formatting is lost or done incorrectly.

FWIW: I have no problem with how Python doesn't use braces nor on how
other languages do insist on braces or other structure markers.

--
John Bokma j3b

Hacking & Hiking in Mexico - http://johnbokma.com/
http://castleamber.com/ - Perl & Python Development

Steven D'Aprano

unread,
Jan 31, 2010, 5:36:32 PM1/31/10
to
On Sun, 31 Jan 2010 04:28:41 -0800, Ed Keith wrote:

> In most functional languages you just name a function to access it and
> you do it ALL the time.
>
> for example, in if you have a function 'f' which takes two parameters to
> call the function and get the result you use:
>
> f 2 3
>
> If you want the function itself you use:
>
> f

How do you call a function of no arguments?

--
Steven

Steven D'Aprano

unread,
Jan 31, 2010, 5:37:25 PM1/31/10
to
On Sun, 31 Jan 2010 14:47:08 -0600, John Bokma wrote:

> An editor can correct the indenting of the braces example but can't with
> this one.
>
> if x:
> if y:
> foo()
> else:
> bar()
>
> While braces might be considered redundant they are not when for one
> reason or another formatting is lost or done incorrectly.

I've heard this argument before, and I don't buy it. Why should we expect
the editor to correct malformed code?

Would you expect your editor to correct this malformed code?

result = sin(x+)y

Why should broken indentation be held to a higher standard than any other
breakage in code?

--
Steven

Chris Rebert

unread,
Jan 31, 2010, 6:40:36 PM1/31/10
to Steven D'Aprano, pytho...@python.org

It's not really a function in that case, it's just a named constant.
(Recall that functions don't/can't have side-effects.)

Cheers,
Chris
--
http://blog.rebertia.com

Arnaud Delobelle

unread,
Jan 31, 2010, 7:14:52 PM1/31/10
to

In a functional language, a function of no arguments will always return
the same value. So, from a non-functional point of vue, f is both the
function and its value.

--
Arnaud

Steven D'Aprano

unread,
Jan 31, 2010, 7:25:44 PM1/31/10
to


>>> time.time(), random.random()
(1264983502.7505889, 0.29974255140479633)
>>> time.time(), random.random()
(1264983505.9283719, 0.74207867411026329)


They don't look terribly constant to me.


There is a difference between a function that does "give me whatever
value is specified by a fixed description" and a function that does "give
me a fixed value".

--
Steven

Ed Keith

unread,
Jan 31, 2010, 7:27:09 PM1/31/10
to pytho...@python.org
--- On Sun, 1/31/10, Steven D'Aprano <st...@REMOVE-THIS-cybersource.com.au> wrote:

> From: Steven D'Aprano <st...@REMOVE-THIS-cybersource.com.au>
> Subject: Re: Python and Ruby
> To: pytho...@python.org

In a 'pure' functional language a function with no arguments is, by definition, a constant. This is because a 'pure' function will always return the same result whenever given the same arguments. so if it has no argument it always returns a constant value.

John Bokma

unread,
Jan 31, 2010, 7:47:42 PM1/31/10
to
Steven D'Aprano <st...@REMOVE-THIS-cybersource.com.au> writes:

> On Sun, 31 Jan 2010 14:47:08 -0600, John Bokma wrote:
>
>> An editor can correct the indenting of the braces example but can't with
>> this one.
>>
>> if x:
>> if y:
>> foo()
>> else:
>> bar()
>>
>> While braces might be considered redundant they are not when for one
>> reason or another formatting is lost or done incorrectly.
>
> I've heard this argument before, and I don't buy it. Why should we expect
> the editor to correct malformed code?

Or a prettyfier. It doesn't matter. The point is that with braces there
*is* redundancy that be used to fix the code.

> Would you expect your editor to correct this malformed code?
>
> result = sin(x+)y

Nice straw man.

Let me repeat again: I am ok with how Python works. To be honest I think
it's cleaner compared to using {}. But in there are real life examples
in which Python code will break where code with braces will survive.

Chris Rebert

unread,
Jan 31, 2010, 7:50:50 PM1/31/10
to Steven D'Aprano, pytho...@python.org
On Sun, Jan 31, 2010 at 4:25 PM, Steven D'Aprano
<ste...@remove.this.cybersource.com.au> wrote:
> On Sun, 31 Jan 2010 15:40:36 -0800, Chris Rebert wrote:
>> On Sun, Jan 31, 2010 at 2:36 PM, Steven D'Aprano
>> <st...@remove-this-cybersource.com.au> wrote:
>>> On Sun, 31 Jan 2010 04:28:41 -0800, Ed Keith wrote:
>>>> In most functional languages you just name a function to access it and
>>>> you do it ALL the time.
>>>>
>>>> for example, in if you have a function 'f' which takes two parameters
>>>> to call the function and get the result you use:
>>>>
>>>>  f 2 3
>>>>
>>>> If you want the function itself you use:
>>>>
>>>>    f
>>>
>>> How do you call a function of no arguments?
>>
>> It's not really a function in that case, it's just a named constant.
>> (Recall that functions don't/can't have side-effects.)
>
>
>>>> time.time(), random.random()
> (1264983502.7505889, 0.29974255140479633)
>>>> time.time(), random.random()
> (1264983505.9283719, 0.74207867411026329)
>
>
> They don't look terribly constant to me.

Those aren't functions in the pure functional programming sense; which
is unsurprising since Python isn't a [pure] functional language.
They both involve side-effects. time() does I/O to the clock chip to
see what time it is, and random() uses and changes a global seed value
variable (which, in a double-whammy, takes its initial value from
time()).

Pure functions must be referentially transparent
[http://en.wikipedia.org/wiki/Referential_transparency_(computer_science)],
and as you've demonstrated, neither of those Python functions qualify.

John Bokma

unread,
Jan 31, 2010, 7:53:16 PM1/31/10
to
Steven D'Aprano <st...@REMOVE-THIS-cybersource.com.au> writes:

> On Sun, 31 Jan 2010 14:47:08 -0600, John Bokma wrote:
>
>> An editor can correct the indenting of the braces example but can't with
>> this one.
>>
>> if x:
>> if y:
>> foo()
>> else:
>> bar()
>>
>> While braces might be considered redundant they are not when for one
>> reason or another formatting is lost or done incorrectly.
>
> I've heard this argument before, and I don't buy it. Why should we expect
> the editor to correct malformed code?

I do expect my editor to assist me in coding. In Emacs I have to do some
effort to enter the broken C code in the earlier post, and when I
reformat the code, it will be lined out correctly. I can't do that with
the above example, because it's correctly formatted.

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

While in the past I wrote that an editor can't make you that more
productive I want to take that back, on the record. Since I've switched
to Emacs the editor has saved me several times from minor issues. Either
because it refused to indent correctly thanks to a missing closing }, ), ]
or other error. With the correct mode in Emacs one gets, in my
experience, immediate feedback when making mistakes one otherwise find
during the run/compiling phase.

Note that I am also not selling Emacs. It's free after all.

Steven D'Aprano

unread,
Jan 31, 2010, 8:22:23 PM1/31/10
to
On Sun, 31 Jan 2010 16:50:50 -0800, Chris Rebert wrote:

>>>> How do you call a function of no arguments?
>>>
>>> It's not really a function in that case, it's just a named constant.
>>> (Recall that functions don't/can't have side-effects.)
>>
>>
>>>>> time.time(), random.random()
>> (1264983502.7505889, 0.29974255140479633)
>>>>> time.time(), random.random()
>> (1264983505.9283719, 0.74207867411026329)
>>
>>
>> They don't look terribly constant to me.
>
> Those aren't functions in the pure functional programming sense; which
> is unsurprising since Python isn't a [pure] functional language. They
> both involve side-effects. time() does I/O to the clock chip to see what
> time it is, and random() uses and changes a global seed value variable
> (which, in a double-whammy, takes its initial value from time()).

Yes, but these tasks -- get the time, get a (pseudo) random number -- are
not unique to Python. Surely even Lisp and Haskell code will sometimes
need to know the time. Whether they are "pure functions" (functions in
the mathematical sense) or impure, they're still functions in some sense.
How do you deal with such impure functions?

--
Steven

Ed Keith

unread,
Jan 31, 2010, 8:31:05 PM1/31/10
to pytho...@python.org, Steven D'Aprano
--- On Sun, 1/31/10, Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> wrote:

> From: Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au>
> Subject: Re: Python and Ruby
> To: pytho...@python.org

You pass it a monad (http://en.wikipedia.org/wiki/Monad_(functional_programming)).

Steven D'Aprano

unread,
Jan 31, 2010, 8:33:26 PM1/31/10
to
On Sun, 31 Jan 2010 18:47:42 -0600, John Bokma wrote:

> Steven D'Aprano <st...@REMOVE-THIS-cybersource.com.au> writes:
>
>> On Sun, 31 Jan 2010 14:47:08 -0600, John Bokma wrote:
>>
>>> An editor can correct the indenting of the braces example but can't
>>> with this one.
>>>
>>> if x:
>>> if y:
>>> foo()
>>> else:
>>> bar()
>>>
>>> While braces might be considered redundant they are not when for one
>>> reason or another formatting is lost or done incorrectly.
>>
>> I've heard this argument before, and I don't buy it. Why should we
>> expect the editor to correct malformed code?
>
> Or a prettyfier. It doesn't matter. The point is that with braces there
> *is* redundancy that be used to fix the code.

Prettyfiers are significant in languages that allow braces (or begin/end
tokens) and indentation to go out of sync. Since that can't happen with
Python, it's not a problem that needs solving. Prettyfiers exist to work
around a limitation of languages where indentation is not significant.

Arguing that an advantage of braces is that prettyfiers can work with
them easily is a silly argument. That's like saying an advantage of horse-
drawn buggies over cars is that it will go faster when you hit the horse
with a whip. That's true, but you only need the whip because of the lack
of accelerator pedal.

A much better argument would be that an advantage of significant
indentation is that you no longer need a prettyfier, and a second
advantage is a major reduction in flame wars over coding styles.

>> Would you expect your editor to correct this malformed code?
>>
>> result = sin(x+)y
>
> Nice straw man.


It's not a straw man. It's a serious argument. There is an infinite
number of problems with malformed code that your editor can't fix, and
your prettifier can't deal with. Why should we care if indentation is one
more?

There are tools out there (such as some web forum software) that corrupt
whitespace. Those tools are broken, and if you (generic you), as a
developer, are relying on those tools to code with, then shame on you.
And if you're the creator of such broken tools, then shame on you more.
You wouldn't arbitrarily decide to remove leading "E"s from the user's
text, or trailing full stops, so why do you arbitrarily remove whitespace?

> Let me repeat again: I am ok with how Python works. To be honest I think
> it's cleaner compared to using {}. But in there are real life examples
> in which Python code will break where code with braces will survive.

Yes. So what? They are rare and insignificant in practice. For every line
of code that you get via a webforum that mangles indentation, you get ten
thousand lines of code from some place that doesn't.

So long as code is written by and for human beings, the benefit of
significant indentation is 100% practical, and the practical benefit of
braces will remain insignificant.

--
Steven

Chris Rebert

unread,
Jan 31, 2010, 8:33:51 PM1/31/10
to Steven D'Aprano, pytho...@python.org

Make the state explicit, i.e. monads or uniqueness typing.
In the case of random(), you have it take the seed explicitly as an
argument and have it return a new seed along with the "randomly"
generated number.
In the case of time(), you pass around an argument to represent the
state of the outside world. I don't quite grok monads, but
http://en.wikipedia.org/wiki/Uniqueness_type has a decent example of
the general uniqueness type approach.

John Bokma

unread,
Jan 31, 2010, 10:30:15 PM1/31/10
to
Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> writes:

> On Sun, 31 Jan 2010 18:47:42 -0600, John Bokma wrote:
>
>> Steven D'Aprano <st...@REMOVE-THIS-cybersource.com.au> writes:
>>
>>> On Sun, 31 Jan 2010 14:47:08 -0600, John Bokma wrote:
>>>
>>>> An editor can correct the indenting of the braces example but can't
>>>> with this one.
>>>>
>>>> if x:
>>>> if y:
>>>> foo()
>>>> else:
>>>> bar()
>>>>
>>>> While braces might be considered redundant they are not when for one
>>>> reason or another formatting is lost or done incorrectly.
>>>
>>> I've heard this argument before, and I don't buy it. Why should we
>>> expect the editor to correct malformed code?
>>
>> Or a prettyfier. It doesn't matter. The point is that with braces there
>> *is* redundancy that be used to fix the code.
>
> Prettyfiers are significant in languages that allow braces (or begin/end
> tokens) and indentation to go out of sync. Since that can't happen with
> Python,

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. It happens, and if you're learning Python and
interested in that code you have a problem.

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

Terry Reedy

unread,
Jan 31, 2010, 10:48:33 PM1/31/10
to pytho...@python.org
On 1/31/2010 7:25 PM, Steven D'Aprano wrote:
> On Sun, 31 Jan 2010 15:40:36 -0800, Chris Rebert wrote:
>
>> On Sun, Jan 31, 2010 at 2:36 PM, Steven D'Aprano
>> <st...@remove-this-cybersource.com.au> wrote:
>>> On Sun, 31 Jan 2010 04:28:41 -0800, Ed Keith wrote:
>>>> In most functional languages you just name a function to access it and
>>>> you do it ALL the time.
>>>>
>>>> for example, in if you have a function 'f' which takes two parameters
>>>> to call the function and get the result you use:
>>>>
>>>> f 2 3
>>>>
>>>> If you want the function itself you use:
>>>>
>>>> f
>>>
>>> How do you call a function of no arguments?
>>
>> It's not really a function in that case, it's just a named constant.
>> (Recall that functions don't/can't have side-effects.)

Three of you gave essentially identical answers, but I still do not see
how given something like

def f(): return 1

I differentiate between 'function object at address xxx' and 'int 1'
objects.

>>>> time.time(), random.random()
> (1264983502.7505889, 0.29974255140479633)
>>>> time.time(), random.random()
> (1264983505.9283719, 0.74207867411026329)
>
> They don't look terribly constant to me.

I believe these are not functions in a functional language sense.
Neither are input and output 'functions'. So all of these are either
missing or some sort of special function-like something.

I personally take a broader view of functions and include the relevant
environment in their input and output, so that there are no 'side
effects'. The concept of 'side-effect' is somewhat arbitrary. In fields
other than computing, like pharmacology and politics, its meaning is
somewhat different and a bit corrupt.

> There is a difference between a function that does "give me whatever
> value is specified by a fixed description" and a function that does "give
> me a fixed value".

Terry Jan Reedy

Paul Rubin

unread,
Jan 31, 2010, 11:22:36 PM1/31/10
to
Terry Reedy <tjr...@udel.edu> writes:
> Three of you gave essentially identical answers, but I still do not
> see how given something like
>
> def f(): return 1
>
> I differentiate between 'function object at address xxx' and 'int 1'
> objects.

In the languages they are talking about, there is no such thing as a
function with no args. A function is closer to a mathematical function,
i.e. a mapping from one type to another, so every function has an arg.
Haskell and ML do have a "Unit" type, written "()", which is something
like Python's "None". So in Haskell you could write

f () = 1

which means the function f, applied to the Unit value (), results in the
value 1. The parens are not function-calling syntax. () is simply a
value. For example, you could say

y = ()
z = f y

which would mean that z = 1.

Steven D'Aprano

unread,
Feb 1, 2010, 1:05:17 AM2/1/10
to
On Sun, 31 Jan 2010 20:22:36 -0800, Paul Rubin wrote:

> Terry Reedy <tjr...@udel.edu> writes:
>> Three of you gave essentially identical answers, but I still do not see
>> how given something like
>>
>> def f(): return 1
>>
>> I differentiate between 'function object at address xxx' and 'int 1'
>> objects.
>
> In the languages they are talking about, there is no such thing as a
> function with no args. A function is closer to a mathematical function,
> i.e. a mapping from one type to another, so every function has an arg.

Suppose I have a function that queries a website http://guessmyname.com
for a list of popular names and returns the most popular name on the
list. Obviously this name will change from time to time, so I can't just
get it once and treat the result as a constant.

In a non-functional language, I'd write it something like this:


def get_popular_name():
URL = 'http://guessmyname.com'
data = fetch(URL)
names = parse(data)
name = choose(names, 1)
return name

name = get_popular_name() # call the function with no argument
f = decorate(get_popular_name) # treat the function as a 1st class object


How would Haskell coders write it? Something like this?


def get_popular_name(url):
data = fetch url
names = parse data
name = choose name 1
return name

name = get_popular_name 'http://guessmyname.com' # call the function
f = decorate get_popular_name # treat the function as a 1st class object


But now you're needlessly having the caller, rather than the function,
remember an implementation detail of the get_popular_name function. Since
the argument couldn't be anything different, I'd immediately think of
applying partial:

get_popular_name = partial get_popular_name 'http://guessmyname.com'

but now how do I call the new function?

Is this where you say "Monads" and everyone's eyes glaze over?


--
Steven

Steven D'Aprano

unread,
Feb 1, 2010, 1:17:21 AM2/1/10
to
On Sun, 31 Jan 2010 18:53:16 -0600, John Bokma wrote:

> 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.


--
Steven

Paul Rubin

unread,
Feb 1, 2010, 1:22:14 AM2/1/10
to
Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> writes:
> How would Haskell coders write it? Something like this?
>
> def get_popular_name(url):
> data = fetch url
> names = parse data
> name = choose name 1
> return name

The syntax and types would be different, but ok, something like that.

> name = get_popular_name 'http://guessmyname.com' # call the function
> f = decorate get_popular_name # treat the function as a 1st class object

You wouldn't need "decorate". You'd just say

f = get_popular_name "http://guessmyname.com"

f is now an "I/O action" which when executed queries the guessmyname site.

> but now how do I call the new function?
> Is this where you say "Monads" and everyone's eyes glaze over?

You'd say something like

most_popular_name <- f

to invoke the action. Yes, explaining the difference between
"<-" and "=" involves monads.

You might like the Haskell tutorial http://learnyouahaskell.com .

Steven D'Aprano

unread,
Feb 1, 2010, 1:27:29 AM2/1/10
to
On Sun, 31 Jan 2010 21:30:15 -0600, John Bokma wrote:

>>>>> While braces might be considered redundant they are not when for one
>>>>> reason or another formatting is lost or done incorrectly.
>>>>
>>>> I've heard this argument before, and I don't buy it. Why should we
>>>> expect the editor to correct malformed code?
>>>
>>> Or a prettyfier. It doesn't matter. The point is that with braces
>>> there *is* redundancy that be used to fix the code.
>>
>> Prettyfiers are significant in languages that allow braces (or
>> begin/end tokens) and indentation to go out of sync. Since that can't
>> happen with Python,
>
> 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.

--
Steven

alex23

unread,
Feb 1, 2010, 1:43:56 AM2/1/10
to
Steven D'Aprano <ste...@REMOVE.THIS.cybersource.com.au> wrote:
> 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... ;)

Chris Rebert

unread,
Feb 1, 2010, 1:49:13 AM2/1/10
to Steven D'Aprano, pytho...@python.org
<snip>

> Is this where you say "Monads" and everyone's eyes glaze over?

Yeah, basically. Your function has side-effects (i.e. it does I/O over
the network), and thus some extra hoops need to be jumped through to
reconcile that with the functional purity of the language. Assuming my
understanding of monads is somewhat correct:

get_popular_name would have the type: IO () -> IO String
i.e. it takes no "real" parameters but does I/O, and returns a String.
"IO" is a generic type, thus IO () is like IO<void>, and IO String is
IO<String> (using Java/C#-like generics syntax).
Wrapping things in IOs (the "IO monad") is how the type system models
that I/O side effects are involved.
So, get_popular_name would end up taking one argument, IO (). Now
where does the caller get an IO () ? Well, the toplevel (i.e. the main
function) is allowed to do IO (otherwise, we couldn't write very
interesting programs), and thus is provided with an IO by the
environment (through some sort of magic). Using this, it passes an IO
() to get_popular_name (or it gets passed down the call stack and
eventually winds up at get_popular_name) and we get back an IO String.
And through some further monad trickery, we make sure that lazy
evaluation is effectively bypassed for the I/O and we are able to rip
the String out of its IO container and pass it to pure functions. And
using the dark magic of "do-notation", we write the parts involving IO
in pseudo-imperative style (the "<-" operator Paul mentioned is part
of that). And there you have it (I think/hope).

Supposedly, in practice, you don't need to know the monad guts of how
the I/O system works in order to use it, you just need to be able to
write do-notation.

Cheers,
Chris
--
I really should read the monad chapters of my copy of "Real World Haskell".
http://blog.rebertia.com

Steven D'Aprano

unread,
Feb 1, 2010, 2:12:51 AM2/1/10
to

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


--
Steven

Paul Rubin

unread,
Feb 1, 2010, 2:24:06 AM2/1/10
to
Chris Rebert <cl...@rebertia.com> writes:
> get_popular_name would have the type: IO () -> IO String

I don't know if it makes the explanation any clearer, but I think that
isn't quite right. The Python version would have type
String -> IO String. The parameterless Haskell version would just be an
I/O action, with type IO String. IO () is not really involved.

Steve Holden

unread,
Feb 1, 2010, 7:55:28 AM2/1/10
to pytho...@python.org
Yeah, what did the zealots ever do for us?

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
PyCon is coming! Atlanta, Feb 2010 http://us.pycon.org/
Holden Web LLC http://www.holdenweb.com/
UPCOMING EVENTS: http://holdenweb.eventbrite.com/

Steve Holden

unread,
Feb 1, 2010, 7:57:16 AM2/1/10
to pytho...@python.org
Terry Reedy wrote:

> On 1/31/2010 7:25 PM, Steven D'Aprano wrote:
>> On Sun, 31 Jan 2010 15:40:36 -0800, Chris Rebert wrote:
>>
>>> On Sun, Jan 31, 2010 at 2:36 PM, Steven D'Aprano
>>> <st...@remove-this-cybersource.com.au> wrote:
>>>> On Sun, 31 Jan 2010 04:28:41 -0800, Ed Keith wrote:
>>>>> In most functional languages you just name a function to access it and
>>>>> you do it ALL the time.
>>>>>
>>>>> for example, in if you have a function 'f' which takes two parameters
>>>>> to call the function and get the result you use:
>>>>>
>>>>> f 2 3
>>>>>
>>>>> If you want the function itself you use:
>>>>>
>>>>> f
>>>>
>>>> How do you call a function of no arguments?
>>>
>>> It's not really a function in that case, it's just a named constant.
>>> (Recall that functions don't/can't have side-effects.)
>
> Three of you gave essentially identical answers, but I still do not see
> how given something like
>
> def f(): return 1
>
> I differentiate between 'function object at address xxx' and 'int 1'
> objects.
>
But in a functional environment you don't need to. That's pretty much
the whole point.

Jonathan Gardner

unread,
Feb 1, 2010, 5:13:38 PM2/1/10
to
On Jan 30, 8:43 am, Nobody <nob...@nowhere.com> wrote:
> On Wed, 27 Jan 2010 15:29:05 -0800, Jonathan Gardner wrote:
> > Python is much, much cleaner. I don't know how anyone can honestly say
> > Ruby is cleaner than Python.
>
> 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.

Jonathan Gardner

unread,
Feb 1, 2010, 5:28:28 PM2/1/10
to
On Jan 31, 3:01 am, rantingrick <rantingr...@gmail.com> wrote:
> On Jan 30, 10:43 am, Nobody <nob...@nowhere.com> wrote:
>
> > That's also true for most functional languages, e.g. Haskell and ML, as
> > well as e.g. Tcl and most shells. Why require "f(x)" or "(f x)" if "f x"
> > will suffice?
>
> 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.

Jonathan Gardner

unread,
Feb 1, 2010, 5:35:57 PM2/1/10
to
On Jan 31, 12:43 pm, Nobody <nob...@nowhere.com> wrote:
>
> 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.

Chris Rebert

unread,
Feb 1, 2010, 6:07:03 PM2/1/10
to Jonathan Gardner, pytho...@python.org

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

Paul Rubin

unread,
Feb 1, 2010, 6:08:48 PM2/1/10
to
Jonathan Gardner <jgar...@jonathangardner.net> writes:
> 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.

Nobody

unread,
Feb 1, 2010, 9:03:18 PM2/1/10
to
On Sun, 31 Jan 2010 22:36:32 +0000, Steven D'Aprano wrote:

>> for example, in if you have a function 'f' which takes two parameters to
>> call the function and get the result you use:
>>
>> f 2 3
>>
>> If you want the function itself you use:
>>
>> f
>
> How do you call a function of no arguments?

There's no such thing. All functions take one argument and return a value.

As functions don't have side-effects, there is seldom much point in having
a function with no arguments or which doesn't return a value. In cases
where it is useful (i.e. a value must have function type), you can use the
unit type "()" (essentially a zero-element tuple), e.g.:

f () = 1
or:
f x = ()

MRAB

unread,
Feb 1, 2010, 9:14:03 PM2/1/10
to pytho...@python.org
A function with no arguments could be used as a lazy constant, generated
only on demand.

Chris Rebert

unread,
Feb 1, 2010, 9:17:04 PM2/1/10
to MRAB, pytho...@python.org
> A function with no arguments could be used as a lazy constant, generated
> only on demand.

The usefulness of that depends on a language's evaluation strategy.
Haskell, for instance, uses lazy evaluation by default, so your use
case doesn't apply in that instance.

Nobody

unread,
Feb 1, 2010, 9:21:55 PM2/1/10
to
On Mon, 01 Feb 2010 14:35:57 -0800, Jonathan Gardner wrote:

>> 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.

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).

John Bokma

unread,
Feb 1, 2010, 9:36:44 PM2/1/10
to
Jonathan Gardner <jgar...@jonathangardner.net> writes:

> 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

Nobody

unread,
Feb 1, 2010, 9:50:55 PM2/1/10
to
On Mon, 01 Feb 2010 14:13:38 -0800, Jonathan Gardner wrote:

> 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.


John Bokma

unread,
Feb 1, 2010, 9:56:34 PM2/1/10
to
Nobody <nob...@nowhere.com> writes:

> On Mon, 01 Feb 2010 14:35:57 -0800, Jonathan Gardner wrote:
>
>>> 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.
>
> 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.

Paul Rubin

unread,
Feb 2, 2010, 3:18:45 AM2/2/10
to
Nobody <nob...@nowhere.com> writes:
> 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

waku

unread,
Feb 2, 2010, 5:21:02 AM2/2/10
to
Steven D'Aprano wrote:
> On Sat, 30 Jan 2010 16:58:34 +0000, tanix wrote:

[...]

> > 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.


>
>
> > Braces is the most reliable way to identify blocks.
>
> 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.

>
>
> > Sane compilers ignore blanks altogether.
>
> 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

bartc

unread,
Feb 2, 2010, 10:23:37 AM2/2/10
to
Jonathan Gardner wrote:

> 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.


--
Bartc


Jonathan Gardner

unread,
Feb 2, 2010, 4:49:39 PM2/2/10
to
On Feb 2, 2:21 am, waku <w...@idi.ntnu.no> wrote:
>
> 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.

Jonathan Gardner

unread,
Feb 2, 2010, 4:55:09 PM2/2/10
to
On Feb 1, 6:21 pm, Nobody <nob...@nowhere.com> wrote:
>
> 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.