Python 3000 Status Update

Guido updates the vision. Syntax focus seems cancerous, leaving FP sandwiched between set literals and backtick syntax, under Miscellany:

  • reduce() is gone. This doesn't mean I don't like higher-order functions; it simply reflects that almost all code that uses reduce() becomes more readable when rewritten using a plain old for-loop. (Example.)
  • lambda, however, lives.

Guido says that example "gives reduce() a bad name" which leaves me wondering as to its relevance. The idea that FP = Miscellany makes me wonder why the more stunning Python success stories (Google) involve FP techniques. Elsewhere:

  • zip(), map(), filter() return iterables

So FP is not even a free-standing category yet. I sometimes wish PLT Spy would revive, or that some FP language would target Python intermediate code. The value of Python is often stated to be its libraries.

I also wonder if Python people might build intuition by watching REBOL (=Lisp) people at work. They seem to enjoy puzzles. The motivating notion would be "hey! that REBOL trick should be so easy in Python."

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Still, I Choose ...

No multi-line lambdas, so there is little chance I'll use the lambdas, even if they survive.
Python is not functional enough for that lambda to be useful, in that, while it allows me to pass code around, Python wants me to return explicitly. As a result, the core FP concept of all functions returning and enabling a program to be a single complex expression breaks down.

Ruby has no such problem. Just saying.
Alright, neither does Haskell. Or Lisp.

Also, Python doesn't play well with recursion, which is yet another FP thing. (In fact, Python is almost fanatically against recursion.) FP is more than lambda.

