Practicality: PHP vs Lisp
briancarper.net
briancarper.net
"Today, Lisp is nothing like what it was 8,7,6, even 2 years ago. It's not just "good" in the well-explored text book fashion; no, it's _good shit_. Get work done good. Think, hack, ship, bill for it good. 2-3 products per month good. You still have to know where things are, who is working on what, what's maintained and what's obsoleted by what. Sure. But there is absolutely no lack of libraries." (http://news.ycombinator.com/item?id=972423).
I'm curious if the author of the article has similar experience deploying CL or if this article is just theorycrafting. I notice some experience with Clojure, but this article was written in 2008.
I have.
I had to seriously hack on Weblocks just to get things to work they way they should. I had to work around various bugs and omissions. And worst of all, every once in a while I discovered that I am clearly the only user of said software.
A good example is when I discovered that the database interface (to CLSQL) isn't thread-safe. It was a quick hack intended for a single thread only. Obviously you'd never notice it in a demo setup. Turns out I noticed it just when somebody else had that problem and wrote CLSQL-FLUID.
But there is more — after running the application for several months I discovered two things:
a) there are obscure bugs related to caching in CLSQL, which I don't have time to hunt down (stale content is being served),
b) there are bugs somewhere either in CLSQL or Weblocks that blocked part of my admin interface and they are obscure enough that I don't even know where to start looking,
c) every once in a while SBCL will crash on me and land me in the LDB.
Don't get me wrong — I like CL and I invested a significant amount of work in to Weblocks — but I agree with Brian here: I don't want to discovere somewhere along the way that I'm the first real user. At least not when I am on a deadline.
I do most of my work in Clojure now, but when there is a simple web application to write — hey, we get our hands dirty and we do it using PHP. Because life is too short.
I've had my eye on Scheme as a potential web application environment for a year now. Maybe I'll make the jump soon, Racket (PLT-Scheme) looks like it would beat CL + Weblocks in maturity.
Can you elaborate ?
In PHP, unless headers have already been sent, you can call this: header("Location: blablablabl") from wherever.
That's just one example of the difference in workflow, it took me some getting used to before I could appreciate it. There are many other "little" things such as above, that are different.
I'm loving Python + Pylons, the more I use it the more I get used to the workflow too...
If a project is absolutely tiny, like 10 lines, or utterly disposable, I'll still do it in PHP. Otherwise, I'd sooner quit coding and take up nude karaoke than do a new project in PHP.
In any case, I'm not a fan of using CL as the end to end solution for a web application. It performs far better as the middleware between the web front-end and dbase back-end. From my understanding, this is what ITA does (details in this thread: http://news.ycombinator.com/item?id=1479107). Who cares that you can't throw up a shiny front end right away if the code that does your business logic is an order of magnitude more shorter/powerful?
I'm not sure what Slava's goal was when he started Weblocks (he never intended to start a web startup at that time as far as I know), and neither do most of the developers that came after him (Slava stopped working on Weblocks long before RethinkDB) do full-time commercial Lisp web work. And that's the problem.
Also, there is nothing about CLSQL that prevents writing race-free code. Sharing connections across threads without locks won't be race free (duh).
I had a lot of ideas about web development I wanted to try out because I believed (and still do) that given the right development environment we could make web applications responsive and interactive in a way that isn't manageable now because of complexity. I wanted a language that could support these ideas, and I picked Common Lisp. I think in practice Weblocks failed to make any of these ideas a reality because the design didn't account for a lot of complexity I didn't realize existed. I am still convinced that the original ideas were solid, and that someone, some day, will make them work in some form or another.
I actually think Ruby on Rails is the worst thing that happened to web development, because it convinced almost everyone that web development is now a solved problem and this is as far we go. It isn't - we've only scratched the surface of what's possible. In terms of Weblocks though, Lisp is well known for insane expectations and few real world applications that satisfy them, so I think blaming it all on Weblocks is giving it too much credit :)
I don't know any Rails devs that think this. I constantly get the feeling when building Rails apps that there are still plenty of opportunities for making things easier and simpler.
However, none of the alternatives are any better and most are far worse, particularly the current crop of half-hearted lisp & functional approaches. I'm still open to the idea that functional languages can be used as the basis of a superior framework but nobody's come close to demonstrating that yet. Redoing Sinatra in Clojure/Scala/Lisp/Haskell isn't going to get you even close.
Still, there is something very true to the original comment. Most web frameworks are wed to an overall philosophy for creating web applications. Rails is unlikely to depart from the MVC pattern for example. If you agree with that you can see that Rails, and any other framework I can think of, can at best hope to strive for a local maximum, unless their overall approaches are eventually validated as the way to do things, but I find that very unlikely.
I like the idea of web frameworks using functional languages, largely because I believe a framework written in a functional language will be better capable of adapting to new advances. I definitely agree with you about Sinatra. Even if a lisp or other FP language is better suited to the task, the advance will be evolutionary at best, while what I'd like to see is something revolutionary.
It's interesting that you think that the Weblocks ideas will continue to be relevant. I'm convinced that HTML5 canvas will make UI issues history, just as I'm convinced that AJAX makes using continuations for managing web app state a really bad idea.
The real point here is that Lisp makes it possible to combine the tools you want to build web applications in ways that are appropriate. Almost all frameworks in other languages are there because that is something that is really hard to do with deficient tools otherwise. Almost all Lisp web frameworks are there because somehow some Lisp programmers became convinced that you need one to write a web application. We're just borrowing stupid ideas from stupid collections of hacks written to deal with stupid tools. "Framework" should be a dirty word.
I don't think most people care about RoR. It's to PHP what PHP was to Perl. Next someone is going to choose another stupid personal language to build a framework with really nifty canvas widgets that interfaces to a no-SQL database and that will go big (hmm, time for me to abandon my principles and become a famous "framework" author?). The only real winner in all of this is O'Reilly, who get to publish 50 different books about all the stupid tools involved.
I think UCW is bad for three reasons: trying to hide the fact that HTTP is stateless with continuations, introducing way too many concepts/mechanisms unrelated to actually serving pages, and I don't like Marco Baringer's (original UCW author) code very much.
The third reason is subjective, the first two somewhat less so. I actually have a blog post with some diagrams in the idea stage about why managing HTTP web app state with continuations is a terrible idea (it all comes down to the fact that it makes it much harder to test) - already noted criticisms include meaningless URLs (can't link/bookmark), and harder debugging. Since UCW uses CPS transformation to get continuations, it means the resulting code is almost impossible to debug.
Next, look at the documentation for UCW: http://common-lisp.net/project/ucw/repos/ucw-core/doc/gettin...
Entry points? Components that need the MOP? Frames? Actions? Just to understand how components get output to HTML and served you need to know the MOP. So you have the UCW component code, the UCW MOP code, the UCW entry/continuation code, the UCW interface on top of an HTTP server. Now you need to learn a whole new horribly complicated UI toolkit and still deal with all the regular web stuff.
This isn't any different that Weblocks. The difference between Weblocks "horrible" and UCW "truly horrible" is in things like the UCW system definition file: http://common-lisp.net/project/ucw/repos/ucw-core/ucw-core.a...
The eval-when, the useless (but confusing - how is it different than regular defclass?) defclass* macro, the defvars completely unrelated to system definition. And this is just the very first file!
Web programming is not a solved problem. I haven't found a framework yet that I'd really like to use.
Also, there are real-world applications using Weblocks — read my post above. I am not entirely happy with the state of affairs, but it isn't really weblocks' fault, but the CL environment in general.
As another data point, I find the Clojure environment to be much more mature, because of the JVM and many widely-used Java libraries.
http://lists.b9.com/pipermail/clsql-help/2005-April/000416.h...
Although it's not at all obvious from the documentation that you should use the with-database macro:
http://clsql.b9.com/manual/with-database.html
I actually remember this tripped me up the first time I used CLSQL.
It's not that hard to get a quick webapp up and running with Hunchentoot, but there is a lot more generally that you'll need. Cliki and CL-Directory are actually pretty good resources for finding out what's available, but they don't tell you, with any clarity, what's useful, what's maintained, what's finished, etc. You kind of need to figure out that by checking. It can be a bit of a pain.
It struck me the other day that this is why archivists have trouble with the web. Old links go dead all the time. Various people have tried to convince web publishers that they should take the preservation of old links seriously - we are destroying history! But it isn't just that preserving old links is hard work - which it is - but that history is a terrible burden for the living. You are forced to curate and disclaim it, or risk having it held against you. It's much more comfortable to just walk away from your history and hope that it biodegrades.
Forgetfulness is a blessing, and few online systems provide it in any well-thought-out fashion. Users are forced to use hacks to achieve it.
Publishing thoughts on web, like print, demands rigour from the author and the reader. Read actively, write like you have an audience, and be skeptical.
This is another mindset endemic to engineers like myself: First-order thinking. The notion that, because a bit in a piece of flash RAM, a memory in someone's brain, and an etching on the wall of a thousand-year-old church are all the same to first order -- "persistent" storage of information -- they can therefore safely be treated as the same thing.
The second-order differences are pretty important. To pick just one particular example: Human memory is not just an incredibly fallable medium (you remember events that never happened, and your memory of events that did happen gets distorted over time and is situational, dependent on your current mood) but it is inevitably filtered through the personality of the rememberer. The only way to learn what a World War II veteran remembers about the war is to listen to what the veteran tells you. If the veteran happens to have been a personal friend of General Patton, they will tell you certain things about Patton. If the veteran was a sworn enemy of Patton, they will tell you other things about Patton. If you strive to prevent them from doing this consciously, they will do so unconsciously. Such is the nature of human memory and communication.
A photograph of Patton, or a written memoir, is an entirely different beast.
And, similarly, there is a big qualitative difference between a third-hand account of a conversation in a bar, an entry in a handwritten diary that is stored in your basement someplace, and a popular web page that has been downloaded a thousand times and is available on Bittorrent in case the original is taken down.
But I couldn't justify using either for a project for work. I generally choose Ruby instead nowadays. In Clojure I still end up rolling my own libraries for a lot of things, which is really quite fun in my spare time, but not justifiable if I'm billing by the hour and there are a dozen Ruby gems already written to do it.
We have seemingly constant threads on HN saying "I can't hire a good programmer!" What are the chances of my non-programmer boss hiring a good Lisp programmer? At the small non-profit at which I work? Good freaking luck.
I'm still using some PHP scripts at work today, and I still cringe to see the code, and I whine a little (to myself) whenever I have to edit it, and my boss still loves the end result, and it's done its job well for 2 years. What else matters? I believe in "Worse is Better" in this case.
I do sneakily use Clojure at work for small data-munging tasks. But not for code anyone else ever needs to see.
(I do also wonder why this blog post from 2008 made it to HN.)
How do you think these Ruby libraries got written?
If you want to put Clojure in the spotlight don't use it to build redundant, half-assed solutions to problems that are already solved. Use it to solve a new problem. Companies like Runa and BackType and Flightcaster are setting the right example here.
Someone has to get the basics in place. Trying to do a web 3.0 startup that may or may not succeed, using clojure, will have absolutely no impact on getting people to use clojure for web development.
"There are 10x as many potential library writers for Ruby/Python etc because it's 10x easier to get up to speed in those languages."
Why? Clojure is smaller, simpler and more consistent than either Python or Ruby.
Forth is even simpler than Clojure. A language is not necessarily easy to learn just because it has a small, simple, orthogonal core. Understanding how bricks are made doesn't automatically make it easier to build a house. It's the difficulty of the macro-concepts that makes the most difference and most people find imperative programming and mutable state and infix syntax easier to handle than declarative programming and immutability and prefix syntax. Lisp has been more powerful than the competition for most of its history but it's never been popular.
TL;DR size isn't everything.
Where is the empirical data to support this?
The overwhelming (and it really is overwhelming) market preference is for imperative, infix languages with rich syntax. The extraordinary claim that this is purely circumstantial is the one that requires extraordinary proof.
In America, there is also overwhelming market preference for junk food. It doesn't mean junk food is better for you.
So what's your explanation then? If functional languages are no more difficult to learn and are more powerful why are they not used? Why have Python and Ruby flourished while Lisp and ML remain academic obscurities?
I still say the burden of proof is on the FP advocates. If you want to claim that everybody is doing it wrong you should have a pretty strong case.
Programming languages are cultural, not technical, artifacts. For reasons why one language is used by more programmers at a given point in time than another you need to turn to sociology. Lisp has some clearly superior technical ideas, which is why it has continued to be used and expanded for the last 50 years, and why all the other languages you mention (Python, Ruby, ML) drew ideas there. On the other hand, a language like Perl (and as Python and Ruby will eventually be) is briefly popular, but has no compelling technical features or metaprogramming facilities for people to continue to use and expand it when another shiny new language comes along.
See the CPAN and especially modules such as PPI, Moose, and Devel::Declare.
So O'Reilly can sell books about it.*
"Despite the existence of Rails, Perl 5 is still more widely used than Ruby."
Who is writing new projects in Perl 5? Ruby will also have a lot of legacy code in five years.
* If you thought that was a joke, you're still missing the point.
I suffer no illusion that their sales numbers have any correlation to the popularity or efficacy of a technology. Their Ruby book sales crashed in 2007, for example.
Who is writing new projects in Perl 5?
I know of many, many new projects written in Perl 5. So far this year I've worked on three and have another later in the year.
I guess all that PR and advertising from dozens of publishing, training, analyst and consulting firms is a giant waste of money?
Sociology is a factor but that's wildly overstating the case. The fact that people prefer to borrow from Lisp rather that adopt it is telling. Many programmers are aware enough of Lisp to take inspiration from it but choose not to use the language itself.
There's a subtext of arrogance in the claims FP and Lisp advocates make about the popularity of various programming languages. In my experience most of those people don't actually write much code. I gave up on the Common Lisp community years ago after realizing that it was full of people that would rather sit around discussing how things should be than actually building something.
Clay Shirky talks about people knocking out an important app in 2 days PHP here: http://www.ted.com/talks/clay_shirky_how_cognitive_surplus_w...
I doubt very much that the typical Lisp crowd would have gotten past arguing which web templating library to use.
And how does anything you wrote after this sentence not support my argument?
Sometimes I wonder how much closures and meta-programming is just code for coding sake. I've seen lots of examples of 5 line LISP code that does something totally amazing but you don't really know what it means but it's so abstract. If you have a quick job to do, I don't see that it's a limitation in using a language that requires to build the most straight forward solution.
PHP is ugly, but for the most part it isn't horrible -- these days you can easily avoid some of the worst parts and concentrate on making code that would be very equivalent to the same code in, say, Java. PHP is very straight forward -- it means what it says.
"Your web framework in PHP probably isn't continuation-based, it probably doesn't compile your s-expression HTML tree into assembler code before rendering it."
This just sounds like over-engineering the problem.
(Though I do admit that I immensely like Lisp's macros.)
In e.g. Haskell abstractions are the straightforward way to solve a problem. Abstractions are cheap.
Currying and combinators are my preferred ways of creating new functions. Having infix symbols can help a bit, but I don't see it as crucial.
Incidentally I only really began to use reduce/fold in Clean and Haskell, though I had been exposed to the concept in Scheme before, and used it a few times. But perhaps that was just a learning effect of prolonged exposure and would have happened while staying with Scheme, too.
I still like Scheme. Matthias Felleisen is doing great work using it for education.
Compare:
(define (list-reverse l) (foldl cons '() l))
listReverse = foldl (flip (:)) []
I hope both versions are fairly idiomatic.Here are two combinators that I have actually used in my code (the first one is fairly common):
dot :: (b -> c) -> (a1 -> a2 -> b) -> a1 -> a2 -> c
dot = ((.).(.))
swing :: (((a -> b) -> b) -> c -> d) -> c -> a -> d
swing = flip . (. flip id)
Imagine (or better: provide!) Scheme versions or their idiomatic equivalents.Of course the point-free definitions makes them a bit hard to understand, but I wanted to demonstrate terseness. `dot' also has a nice point-full definition:
dot f g a b = f (g a b)
The use case for `dot' should be obvious from the latter definition. I leave the point-full definition (and a use case) for `swing' as an exercise. Let me just note that Lisp would carry some more syntactic baggage for the definition and use of both of these combinators.However, you can't beat Lisp, when it comes to Quines:
((lambda (x) `(,x ',x)) '(lambda (x) `(,x ',x)))
Haskell's facilities for talking about Haskell code are more verbose.P.S. for completeness sake, to make the exercise above easier without doing a search:
id a = a
flip f a b = f b aThe mental energy is probably not worth it if you are just building a blog for yourself, but in that case, the mental energy of learning PHP is not worth it either. If the job is really that quick, why are you using dynamically generated content in the first place? HTML one-off's are the most straight forward solution.
On the other hand, if you want to build a bulletproof web application, you should probably use powerful tools, figure them out once, and then actually solve your problem.
You probably already know PHP. It's so much like many other languages and it doesn't require much knowledge to get started. Many of the "gotchas" about PHP are more academic than practical and if you are ignorant about these things then you are more likely to do it right. Some of the horrible stuff, like huge body of non-namespaced functions, is pretty easy to search though and then use without a lot of knowledge overhead.
I actually write very large business web applications in PHP. Crazy? Maybe. There is a bit of a sunk cost here, when the app was started most other solutions were pretty immature. However even with potentially "better" options now, PHP isn't going to burn down the house.
Sometimes I wonder how much closures and meta-programming is just code
for coding sake. I've seen lots of examples of 5 line LISP code that does
something totally amazing but you don't really know what it means but it's
so abstract
You could the same for so many PHP frameworks. Why are there so many classes? Why do I have to inherit from a class I don't understand? Why am I forced to define classes at all? Why are my custom classes 50% getters/setters? Why are my objects mutable? etc. etc. etc. (map :last-name people)
The point is if the language provides the proper level of abstraction, you end writing less of your own hand rolled abstractions.Again the only thing I'm hearing here is arguments from people who are too lazy to actually see how things are done from a functional perspective. Get off your ass and find out. Then tell me you have a problem with it.
You don't even have to include the word "PHP" in there. A lot of frameworks include a massive amount of functionality that you're almost never going to use. And for the few times you might need to use it, it'll probably take less and less learning and less dependency on code you don't control just to code up something by hand.
But my complaint isn't about frameworks or their relative complexity. It's about how most people touting some of these solutions pride themselves on how terse the end result is. This goes well beyond DRY. A good abstraction is great for providing a clean view of the logic, but some abstractions and meta-programming take it so far that now the logic is no longer obvious.
> Again the only thing I'm hearing here is arguments from people who are too lazy to actually see how things are done from a functional perspective.
I've done functional programming work in the past (ML) but the fact is, it's just much harder to just get things done in functional languages. When you find the perfect domain mapping for functional work, it's great, but most of the time you don't have that. It's like arguing the Esperanto is a nicer and cleaner language than English -- that's probably true -- but if you want to get work done you use English.
This is 2010, we're not living in a FP vs. OO world anymore. Clojure (and I've heard Scala) preserves the greats parts about OO programming. I'm sure this is the just the beginning.
With my addition above I agree with you 100%. Generalizing from personal experience? Let's try to raise the bar on discourse a little higher.
There was a recent article posted here about people assuming, by default, that they are smarter than everyone else. Lisp has had over 50 years to prove that it can be used to develop software better than all the alternatives and it's still less successful attracting developers than languages just a few years old. It appears the previous commenter is just assuming he knows something that 99.9999% of other developers don't.
I don't advocate any particular language or platform for all possible solutions. Sometimes Java is right choice, sometimes PHP, sometimes C#, Python, etc. And whether or not a developer knows the language is a large factor but it's not the overriding factor. Trying to shoe-horn in a language of choice into every situation is a recipe for disaster. Sometimes it's necessary to learn a platform/language to effectively tackle certain tasks. So far, I've personally been unable to find a situation where Lisp seems to work. To generalize it: there is lots evidence that a vast majority of other developers haven't either. You can either assume they're all morons or not.
In my own ridiculously limited experience (which happens to include one new FP lang) I found your claim to be simply, irrefutably (in my mind) untrue.
The whole point of karma on HN is to keep things in balance. And I saw the need to keep the balance here. If you can't roll with that what's the point of discussion?
Movin' on.
Honestly, I'm not even sure what claim you're talking about. I think I even agreed with you. The whole line about lazy and ignorant seems entirely tacked on without referring to anything in particular.
> And I saw the need to keep the balance here.
You made a valid point but then you went into essentially personal attacks. That's not the kind of thing that Hacker News is about.
http://brl.codesimply.net/brl_4.html#SEC31
I can't forget to fetch the next row from the database. I can't forget to check that I'm at the end of the result set. Grouping the results is easy and straightforward. The statement and connection objects are automatically closed when the request is done. Compare that to PHP.
I'm getting better, but even today I feel a little irritated when someone says PHP was designed for simple web/database apps. I know what a language designed for simple web/db apps looks like, and PHP is not it.
sql_apply("select id,somefield from sometable","applicator_function");
PHP is a programming language, it was not designed for 'simple web/database apps' any more than any other language, you can use the building blocks provided to create access at the level you require. But you can customize it so that it does become usable for 'simple web/database apps'.The above is a short sample of how I'd do the thing you describe and I don't have to remember to fetch the next row from the table and I don't have to check that I'm at the end of the result set, grouping is as easy as SQL will make it and all cleanup is automatic.
Um, yes it was. See http://en.wikipedia.org/wiki/PHP#History to verify that PHP started as a bunch of CGI binaries to serve some simple dynamic web pages. The database bit came later, but at the start it was explicitly designed for quick and dirty web pages.
You could make such statements about every other mainstream language.
I guess we can't blame PHP for preserving the $ in front of variable-names with all the legacy code lying around. But the following should parse in a sane language:
$width = getimagesize($filename)[0];
Adding support for this would not break legacy code. Nobody can tell me that naming all intermediate results like $sizes = getimagesize($img);
$width = $sizes[0];
is such a preferable style, that the parser should enforce it.By the way, this is how PHP pretends to support higher order functions:
function cube($n) {return($n * $n * $n);}
$a = array(1, 2, 3, 4, 5);
$b = array_map("cube", $a);And yes, you can make such statements about every other mainstream language. For instance Perl was more designed for text manipulation than most other general purpose programming languages. Java was more designed for multi-threading than most other general purpose languages. C was more designed for close to the machine programming than most other general purpose languages.
All of these things are true. All of these things still show in various ways. Yet every one of those is a general purpose language that can be used for anything you want.
$result = $conn->execute('select * from favcolor order by color, name');
while($row = $result->next()) {
if ($result->groupBeginning('color')) {
echo $row['color'].': '.$row['name'];
} else {
echo ', '.$row['name'];
}
if ($result->groupEnding('color')) echo "\n";
}
echo 'Count:'.$result->count();
I just came up that off the top of my head, but there's nothing impossible in there. Also, instead of field name for groupBeginning(), passing a closure would also be possible. echo $conn->execute('select * from favcolor order by color, name')
->groupBy(L(val)->color)
->map(L(key)->wrap('<li><b>', '</b>')
->append(
': ',
L(val)->map(L(val)->name)->join(','),
'</li>'))
->join("\n");Also http://commonphp.blogspot.com is where I write about it.
// controller function
public getcolors($request) {
$db = CMS::GetDB();
$request->favcolor = $db->transform($db->getRows("select * from favcolor order by color, name"), "collect", "color");
}
// and the template
{@ favcolor ?
"<ul>"
`<li><strong>{$key}</strong>: {$:implode(", ")}</li>`
"</ul>" @}
the template uses a control structure called a conditerator (more info at the site). The controller uses a data transform to convert the set of rows into a hash of rows keyed on color.I think that is more concise and reads better than the BRL example.
(Whether MVC is the right style is a topic for another discussion.)
As an example, in the Clojure space there are two libraries that are good exemplars of the ends of the spectrum: Hiccup and Enlive.
Hiccup (http://github.com/weavejester/hiccup) uses sexpressions to define the (ht|x)ml output. Effectively either the developer and designer roles are fused or the developer gets a design from the designer and encodes it into hiccup manually.
Enlive (http://github.com/cgrand/enlive) is (in overly simplistic terms) a selector driven substitution engine. You give it an HTML file for a template and some CSS selectors describing what to modify, alternatively you define a snippet in terms of some elements within the page. In this model the designers work is first class resource, and not modified by the developer.
This is exactly the same breadth of options as I've seen in just about any real language being used for development tools.
Except the problem was never defined. Of the five commercial Lisp applications I've worked on, two are addressing domains (large-scale financial calculations, and a web platform/OS) where using PHP makes absolutely no sense, and the current one (ERP) where PHP was previously attempted and found not to make any sense. All three use basic techniques like closures, markup generation and metaprogramming, and one of them is continuation-based (which I think is a mistake, but opinions differ).
A tool is seldom more than a tool. In regard to languages, for most projects there are more than enough constraints to begin with, so you can pick a language of your choice in no time. Sure there are languages that suck and languages that are awesome. But most of these comparisons only work in a vacuum. And in practice, no project ever starts in a vacuum.
Use tools appropriate to your skills and to the job you are trying to get done. Learning to use more powerful tools is one of the best ways to increase your effectiveness.
That is the best tool depends on both the job and your skills. (Most of the post was about my main illustration though, which was drafting versus CAD.)
This article could easily be turned around to something like "use emacs, lisp and the trusted framework you already know, or try to learn PHP with its inconsistent naming and verbose syntax and ..."
Essentially he's judging languages by "wall-clock time", but only including time-to-learn in one of them.
It took me 2 years to finally get comfortable with Emacs to the point I trust doing stuff in it, and I still don't know what I'm going to do if I ever start working in a language that doesn't have an editing mode available (it's not Textmate where you can define a syntax file in an hour).
For a whole month I studied Clojure, trying to wrap my head around it. I still have problems.
And now if I'd want to do stuff in Clojure, all web frameworks available suck for me (no, I don't like Compojure) ... which would mean I'd have to write my own ... or use Django, Rails 3, or even asp.net mvc 2 (even that is preferable).
Of course, being the yak-shaver that I am, I'll probably attempt to write a web-framework for Clojure of my own, but not when the clock is ticking.
On PHP ... doing PHP programming / copying popular websites was my first job. It took me exactly 1 week for going from a complete zero to someone that could get the job done.
I don't love PHP as there are truly better options out there, but libraries/frameworks are more important than languages. If Java frameworks would've been designed with an eye towards their users and not to please managers, it would've crushed all other high-level languages by now (and it did in many ways).
There are a couple of things a web-developer needs ... data-models, with validations, form/request handling with validations (forms that render themselves are a plus), authentication/authorization (OpenID/Facebook/whatever support should be available of course), CRUD generating (I don't want to work on stupid admin interfaces that show tables of existing items more than 10 minutes), session handling, caching support backed in, a nice templating language that doesn't suck ... and a (lazy) ORM querying language would be nice (bonus points if it has integration with NoSQL databases). And all of them nicely integrated of course, as I don't want to lose time trying to figure out how to blend them in.
That's not much to ask, and these are problems devs have struggled with in the last 10 years ... it is unacceptable to work just with servlets.
Clojure doesn't suffer for capability or libraries. It has that in spades and then some. The main thing missing is a site that documents how to use these pieces in concert to accomplish common web programming tasks.
You know, not to get dragged into a stupid language debate, but for any language, a proposed solution without documentation is not a solution.
The challenge is to prove that those smart programmers working in that smart language are still more productive than the average programmers that started with the problem 75% solved out of the gate. For basically solved problems like CRUD webapps you won't be able to do this. For harder problems like scheduling air travel you might but then you're working in a problem domain too difficult for at least 3/4 of the working programmers today so you're in an even smaller niche.
Clojure (or any functional language) doesn't have a tiny
fraction of the libraries/frameworks/documentation that
PHP does.
Well, you get all those Java libraries out there for free ('free' as in automatically, not necessarily 'free' as in without paying)PHP is pretty bad when it comes to reusable libraries. PEAR is a pretty unusable mess, the Zend "framework" is a bit better, but still not that all-encompassing. Core PHP is a huge hodgepodge of very bare wrappers around C libraries, without a decent module system or OO layer.
The documentation is often centered around newbie questions and most frameworks really reinvent the wheel -- and quite often Ruby on Rails (which is pretty painful considering the PHP execution model).
I'd rate the library repositories of Perl, Ruby and Python above that, and even with some paradigm mismatch, Clojure's access to Java libraries is at least on par with PHP (PHP/C vs. Clojure/Java).
As another poster noted, Clojure gives you access to the Java libraries, which is a huge, huge win for Clojure vs most other functional languages but gluing that stuff together is still going to be more work than it's worth if you're not doing something really unusual with your site.
The functional web stack that looks the most promising to me at the moment is the Play framework with Scala. It seems a lot simpler and more manageable than Lift and Scala drops in pretty nicely in place of Java. From what I can tell there are still a lot of rough edges but I think it's a combination worth keeping an eye on.
Clojure I'm evaluating for my own project.
I've dabbled with Common Lisp for webdevelopment and I failed, miserably. I tried various the Mandriva package manager, downloading latest releases from the web, automatically and manually. It was already hard to get a bunch of packages together that where stable, somewhat current and compatible so I eventually quit.
If someone in the Common Lisp community could put together a web stack to get started it would help people like me tremendously. Lisps superiority is no point of discussion for me.
From the article: "You can learn PHP in a day or two if you're familiar with any other language. You can write PHP code in any editor or environment you want. Emacs? Vim? Notepad? nano? Who cares? Whatever floats your boat. Being a stupid language also means that everyone knows it. "
The author didn't spend a lot of time talking about learning PHP because there's not much to learn. There's nothing surprising in the components in the PHP stack. If you know HTML, adding PHP has low overhead. DB reads and writes are simple. If you can program in another language, you know all of the logic statements you need to write an application. If you need an example, there are probably tens of thousands of bad PHP tutorials online with bad sample code that still manages to work.
I've learned PHP and Common Lisp from scratch at different points in my life, and PHP had a much lower barrier to entry. I installed and configured PHP on my local machine and made a stats-tracking webpage all on the same day. This was my first server-side web application ever, plus my first database program ever.
Fast forward 4 years, and I worked through "ANSI Common Lisp" for a month before I felt comfortable writing regular applications in Lisp. Then I installed Hunchentoot and stumbled around for a while, but was able to figure out how to generate static content. Most of the Hunchentoot tutorials online were for older versions, but I found one that proved invaluable. I then ended up patching S-XML, because it was only written to support 5 or 6 of the 250+ "&" style HTML character codes. I sent that patch to the mailing list, but I bet nobody ever got it. I tried to hook up a database, and found Postmodern, which was nice. Thank God I already knew Emacs, but I wasted more than a day fighting with upgrading SLIME and SBCL at the same time.
The Common Lisp path doesn't sound so bad, but compare it to my PHP experience - I wrote an application on the same day I first looked at PHP. By the time I was integrating Database code, I was well over a month into learning Common Lisp.
Common Lisp may not be a paragon of elegance, but it's not nearly as awful as PHP. And Common Lisp is a fairly conventional, mostly imperative language. Nothing as scary as Haskell or Prolog, or even Scheme.
It's the same as Worse Is Better: http://www.dreamsongs.com/WorseIsBetter.html
People with the problems you mentioned are one of two types of people:
1. No prior programming experience. 2. Do not understand fundamentals of programming.
These are the people that use $var1, $var2, and $var3 instead of arrays.
Beyond that, if you can't be bother to learn the difference between =, ==, and === in PHP, you aren't bothering to learn, and have no reason to complain.
It's very close to trite. Yes, PHP is easier to learn. But if you're already proficient with Lisp, would you still be faster learning PHP? And if you are not up to speed with lisp, why the hell would you even be considering it for a time-sensitive quick-n-dirty job?
The question he set out with was "why is PHP more popular"? His answer is "because it's easier to learn and more popular".
I still have a Clojure book on my shelf, read almost the whole thing, got emacs off the ground with SLIME a few times, and haven't actually solved a business problem with it. I have existing code bases in Python and Java, and I can create way bigger wins by fixing the obviously wrong things with them than by bolting on some component in Clojure and creating a new area of "nobody knows what happens here".
Mayyyyyybe if you have specific needs then a lisp is a good idea -- if you're in a green field situation, have sufficiently complex application logic to justify an unusual web setup (this is much more rare than people think), and either know what you're doing with lisp and/or have a long timeline to figure out what you're doing. But it's pretty uncommon, and as awesome and elegant as LISP is, it's refreshing to see someone writing from everyday experience rather than "this is cool!" once in a while.
I haven't found anything misleading enough in the actual documentation to remember.
Moral of the story? Don't use PHP for stats.
To say most programmers are craftsmen is a huge overstatement. Most programmers have no sense of craftsmenship.
For example NOLOH (http://www.noloh.com), which provides just that sort of abstraction. NOLOH devs never even need to really know that they're in PHP. You would never know it from the consistent and elegant code, or the numerous syntactic sugars that make coding in it a joy. While none of this is out of the box in PHP, once you add NOLOH, poof, wonderful, clean, and consistent language, with language features that rival many others. Furthermore, any PHP environment can benefit from this, including all shared hosting users.
Thus in my opinion it's never that clear cut to suggest, oh PHP is crap, it's terrible, I hate working with it, because the language is flexible enough that you can write a framework that makes programming in it a joy. Now, if you were to ask me if I would use PHP without NOLOH that would be difficult. I've done it before, and it isn't so bad, but I would likely only go so far to a small script, or a small WebApp.
Disclaimer: I'm a co-founder of NOLOH
(map-dict
[k v | tag :li (tag :strong k) (join "," (map [get :name _] v))]
(group-by :color (sql-query "select * from favcolor order by color, name")))Lisp may be a superior langage, but setting it up is impractical for anybody who isn't used to hack emacs and bash scripts all day.
> but setting it up is impractical for anybody who
> isn't used to hack emacs and bash scripts all day
This is Hacker News right?Having built websites in PHP, Python, Ruby, and Clojure ... guess what? They all present you with equal challenges if you're not building trivial small websites on shared hosting.
Getting a website up and running in Clojure is as simple as it gets. Compojure ships with a good webserver baked right in.
Well you first have to get clojure running. And that's not as simple as it gets
My time from 0 to getting (the correct!) result of (+2 2) from Clojure's REPL was approximately 60 seconds.
Pretty simple.
#apt-get install closure
#closure
user=> (+ 2 2)
4
Most of that 45 s was waiting for apt-get.
Now it's not going to be this easy on platforms that don't have such nice package management (e.g. Windows). Furthermore, Raphael_Amiard makes a good point that there's a lot more infrastructure that has to go into web application development (or any other kind of application development, for that matter) than computing the sum of 2 and 2.
Nonetheless, it just doesn't seem that hard. At worst, put a "clojure /path/to/project.lisp" in rc.local or equivalent.
(Caveat: my web development experience consists entirely of a couple of toy projects I ran on my laptop for my own amusement. Take all this with a grain of salt.)
EDITed for formatting.
I don't know why the Enclojure plugin for Netbeans isn't mentioned more. It provides an interactive development environment for Clojure in package that is much easier to digest for anyone who is familiar with an IDE.
Also you don't code a website from a REPL, you need a proper developpement environnement, some way to manage your website dependencies, etc.. well, theses issues have been covered in lengths these last days, in a few articles, and the clojure people are well aware of it, and working on it, but for having done a serious website in clojure , let me say it's nowhere as automated or simple as setting up a LAMP server.
I've built websites in PHP, Python, Common Lisp, and RXML/Pike. Some have been very small, and some have been medium-sized. I currently work on a several-hundred-thousand-line PHP codebase, and I don't think being in PHP has been a serious problem for it.
I do agree that language infrastructure is more important for small projects, and language power is more important for large projects. I think it's critical to provide good language infrastructure precisely because of this, though, since virtually everyone starts out learning a language with a small project! It's really easy to bounce off of CL, when you're first starting out, as easily demonstrated by a survey of c.l.l (at least, when I paid attention there 2003-2007), and it's not because of the language itself; it's because the infrastructure is (was?) severely lacking.
I think it's harder to build a good infrastructure with a more powerful language, ironically, because the power substitutes for things that would otherwise be infrastructure-related, and once you've learned enough of the language to work on infrastructure, you no longer care so much.
sometimes i feel lisp is like an exercise in barrier of entry. "Let's make an awesome language that is as inaccessible out of the box as possible" not just application wise. knowledge wise too.
It's unfortunate that people advocating Lisp also advocate Emacs+Slime as the only option (although it is a good option).
This is disastrously bad advice. This is how to create parentheses-phobia.
PHP is ridiculously easy to get started with. I believe it was the first 'real' language and ecosystem that I really knew well [enough]. There's a huge body of knowledge associated with it that you can find on the web or in the bookstore.
PHP is ridiculously easy to grok because it's in the C family when it comes to syntax. PHP essentially enforces no control over the style you must employ while using it and doesn't even suggest a style to use. I made some awesome stuff in PHP but the code behind it was terrible.
Contrast this all with Lisp (which I'm still learning). I've never tried to do web dev with Common Lisp or anything, but getting started with Compojure was comparatively much harder than it was with PHP. Lisp is conceptually more complex than PHP. You have to think at a higher level. It becomes easier but I definitely could not have grasped it at 12 or 13. Lisp isn't purely functional but afaik (from what I've seen), but it encourages a functional style. It's not as easy to grok as PHP and so I would imagine this creates a barrier for most 'code monkeys'. Why learn to use a new tool when the one you got ain't broken?
Yes, Racket is Scheme, but it's much more practical than a vanilla R6RS implementation, and it packs a lot of libraries, tool support, and clear and simple end-user documentation, exactly the kinds of things that people mean when they say 'user-friendly'
What, specifically, makes PHP easier to pick up than Racket? Everyone I know who got started with PHP took an off-the-shelf lamp installation and started spitting out simple webpages. By that measure, Racket is at least as easy - download it, and you have a webserver, templating language, and a package manager with plenty of database toolkits.
If you're simply saying that PHP doesn't burden a noob with features like macros and continuations: You can write Racket code that's just as stupid as what you have to write in PHP, but unlike PHP, once you've gotten over the learning hump, there's a nice language waiting for you on the other side.
How about Ruby/ + Sinatra or Rails, or Python + Django or Pylons?
btw, take the arc, add a buzzword (llvm) and easy api to write extensions with fast FFI, and it will get as much hype as clojure - llvm is better buzzword than jvm ^_^