Well said and entirely correct with respect to my intentions to maintain a respectful relationship. Upon re-reading, it's all too clear that my original post was indeed inflammatory, wholly speculative, and baseless. For that reason, I have deleted it and let the apologies stand.
I will make every effort to observe actual similar events in the future, do my best to freeze the state of the system, engage in collaborative diagnostics in a constructive fashion, and resist the temptation to offer random, emotive guesses as to what happened. I greatly appreciate your patience and do humbly apologize.
Once again, I need to break this down into chunks:
Paul Prescod @ 05/22/2002 10:07 AM. Python is not designed to be an innovative language. It is designed to be a productive language. That means that what you get over Lisp is syntactic sugar but productive sugar, extensive libraries, excellent integration into environments like the JVM, COM, Unix, etc. and a large community. What you lose is basically macros.
This seems like a fair characterization to me. I actually do think that Scheme does just as well on the platform integration/library front these days. It just doesn't have the visible number of adherents (and consequently, the amount of highly-visible code) that Python does.
I don't think that's a good analogy. Standard ML is an aggressively strongly typed language. It is almost the polar opposite of Python.
But it does type inference in all cases except those in which the type of an expression is ambiguous. ML programmers very rarely declare the type of anything. So from the programmer's POV it might as well be "weakly typed" (I much prefer the term "latently typed"). ML's insistence, though, on strong typing has strongly desirable properties both with respect to provability of program properties and efficient compilation on stock hardware.
If you want to learn new languages to broaden your horizons then those are better choices. If you are trying to get work done and ship software then I would say that Python has a better record than any of those. Where is Haskell's Zope or Mailman?
I don't buy that the two are mutually exclusive. Even if I did, I'd be arguing Java vs. Python in that case. Commercial success (or open-source success, for that matter) has as much, if not more, to do with bandwagon effect as with anything else. Again, that's fine—a valid argument for what's explicitly intended to be a team endeavor (and I hasten to point out that Seppuku, my own open source project, is attempting to limp along in C++ for that reason). But one of the things I like about being interested in programming apart from my day job is precisely that I get to think about better ways to work vs. more popular ways to work.
That's a fair comment. But bear in mind the scope of the problem. There are a short list of these functions that you just memorize.
But the advantage to doing it the Python way is that things that have almost universal applicability are functions so that the methods on an object represent the things that are unique to that object. You don't introspect an object and see all kinds of inherited junk like "hashcode" and "id" and "issubclass" on the object.
This seems like a double-edged sword to me: it demands an extremely high level of generality of the global functions, since they now have to be polymorphic with respect to literally everything in the language. And your list of things you don't find objects "cluttered" with is precisely the stuff that you need to make object introspection tenable in the first place. Granted that Java screwed it up by having primitive types and therefore not being uniformly object-oriented, those methods could be functions, and arguably should be if doing so would allow them to treat the primitive types as well. Smalltalk, of course, avoided that error.
Well, if you really don't care about libraries, size of community, static versus dynamic typing, integration with other technologies, ability to recruit other programmers, (arguably) readability, and availability of ports then I agree, those choices are all as good as or better than Python!
I care about all of those things a great deal! The only one that I think I consistently care less about than others do wrt personal projects is size of community. And frankly, my experience with Seppuku has been that the size of the C++ community hasn't been a benefit. At all. So there are other issues, and almost all of them outweigh language choice in practice.
Every language makes tradeoffs and Python was designed to be easy to learn, which means it is very conventional -- i.e. relatively boring. What I find exciting is the opportunity to use a language with most of Lisp's technical advantages and few of its social and platform disadvantages.
I think this is more than reasonable. I still wonder about some of Python's semantic limitations relative to, say, Objective Caml, and I still find its syntax a bit stilted and awkward. I tend to cringe when I see what look like magic words beginning and ending with "__". And I guess in the final analysis, I at least want the option of efficient compilation to native code. It just seems like I can get everything I want in a language someplace else, if only I'm willing to sacrifice the company of tens or hundreds of thousands of other programmers. So far, that hasn't felt like a sacrifice at all. But I remain puzzled as to why a few more tens or hundreds of thousands of programmers don't seem to agree, and like a lot of Schemers/LISPers/Smalltalkers/MLers/Haskellers/Erlangers, I tend to attribute it to simple lack of exposure, particularly when the technical benefits of a Python or Perl or TCL that are promoted are precisely those that accrue, IMHO in a stronger form, from most or all of the less popular languages. This leaves popularity as the single remaining characteristic, one that is essentially, beyond some tipping point, self-fulfilling, and therefore, in my mind, all but meaningless.
Regardless, I have to say that you've been most patient and considerate in this dialog, and I greatly appreciate that. It's helped me a great deal to refine my thinking about the personal technology choices that I make and the contexts in which I make them. It's also prompted me to revisit an old love, Scheme, with renewed appreciation (I also have to credit Python itself for that). So thank you!
Paul Prescod @ 05/22/2002 10:01 AM. Re: Python versus Scheme: This one is easy. First, you will probably never be able to get other programmers on your project to use Scheme. Second, Scheme is NOT a multiparadigm language. If you want objects in Scheme you either build them yourself or download a library. If you have six different scheme modules they will probably all implement objects in incompatible ways. The same goes for exception handling, iterators, generators etc.
Third, library: will you be able to find a single, portable scheme with you get threads? Unicode support? XML support? Matrix math? HTTP? FTP? GUIs for all platforms? Parsing? Legacy protocols like CORBA, COM and SOAP? ;)
I think it's important to differentiate between what I do for fun/enterpreneurship (yeah, right!) and what I do for work. On that basis, the "finding other Scheme programmers" thing may be a good point (that is, if I wanted to start a company and write in Scheme, that might be tricky. On the other hand, I have pretty easy access to CalTech grads...)
Practically all of the other points are addressed by some combination of MzScheme, SLIB, and/or S2. DrScheme is an excellent Scheme IDE for multiple platforms, and can be extended with some really amazing tools such as MrFlow, a static analyzer/debugger, the likes of which I have yet to see outside the LISP/Scheme world.
It seems to me that Scheme is enjoying robust health—I would say, considerably greater than that of its cousin, Common Lisp. R5RS has been with us since late 1998 and shows no signs of requiring further revision, with the Scheme Request for Implementation mechanism serving well as an extension approach—sufficiently well that S2 effectively unifies five very distinct Scheme systems mostly by leveraging SRFI-0.
So I maintain that Scheme has become the ultimate ball of mud.
More excellent stuff from someone whose clarity I envy, Paul Prescod (hey—he and Paul Graham and I are forming some kind of triangle! I guess one thing you can safely say is "Paul sure is passionate about programming languages.") I'll have to take this a bite at a time.
Paul Prescod @ 05/22/2002 10:01 AM. Okay, we seem to agree that the term "scripting language" is too vague to be helpful and that people can build real, new, interesting apps in pure Python or in a mix of Python and C.
Heavens, yes. Once again, I think a good FFI (foreign-function interface) is critical to a glue language, and Python has several extremely good ways to integrate with C and C++.
Let me go into more detail on lambda. Okay, as the lambda calculus proves, almost everything is syntactic sugar. But for most programmers, most of the time, lambda is a confusing way to accomplish whatever you are trying to accomplish. So for instance if you want just a plain old function, define a function. If you want to filter a list, use a list comprehension.
This is an important point that I think language discussions too often overlook: the functions/methods/closures that make sense to apply in a given situation depend greatly upon the data types/structures that are provided by the language and/or libraries. More on this in a moment.
If you want to package some state and behaviour together, use an object. I happen to believe that using lambda for everything makes code more difficult to read, just as using parentheses for everything makes code more difficult to read.
I think this becomes a matter of a combination of familiarity and the point above. If you start with a lambda language, like Scheme, then the lambda approach is "more readable" than whatever object mechanism you write/download (especially to someone else). If you start with an object language like Python or C++, then sure, the lambda approach that you write or download is less readable.
For instance, I compare the latter of these two options more readable:
>>> filter(lambda x: x%2==0, [1,2,3,4,5,6,7,8])
[2, 4, 6, 8]
>>> [x for x in [1,2,3,4,5,6,7,8] if x%2==0]
[2, 4, 6, 8]
(hope that doesn't get munged)
Looks good to me, and I agree with you, but I think your example reinforces an earlier, implicit point that I feel you made and with which I agree: given list comprehensions as a language feature, your second example is likely to be considered more readable. I had a moment's difficulty with it just because it's not clear to me where the "construct break," if you will, between "x in [1,2,3,4,5,6,7,8]" and "if x%2==0" is, or maybe I should say that it's unclear what the scope of the "for" is. Also, "x for ..." looks to me like a statement and leads me to wonder how I would compose more than one of them, whereas I have no trouble at all imagining how I would compose "filter(...)".
The same goes for this pair:
>>> map(lambda x: x*2, [1,2,3,4,5,6,7,8])
>>> [x*2 for x in [1,2,3,4,5,6,7,8]]
To me, the non-lambda version is easier to read than the lambda version.
I don't doubt that. It's easy for everyone—myself most certainly included—to make familiarity arguments.
The most explicit version of this phenomenon is Scheme's way of looping (tail-recursion) versus a simple Python for-loop. I'll take the for-loop any day!
C'mon, Paul! You know perfectly well that R5RS Scheme specifies both "do" and "named let" as iteration constructs. You also know that there are times when recursion is the most natural way to express an algorithm, but isn't safe even in most languages that support it due to concerns over stack overflow in cases of deep recursion. Tail-recursion optimization makes explicit the point that tail-recursion is not merely isomorphic to, but identical to, iteration. There's never been a Schemer who said "Rewrite all your iteration as tail-recursion." There have been many Schemers who have said "Good news! You no longer have to avoid recursion where it's the right approach due to concerns about stack overflow."
Paul Graham was beating up on Python because it doesn't like to build mutable closures. Once again, I think that the Python way is more explicit than the Lisp way, if only because most programmers do not think in terms of mutable closures but rather in terms of mutable objects.
I would agree that that's the only reason. ;-) Seriously, this is almost wholly a familiarity issue. If there were to evolve a generation of Goo programmers, they'd also probably have this same debate with Scheme programmers. In a previous generation, it was Oaklisp vs. plain Scheme. Same questions. You can start with lambda and write objects, or start with objects and write lambda.
The Common Lisp way of creating mutable objects is more succinct but most programmers (with a background in any of Python, Java, C++) would consider it harder to read.
And I think that's the crux of the question: what paradigm do you start with? I think this whole debate has degenerated into Common Lisp/Scheme vs. Python, where the real question at hand is functional paradigm vs. OO paradigm. I'd love to make the shift, because I think it would be more intellectually honest, more explicit, and more interesting. But perhaps not: that discussion would rapidly reach what I perceive as the same metastable point: want to start with objects but have lambda? Try Oaklisp. Want to start with lambda but have objects? Try Goo. Want to start with lambda, have objects, but not have parenthesis? Try Objective Caml. Want lambda, objects, logic, concurrency, and constraints? Try Oz.
I'm back to my original problem, which is: where does Python fit in the design space that makes it unique? I recommend, at this point, treating the question as rhetorical, as I have no reason to believe I'll ever use Python for work, and my personal programming language choices are strongly governed by Alan Perlis' dictum that "A programming language that doesn't change the way you think about programming isn't worth learning." The upshot is that bandwagon-effect arguments that have great commercial validity don't matter to me at all on a personal level. And since I've largely already concluded that Python has no fundamental distinguishing characteristics in programming language design space—a point that I feel you've acknowledged, I'd feel bad if anyone spent too much energy attempting to convince me otherwise.
Dave Winer @ 05/26/2002 09:05 AM. OK, but I wish my integrity as a developer and a philosopher of software hadn't had to take a hit. I don't think there's anything wrong with the architecture of Radio. It's pretty straightforward. Nothing I know about the software could account for that behavior. It's possible that clicking on the Refresh button could have cleared the problem. I guess we'll never know. Onward. [YACCS Comments for It's Like Déjà Vu All Over Again]
Well, it certainly wasn't my intention to impugn your integrity on any front. I must apologize if I gave that impression. While it's true that I am myself a developer, I sometimes allow my frustrations as a user to color my perceptions. Once I'm able to pull back a bit and regain some objectivity, I can see that there are too many variables in the equation to allow the reaching of a simple conclusion.
I do wonder sometimes—and this is only a point of curiosity, not an accusation—whether or not there's a potential issue in having a web interface (which must at least mean that there are object id's of some kind sitting in HTML pages that allow their editing/deletion) in front of a database that doesn't support transactions. There's also the question of if/when object id's get recycled.
In using a system that I believe to have these characteristics and having a problem with that system, I do indeed start thinking in terms that lead me to question the architecture. However, there's no question that to say that the architecture is flawed is premature and uncalled for, so I must apologize for that as well.
Radio 8.0.7 does a fine job of subscribing to some twenty-odd syndicated feeds, allowing me to comment or make original posts, and publish them to a service that Userland is kind enough to provide at an extremely reasonable price. Not only that, Userland has been gracious enough to expand their online storage for us users not once, but twice.
Finally, as I alluded to in my previous post, very few people have attempted to empower users as consistently as Dave over the past decade plus. Frontier, in one guise or another, has been with us for a long time. It's a pleasure to see things like ActiveRenderer, Kit, Stapler, rssDistiller, the Python IDE, and other great tools being built on the Radio foundation. And yes, it's great to see the integration points being built around XML-RPC and SOAP, even if I do feel REST principles are preferrable as a foundation (and I think Sam Ruby is doing an excellent job with REST/SOAP reconcillation efforts).
Finally, I wouldn't even know any of this was going on if not for Radio! So, thanks.
Joey deVilla @ 05/26/2002 03:51 AM. Ah, the dangers of the smart-ass retort that appears on BoingBoing. Luckily no angry mob has shown up at my door, waiting to kick my cdr.
The meat of my complaint about Graham's article was its apparent snootiness rather than the points he's laid out. I found it a jarring change from the tone of the other writing on his site and ANSI Common Lisp, which I'm currently working through.
My retort to Welsh's posting on Lambda the Ultimate wasn't a reply to Graham, but a response to a completely other issue -- and an attempt to counter bad generalization with equally bad generalization, and not intended as an ad hominem attack. You've got the meat of the point I was trying to make there: "use commodity technology to address commodity problems. Use less commoditized technology to address less commoditized problems".
I've re-read Paul Graham's Revenge of the Nerds at least five times now. I'm sure there's a heavy self-selection process going on, but I just can't see the "snootiness" that Joey and at least one other person whose name escapes me at the moment detected there. Mostly Graham talks about very divergent language-design choices and what informs them, using the two oldest extant languages, FORTRAN and LISP, as a launching-off point.
Well, OK: he makes the fatal error of daring to suggest that most modern languages are still catching up in expressive power to LISP. I don't know what to say about that. I went through a period of some years of pointing people to gems like Daniel Friedman's logic programming system in Scheme, or Guy Steele's constraint system in Scheme, or the Similix partial evaluator... the maddening thing is that it's not that some people can't see; it's that they won't see.
I have to say that, in my experience, the "worse is better" language crowd has been far "snootier" in forcing their McDonald's of programming languages down our throats than anyone in the LISP or, more generally, functional camp has dared to be. All you have to do is read Erann Gat's tale about LISP at JPL to see one shining example, and it's worth pointing out that this is in the context of Erann saying that he's moved on from LISP himself and that LISP needs to evolve, the same message that I think Graham is delivering. Unfortunately, Erann's experience at JPL is common to Lispers: LISP gets blamed for totally unrelated project failures by folks who don't know LISP or, worse, aren't technical managers at all. It's a more aggressive form of the self-fulfilling prophecy that says "LISP is a marginal language, so we won't use it."
So I'm glad I got to the meat of what you were trying to say. But it continues to strike me as a bit peculiar to have folks who are clearly lined up with the majority when it comes to programming languages invest any energy in potshots at the minority, bad generalizations or no.