Old, old joke: `Even assembly has lambdas!'

explicit returns

In Python, I believe that lambda does return implicitly. Use of 'return' is only required in functions introduced via 'def'. No, I don't think this particularly makes a lot of sense. (This may have been what you meant, but it wasn't quite clear.)

I'm putting together a course at the moment, a sort of "Learning to Program With Python". (No, I didn't get to choose the language.) The course has a functional bias, but I must say that it has been of a trick to do this with Python. It really is not well-suited to FP.

Or to be more specific

A 'def' function will implictly return the value None if there is no return statement. It just doesn't do the 'last expression evaluated is automatically returned' which isn't necessarily inuitive. As the 'zen of python' says, explicit is better than implicit.

And in fact, since it doesn't look like the Zen of Python has been listed here before, maybe this will foster some constructive discussion:

Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit (Intel)]
32
Type "help", "copyright", "credits" or "license" for more information.
>>> import this
The Zen of Python, by Tim Peters

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

neither

Neither is more intuitive than the other. The first time I used Python, I was surprised that I had to explicitly return.

Well debating intuitiveness is a lost cause...

Especially in something like programming languages, but I'll try anyway. ;-) In the simple case, yes neither one beats the other.
let x () =
  1;

def x ():
    return 1
But in the slightly more complex case:
let x () =
  1;
  2;
  3

def x ():
    1
    2
    return 3
Just returning '3' seems someone arbitrary in the caml code.

...

Python is rather cranky about the difference between expressions and statements. Lambda takes an expression (and as a result is not terribly useful). Return converts an expression to a statement (that returns the result of the expression).

I'm putting together a course at the moment, a sort of "Learning to Program With Python". (No, I didn't get to choose the language.) The course has a functional bias, but I must say that it has been of a trick to do this with Python. It really is not well-suited to FP.

If you are teaching a sort of "Learning to Program with Python", wouldn't it be easier to teach Python rather than Scheme impersonated by Python? Swimming upstream, and all that....

reductions in crankiness?

Extending Python to be more FP is interesting to me, as long as it doesn't change any meaning in existing Python code. This post is geared just toward asking if folks know specific restrictions that can be loosened, that don't result in chaos.

(I don't mean to cause trouble. I'll duck exchanges about whether FP is good or not, or whether Python needs less or more of it. I just wonder if Python says "you can't do that" in some cases where nothing bad would happen if it were permitted instead.)

If a backend with more FP support (pervasive TCO for example) was used to implement Python, and care was taken not to change the meaning of existing Python syntax, what additional things might you do in Python like you could in Scheme if a restriction was loosened? Or if a new bit of non-ambiguous syntax was added? (Extending syntax would be a Python variant of course; you'd want compatibility in at least one direction.)

explicit return improves Python's readability

When you're reading a "function" in Python, if it doesn't return a value, you don't have to wonder if someone, somewhere, cares what value it returns. You don't have to wonder whether its callers know it has side effects. And you don't have to wonder whether the method call it happens to have as its last line returns a value you have to care about.

It substantially expands the number of modifications you can make to the program without being afraid of breaking it, without doing a whole-program analysis to understand their effects.

I agree, explicit return is

I agree, explicit return is essential for any dynamically typed language. The E language found this out the hard way, as even relatively simple refactorings caused unintentional information and authority leaks.

Ruby has different problems

Ruby has no such problem. Just saying.

As far as I can tell, Ruby lambdas are not functions but rather code blocks. Being a code block, they have to be .called() as opposed to having normal function application (). Means that functions defined through def and functions defined through lambda are not directly substitutable. In Python, you have to overuse def (named functions). In Ruby, you have to overuse lambda.

[Edit Note: I guess I should add that Ruby shares more in common with Smalltalk code blocks than it does with Scheme lambdas.]

Also, Python doesn't play well with recursion, which is yet another FP thing.

Both Python and Ruby lack TCO.

TCO in ruby 1.9

Luckily, the development version of the ruby interpreter/VM already does taill call elimination.

And yes, ruby's lambda are no substitute for normal methods.
At some point matz was esperimenting with syntax sugar that would allow foo() to mean foo.call() if there is a foo variable in scope, but that introduced some subtle ambiguities, IIRC.

Shouldn't langauge bashing go in the forum or comments?

Not on the homepage?

"Syntax focus seems cancerous, leaving FP sandwiched between set literals and backtick syntax, under Miscellany"

I believe every time a newcomer (or troll) tries to claim that this is an FP site, the community responds that we're interested in all language theory.

Yes

Shouldn't langauge bashing go in the forum or comments?

Not on the homepage?

Yes. And in general, it may not even be appropriate in the forum or comments; see point 6(a) in the policies.

LtU is an FP Site

We can't change the fact that LtU is an FP site. We can't deny it either. We can only be more-accommodating of divergent views better than c.l.l. Okay, that's easy, but ... :o)

Denial

We can't change the fact that LtU is an FP site. We can't deny it either.

I suppose it depends on the definition of "an FP site". This thread had some good comments on this subject, in the linked comment and subsequent comments.

I think the point was

I think the point was intended to be that FP is a semantic issue rather than just a syntactic one - the "cancerous" comment isn't about paradigm, it's about paying attention to surface issues.

To put it another way, it's a complaint about Wadler's Law in action. Which isn't to say that it was necessarily a well-phrased one.

The obvious reference is, of

The obvious reference is, of course, to Perlis's epigram Syntactic sugar causes cancer of the semicolon.

Perhaps Wadler's Law is about people being smart

Wadler seems to be suggesting that people spend a lot of time discussing things that aren't very important. Certainly they aren't the things that he thinks are important.

But maybe syntax and especially comment syntax is really more important than semantics. After all, you (a hacker in general, but especially someone like you, Philippa) can eventually Greenspun any Turing-complete language into something usable. But if other people can't read your program, it will have failed at conveying your ideas to them, and they won't be able to learn from it, fix bugs in it, or modify it to fit their needs.

So maybe the people discussing comment syntax are onto something.

Lambda, lambda, lambda

I remember discussions where LtU was blamed by participants to be an "FP fanclub". Some articles do indeed very little to avoid this impression.

A certain amount of FP bias is probably unavoidable

Most research aimed at the theory of programming languages is based on the lambda calculus - and any meta-discussion of PLs will probably be framed in functional programming terms.

That said, I think the Guido has stated quite explicitly on any number of occasions that the goal of the Python community is not to create a PL that can be classified as an FP language. Given that acknowledgement, the merits of Python 3000 probably should not be judged on the basis of how well it supports a paradigm that it explicitly is not trying to achieve.

Readable code is important to the Python community

"... that REBOL trick should be so easy in Python"

"trick" is just about the opposite of readability.

And making a program be a huge, "single complex expression" almost always makes that program harder to read.

While I understand the

While I understand the points you're trying to make, you're using the wrong language for the audience. Amongst other things, 'trick' can often mean 'well-founded technique I hadn't seen the groundwork for before' - which isn't to say that Python isn't allowed to stick to a carefully chosen set of base concepts, but it can't be assumed that the audience here knows all of Python's stances.

Also, "single complex expression" is... not the simple concept you might think it is. Python has two distinct syntactic categories of 'expression', but there's not necessarily anything particularly special about ; as an operator whether it's explicit or implicit - Python programs are still "single complex expressions", there's just a certain amount of enforced convention to aid readability. There's no reason not to look at exploring other conventions for that purpose, or to make blanket statements that equate functional programming with minimalism of concrete syntax.

Not an FP language

Guido misspoke--reduce isn't going away; it's being demoted to a library feature, so you'll have to "from functools import reduce" if you want it.

I dunno, it seems like I only use folds when I'm writing compilers. And in that case it's always fold-right, so reduce() would be the wrong thing anyway.

Anyway, whether reduce()-- which is, what, a five-line function?-- is provided or not really has **nothing** to do with whether Python is a good FP language. Here are the issues as I see them:

1a. There are statements and expressions in Python, and a lot of things you simply can't do with an expression... really basic things, like (let). Python's syntax, from the ground up, encourages you to use statements, and one statement per line.

1b. The syntax doesn't have any of the features of ML or Haskell that support FP. Such as: functions being curried by default. Or Haskell's "." operator. Or Haskell's cute "(+ 1)" syntax.

(Scheme doesn't have any of these, either, so I always find myself writing little macros to hide the verbosity of the language. I suspect that's not the right way forward. But what do I know.)

2. Python is enthusiastically stateful. Almost everything in the Python standard library involves state or side effects. The coolest thing about Python is its amazingly fun and useful data structures... which are mutable (except tuples).

3. Hard recursion limit of 1000 or so in the Python VM, and no TCO.

Here's the thing, though. These things are the way they are not because Guido doesn't grok FP (though I guess he probably doesn't, not deeply). They are the way they are for principled reasons that the Python folks actually do a pretty good job of explaining if you ask.

Every language imposes its vision on the world. Some of the best languages, like Haskell, are in fact the most restrictive. You can of course still write functional code in Python; it's a lot easier than writing procedural code in Haskell. But why would you?

Indeed.

Python is not trying to be Haskell. Besides, if it is Haskell we want, we know where to find it.
Only that I had to write Python code, after something like one-and-one-half years of straight Ruby (no, not Rails, just scripting) and Haskell + OCaml, and I found that my expectations had changed along with my style. More recursion, an expectation of implicit returns, et al.
So, I'm generally rusting at Python. But ...

Python is becoming a better Python, and I really would have loved to be in the community yet. Python is great, even without being of the paradigm I favour these days.

Becoming better

Python is becoming a better Python

I agree, and I'm glad to see the improvement since I use Python at work. Years back, when Guido first started talking about Python 3000, I was disappointed at how small the changes seemed, but now the update looks like it will have some good stuff. (Maybe even generic functions!)

At risk of descending into

At risk of descending into advocacy, this Haskeller is far from convinced that writing functional code in Python is 'a lot easier than' writing procedural code in Haskell.

Objective

There's no reason to worry about advocacy.

Objectively you can't write functional code in (standard) Python for at least two distinct reasons.

What are they?

All this time I thought I was writing functional code when I wrote higher-order functions with no side effects.

reduce redux

In Python, map and filter can almost always be replaced with comprehensions, often improving readability - especially as a single expression can combine both maps and filters, and in a way that follows conventional mathematical notation and/or natural language reasonably well.

It is more of a challenge to design a syntactic construct to replace a fold (reduce) equally well. For simple cases it can be seen as putting an operator between adjacent items, but I see no obvious way to write it in a way much clearer than a fold with a lambda expression. Does anyone know of a language that handles it in a more elegant way?

The removal of reduce() is not a problem; it is easy to replace, and it was always somewhat oddly designed. Also, I don't think Python ever had a right-to-left fold.

Scala has /: and :\ operators

know of a language that handles it in a more elegant way?

I like the way Scala's library defines /: and :\ operators as semi-synonyms for foldLeft and foldRight respectively.

It does make one suspect, however, that it's only a matter of time before there's a smiley operator in there somewhere.

Perl6 reduce metaoperator?

Perl6 provides operators for almost everything so of course it has something here :)

The prefix "reduce metaoperator" takes an operator and basically just puts it between the arguments, eg:

[+] 1,2,3

IIRC it handles folding to left or right just by relying on the definition of the operator.

Additionally, since perl6 provides chaining operators it also allows stuff like
[>] 1,$x,3
to mean 1 > $x > 3

Oh well...

LtU was never an FP site, nor will it be one, as far as I am concerned (of the ten homepage stories at the moment, at most three can be considered FP, and even these are not particularly about FP languages). Language advocacy is also not welcome on LtU, even if tolerated at times.

There are cases where informed criticism of particular constructs is of interest, and is appreciated. But it has to be informed, and civil.

Finally, individual members are allowed (indeed, encouraged...) to have opinions, and shouldn't be afraid to express them, when appropriate, for fear they might help some outsider claim that LtU is an FP site (or any other silly generalization).

By the way, the LtU policy explicitly says that regular and senior members (as in "senior citizens", not "senior officials") have more leeway than others. This is especially true of contributing editors, of course.


I should also mention that I didn't find Mark's post objectionable, or as praticularly opinionated. And I like Python...

Laundry list

I should also mention that I didn't find Mark's post objectionable, or as praticularly opinionated. And I like Python...

It seemed inexplicably unfair to me. Here's why (quoting from the story):

Syntax focus seems cancerous

This inflammatory remark is neither explained nor supported. The subsequent phrase doesn't seem to relate:

leaving FP sandwiched between set literals and backtick syntax, under Miscellany:

This refers to the ordering of bullet points in a short list of changes, yet it's phrased as though it's somehow a valid criticism. It's not. (See also "FP = Miscellany" below).

* reduce() is gone

This quote of Guido's is the only change that might have supported the story's focus, but Guido's post was apparently later edited to add "(moved to functools, really)". [Edit: ...which only emphasizes the weakness of Mark's remaining points.]

The idea that FP = Miscellany

One FP-related change and one FP-related non-change was listed under "Miscellaneous". That hardly translates into any kind of claim that "FP = Miscellany".

* zip(), map(), filter() return iterables

So FP is not even a free-standing category yet

I don't know what this means, in the context of Python and these functions. Why should FP be a "free-standing category" in Python, and what does that mean? What should these functions return, to achieve that? A bit of explanation would have added some substance to the story.

Finally, individual members are allowed (indeed, encouraged...) to have opinions, and shouldn't be afraid to express them, when appropriate, for fear they might help some outsider claim that LtU is an FP site (or any other silly generalization).

What outsiders think is not particularly important. Expressing the opinion that Python should have a stronger focus on FP is reasonable. But this story went beyond that, into mischaracterization. We should aspire to better than this.

Comments

Ehud has a correct understanding. This post is not much opinionated. Although opinions from experienced persons make LtU valuable. The opinion here should hardly inspire criticism in a language forum: FP featurettes are more important than syntax tweaks, whether a language wants FP or not. But that wasn't even the point.

The issues to discuss are PLT Python, REBOL inspirations, and Python's FP subset, with an eye toward multiparadigm code.

I've used and enjoyed Python for 10 years I suppose. FP is just one aspect of Python. My profile says multiparadigm which is the real happening here. Python is gradually adopting FP featurettes like list comprehensions (fact), but in a too-ad-hoc way (opinion). Python design should assign the FP design segment a proper subcategory (opinion). Even more so if Python wants to avoid FP featurettes - put them in quarantine to avoid infection.

I have no opinion whatever about lambda and reduce in Python. My only opinion is that FP belongs on a higher plane than syntax. Guido has good taste in general. The whole Python community is just too blinkered by syntax (opinion).

PLT Python could show what works and what doesn't at the interaction boundary between FP and Python. The SAGE project might also merit attention insofar as it links Python with Maxima (a Lisp system). Boost Python calling the Boost FP stuff is another configuration. I have won great gains by such dual-language or dual-paradigm development strategies.

Fanboy accusations made me laugh. I have a beef against FP promoters. They often adduce ugly things like folds and recursion. No wonder FP has a reputation for difficulty. What I like about FP is declarative code: to state a problem is to code the solution. If you must think too hard about declaration internals, you may as well code imperatively. However in more than enough FP cases you don't.

I'm not saying this is one of them, but still: Ponder the spectacle of a language which says it does not want FP, achieving its most famous success with FP - Google's MapReduce - and the company then hiring the language designer.

REBOL was mentioned to counterpoint Python's desire for social appeal. Designing a language people want is fine, even commendable. I wish Haskell would do that (attempted comedy). REBOL shows it's possible to win social appeal with FP.

Most REBOL programmers have no idea they are in effect using Scheme/Lisp FP. They just know it works magic. They (and I) see the same zen in it as listed in the Python zen creed. Python will realize the two zens are the same zen, maybe circa Python 5000. In fact Python may reflect the natural speed of mass migration to a new multiparadigm landscape, however slow.

python and MapReduce

I'm not saying this is one of them, but still: Ponder the spectacle of a language which says it does not want FP, achieving its most famous success with FP - Google's MapReduce - and the company then hiring the language designer.

I'm not sure why you suggest that MapReduce is a success for Python. Wikipedia states that Google's MapReduce is implemented in C++ (though it does note that they have Python bindings). MapReduce appears to have little or nothing to do with Python specifically.

REBOL - Scheme/Lisp FP

"Most REBOL programmers have no idea they are in effect using Scheme/Lisp FP. They just know it works magic. They (and I) see the same zen in it as listed in the Python zen creed."

Agreed :)

- REBOL guy