Hacker News new | past | comments | ask | show | jobs | submit login
Clojure: 1, Common Lisp: 0 (briancarper.net)
112 points by mqt on Jan 19, 2009 | hide | past | favorite | 68 comments



Being on top of the JVM is also one of the really nice things about Rhino (Mozilla's JVM based JavaScript interpreter: http://www.mozilla.org/rhino/). You have access to a zillion Java libraries. Taking two of their examples:

MySQL:

    var conn = java.sql.DriverManager.getConnection("jdbc:mysql://"+host+"/"+db+"?user="+user+"&password="+password),
        statement = conn.createStatement(),
        resultset = statement.executeQuery("SELECT * FROM test");
        // do stuff!

Jetty also works from Rhino:

    var server = new Packages.org.mortbay.jetty.Server(8080);

    server.setHandler(new Packages.org.mortbay.jetty.handler.AbstractHandler({
        handle: function(target, request, response, dispatch){
            // do stuff!
            request.setHandled(true);
        }
    }));
    server.start();
Obviously these could be wrapped up in more JavaScripty libraries, but all the hard work is done for you.


for more javascripty DB/server stuff http://dev.helma.org/ is (though relatively unknown) the premier (kinda) server side javascript library/framework,


There's a lot of monolithic server side JavaScript packages like Helma, but I want something more modular. Also, Helma is written in mostly Java I believe, rather than JavaScript, which is ok if you don't want to hack on Helma itself (or if you know and like Java), but I'd rather have an all (or at least mostly) JavaScript solution.

Anyway, I started working on part of a solution for this: Jack (http://github.com/tlrobinson/jack), which is like Rack (http://rack.rubyforge.org) but for JavaScript.

If you don't know, Rack/Jack are like bridges between webservers and Ruby/JavaScript web apps/frameworks, so framework/app devs don't need to worry about what server they're using, they just write to the Rack API. It also includes "middleware" which lets you pre and post process requests, which allows for neat things like intercepting some requests and serving static files, or gzipping responses, etc (in a server agnostic way)

Right now it only works with Rhino+Jetty but ideally it will work with a number of JavaScript interpreters and webservers.

It also includes a Sinatra-like routing framework (called Roundabout), which lets you define routes like

    GET("/user/{username}", function() {
        var user = this.wildcards["username"];
        // do stuff!
        return resulting_html;
    }
Jack and Roundabout, combined with your other frameworks of choice, like ActiveRecord.js (http://activerecordjs.org/) make a pretty good solution, I think.


This guy is just rambling about CL and writing about his inability. I never had problems with SBCL on any machine, runs on my VPS, with threading, like a charm. Also, noone forced him to learn and use Emacs. There are Vim modes or CUPS for Eclipse. Destructive functions are the language's feature. If not sure, just use non-destructive. It's also not CL's fault he doesn't understand macros and can't use CL-WHO.

I like Clojure, but I like CL better. One guy's incompetence learning CL doesn't mean Clojure wins.


This attitude ("It's good enough for me, I don't care anymore about the learning curve's steepness, and I'm indifferent/enthused that my language is only accessible to a tiny minority") captures the CL spirit quite well. It also explains why you have to do so much wheel reinvention when you code in CL: those lower lifeform coders, who you openly despise, produce working, ready-to-use libs for most common tasks on JVM, not for CL dialects. Up to you to reimplement your superior libs in your superior language for your superior self.

CL is the perfect language for those who consider that development is not a social activity, and luckily for you, there are a couple of niches where this remains a sustainable delusion. For now. Meanwhile, Clojure carries on the Lisp heritage in the branch of software development that's not going to get extinct soon.


I don't have that attitude and I'm sorry if you encountered it (it's true the Lisp community could be friendlier, warmer to newcomers). However, what can a I (or any other Lisp programmer for that matter) do about the steep learning cure you mention? You have to try for yourself to learn the language, noone's going to do it for you.


what can a I

Create a simple working installer for the major OS's that includes a useful IDE, Database connectivity to least one major database and a fully functional web server. Once this is working get some people to write a standard library for date / time functions, file IO, formatting output etc.

Never underestimate how difficult it is for a new user to setup a working environment.


For OS X, Ready Lisp is the closest I have seen to what you describe.

http://www.newartisans.com/blog/ready-lisp.html

It's Aquamacs combined with SBCL, some documentation, and some should-be-standard CL libraries. Double click and it immediately takes you into a REPL. Aquamacs recognizes most of the usual Mac key bindings, making the Emacs curve not quite so steep.


The closest thing at the moment would probably be Lispbox (http://gigamonkeys.com/book/lispbox/) altough it's a bit outdated, so you'd be better with directly downloading SBCL (http://www.sbcl.org/platform-table.html). Use cl-build (http://common-lisp.net/project/clbuild/) for to ease library download. and install. I guess it's too complicated for a newcomer, but there's no easier way atm, sorry.


That's my point, you could fix this.


I get that. I'll definitely consider it. It's on my list of open-source side projects.


Lispbox is a good idea. Target Windows if you can. Setting up Clojure with Emacs on Windows involved a lot of steps and arcane stuff, but now there's a Clojure Box which makes things a lot more pleasant.

I've tried SBCL with the Eclipse plugin and it's been a huge PITA. IIRC, I couldn't get libraries to install when I finally gave up. It may have improved since, but I'm not sure. Of course the fact that many cool-sounding CL libraries had defunct websites and inaccessible CVS repos didn't exactly encourage me...


"Create a simple working installer for the major OS's that includes a useful IDE, Database connectivity to least one major database and a fully functional web server..."

I'm just learning and my conclusion (by elimination :-)) is that for Windows the best is to use Emacs + SLIME + SBCL. There is an installation guide here: http://robert.zubek.net/blog/2008/04/09/sbcl-emacs-windows-v...

In the comments there are instructions to get ASDF working, that I haven't tried yet.

I've tried to avoid Emacs, but it seems impossible. Lisp in a Box has a lot of problems, ABLE has still too many bugs and Corman lacks GUI programming without which I can't justify the price. CUSP also has too many bugs. So I'm surrendering and looking at Emacs.

For the web server part, just use good old CGIs.


I think CL is suitable for projects which are fluid and have a very few people working on them. Speaking from personal experience 1 person can get an awful lot done in CL, very quickly. Compared to any other scripting language. I've worked with CL, Python and Ruby. There are certain things that I think are impossible to write in Python.

I started by writing a domain-specific crawler which extracted certain information from a bunch of sites. But the sites I was crawling changed their design mid way. So I then ended up writing a program in CL, to which I describe the data that the site has. E.g. Name-of-city is "Edinburgh", Address is '15 Market Place, ED12', First-Movie-name is 'Bend it like Beckham', First-showing-date is '15 Jan', First-showing-time is '14:20'. The program then produces a function which when give a page from this website extracts this information in the form of an alist so that it can be pushed into the database.

Funnily enough the my site which shows this data runs on django.


"I never had problems with SBCL on any machine"

I did, and so did this author.

So who's anecdote wins?


Reddit was initially built on CMUCL on FreeBSD. Here is what Steve Huffman said on why they switched to python one weekend.

"The biggest trouble that plagued us was that we could never quite get Lisp reddit stable enough to sleep at night. There were weird threading issues that would bring the site to its knees a couple times a day and required constant monitoring."

You can read more of it in this blog entry.

http://www.findinglisp.com/blog/2005/12/reddit-and-lisp-psyc...

Edit: Corrected :-)


Reddit wasn't built on SBCL, which you would know if you had read the blog entry you linked to.


I used CMUCL a bit, and SBCL almost never. Does SBCL really deliver on what it set out to do? Is it better, faster, more portable? As far as I know, the Windows port never matured. Which of the two do people recommend using?


SBCL set out to make a version of CMUCL that was easier to build and maintain. I'm pretty sure that was delivered.

But of course that's not of much interest to the average user. I think SBCL is in general faster, is developed more actively, has more features that are relevant in the modern world (eg. lose a Motif interface, gain native threads), and currently runs on more platforms than CMUCL does.

My impression is that most people using CMUCL are ones who started using it 10 years ago and are comfortable with it, new users would tend to go with SBCL. But I'm biased, so it's quite possible that there are real and substantial reasons to prefer CMUCL.


_...the Windows port never matured_

I was subscribed to SBCL list some months ago. I could see that Windows port was quickly progressing. "Never matured" suggest a project that was tried and later abandoned. It seems more of an ongoing effort. Versions are still being created regularly. I would try in a few months.


They would have had fewer issues with sbcl on linux.


As did I. In my case, the problem was running it on a VPS that had no user-visible swap, no way to add swap space and possibly some other memory-related oddities that I don't remember. The workaround ended up being to limit SBCL's memory usage with --dynamic-space-size.


Noone's. The point is it's not a valid argument. The sameway the author had problems deploying SBCL on his machine, I could have problems deploying JVM on mine.


I'm going to have to disagree with you here. You rarely hear about people having issues getting the JVM set up on a random machine. On the other hand, deployment of SBCL is a complaint you hear somewhat regularly from people using shared hosting.

It's not necessarily a fault of SBCL, as much as it is a function of Java's popularity. But to say they equally share deployment problems seems a bit misguided to me.


Yeah, you are probably right. Because of Java's popularity and high demand, hosting providers have to be Java-ready and nowadays, it's not a problem.

However, it seems I've been living in a cave. Besides the Reddit case, I haven't heard (or at least can't remember) about problems running a CL environment. Can people who had this problem please reply - what disto, what implementation, what was the issue?


My experience trying to move some code from SBCL/OS X to a particular version of Linux is partially documented here.

http://groups.google.com/group/comp.lang.lisp/msg/0450136edf...

The use case was a final class project, where the instructor needed to be able to run the final version of the program just by executing a script in an unpacked tar file. Couldn't get SBCL to run with the limited time I spent on it. Got CMUCL to run, but not in a way that could be deployed in a self installing manner. Punted and used Java (was easier to work with team members that way, too).

Clojure would have been perfect.


I've had a lot of issues with JVM in a cheap hosting with Virtuozzo (a VPS). I assume people that are using Java choose a provider that gives it preinstalled.


For anyone interested in the Eclipse plugin, it is CUSP: http://www.bitfauna.com/projects/cusp/


This might be a good experiment, but the examples seem a bit flimsy to me.

For example - Whilst it may well be better from his experience, Timestamp has always been an anomaly in Java (it doesn't necessarily play nicely with Date)....

Equally I've never found browsing the filesystem that superb in Java - in fact the whole FileFilter, FilenameFilter thing can be quite clunky to use... It's one area where I've never felt more than a smidgen away from C (even moreso now with the NIO library).

So - maybe better, certainly not perfect - Either way they didn't on the weight of it seem killer arguments.


I'm going to make a different kind of statement here. Something that I've learnt from my CL experience.

When I think about solving a problem by writing new software, I ask myself, is a run of a mill problem like a website which serves data, or making use of a bunch of libraries to do something. Then use rails/django, I use django/python.

If I don't know what the solution will look like and I don't think I'm going to need existing libraries. I'll use CL everytime.

Horses for courses. Nails and hammmers.


His shiny new Clojure powered site is down for me...

"The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later."

http://origamigallery.net/


Between being posted here and on reddit, I'm sure he's getting much more traffic than his host is accustomed to.


Curiously, the server appears to be Apache rather than Jetty.


It is common to have Apache as your static web server to serve images/css/js files and use modules such as mod_rewrite or mod_jk to route to your dynamic context. It seems like his dynamic content server is down (could be the jetty server he was referring to), hence the 503 error code.


Would the same Clojure advantages apply to Armed Bear CL which also runs on the JVM?


Not in my opinion.

Using Java libraries from Clojure is very simple e.g. (.substring "abcd" 2 3) ==> "c".

Armed Bear on the other hand requires a lot more scaffolding code to make a Java call (you have to get the class, find the method and then call it).


In Lisp one has the freedom to code in Structured Programming, OOP, AOP, FP, meta programming, or create his own DSL.

Does the same stand true for Clojure?

I am thinking about switching. Only risk is that if it doesn't work, I can't port the code anywhere else, because it's so different from CL.


Clojure is a Lisp, so you get all the usual things like first class functions and macros. Clojure leans toward FP philosophically, so all the built in data structures are immutable. Concurrency support is generally very good, and it has some useful syntax sugar for vectors and maps.

I prefer Clojure over all the other Lisps I've tried, but YMMV.


Good. Only thing missing in Clojure seems OOP. But I can live without that.

Hope Clojure doesn't push the FP thing too far. Pure functional languages are evil. In broad sense, pure anything in evil. Look what Java turned into trying to be a pure (or too much of an) object oriented language.

It’s multi paradigm that wins. Giving programmers freedom on how he wants to code any specific set of problem.


Clojure supports OOP in the same style as Common Lisp.

http://clojure.org/multimethods

The integration with Java is almost seamless, so of course you can also use Java-style OOP if you're feeling masochistic :-P

Clojure is definitely not pushing FP too hard. It was designed to be especially supportive of FP, but it is definitely a multi-paradigm language.


Another Java-style construct: Clojure has a do form, which enables you to consecutively execute the following expressions in the list.

It seems to me a way to sneak statements into the language. Or does lisp have something like that as well?


I believe that common lisp's prog1 and progn both do this.


It's pretty realist, it even has a doseq especially for side-effects iterations. It's not that it forces you to be FP (it can't, you can always run java methods), it's that it makes the advantages obvious and lets you decide.

It is my first contact with FP, but what I find incredibly cool is the way the data structures are transparently persistent. If it's true this is a rarity in functional languages, I can't imagine using another one.


I'm curious, what do you mean by "transparently persistent"? Do you mean that you can serialize anything (and so persist it as a file or what have you)?


Uh.. I know it's been 10 days :p

Let's say you have a map, and you change a value in it. Being a functional programming language, and the map being an immutable structure, you end up with two maps: the old and the new. Now, the cool part is every data-structure in clojure is designed _not_ to do this by copying the whole thing. You'll have two maps who share everything except the changed value. Same with collections, sets, trees etc. The work under the hood must be impressive...

Another nice thing (for me at least, coming from imperative programming) is there is a better difference between a variable and a value. A variable is a placeholder, and a value is ... well, a value. In clojure you treat them separately. A better explanation: http://clojure.org/state


Persistent in this case means that if FOO has value '((2 3) 4) and someone does (CONS 1 FOO) => '(1 (2 3) 4); the value of FOO does not change, but the new list shares its structure.


If you do a cons cell diagram for this it will make perfect sense.


I believe 'do' is found in the majority of Lisp dialects.


Yes, but it looks like Clojure's do is not the same thing. Lisp's do is for iteration, while Clojure's do seems to be the same as progn in Lisp.


Ah, my mistake.


I came across this http://en.wikibooks.org/wiki/Clojure_Programming/Tutorials_a... which seems to confirm progn ~ do

I'm just surprised that (it seems) you can do statement-based code in lisp. I thought it all had to be expressions. This feels like cheating. BTW: I can see that progn/do syntactically produce expressions, but the value of all but the last one are thrown away - similar to python in that respect. This seems against the spirit of expressions.


"I thought it all had to be expressions."

This is a common misconception. You are thinking of pure functional programming, not Lisp. Certainly a lot of Lisp programmers, myself included, prefer functional programming. Scheme, especially, leans toward functional programming. Haskell, not Lisp, is rightly known for embracing functional to the exclusion of all other paradigms.

What really stands out about Lisp is support for ALL paradigms, even those that haven't yet been invented. Lisp is an extensible language, that can be changed to fit your needs. Features that would require language extensions in other programming languages can be implemented as ordinary libraries in Lisp. Lisp was the language that allowed experimentation with new paradigms like functional programming, object-oriented programming, and logic programming long before more specialized languages (Haskell, Smalltalk, Prolog) were created to provide specific support for these paradigms.


I agree except that Clojure is specifically intended to be used functional, and not as OO. Clojure is not pure FP as it does allow state changes (in a controlled way), but that's an acknowledgement that state changes are useful and purity can be, I'll say, difficult. The way Java's OO embraces state changes is not the same principle, and makes things more difficult. OO style is possible in Clojure, but that's not what the language is meant for.


This is not cheating. Nothing surprising here.

Of course you can do statement-based code, like in any language that supports I/O(Haskell included).

That's a hard fact and it isn't what functional programming is about.


Not sure what your point about Java is since it doesn't seem to be either very evil or a very pure OO language.


Everything is in a class. Everything. Even poor little printf or the main function.


Although Java puts everything in an class, not everything in Java is an object. For instance, you can't write:

    Package p = java.lang;
    Class x = p.String;
    x y = "Hello";
    Method z = y.substring;
    w = z(0, 5);


That's just the syntax failing to support such a nice way of accessing those objects. Packages, classes, and methods are objects.

Of course, primitives are not objects, but autoboxing helps.


Sure, they're represented as objects in the JVM, and you can access this via refection; but they're not treated as objects in Java's syntax. I'd argue that OOP is a property of a language's syntax, rather than how it is internally represented.


In a trivial setup it's pretty easy to get the jvm up and running, but making a good cached deploy of apache httpd fronting tomcat and a database server isn't very easy. It's not very easy to set up a server with rails either (easier these days but still a pain if you're a noob). I'm not sure how easy something deploys is critical for the value of a platform. Developers should understand how stuff are deployed but it's not necessary that they know how to do it correctly, nor should every developer deploy their own applications. (I mean, it doesn't hurt if they know how to do it, but it's better that developers spend their main time developing not minding the server farms).


Someone please compare Clojure to PLT Scheme.


PLT scheme is primarily used for education. Pedagogy is (or at least was) the project's central goal.

Clojure is a general purpose project. It is not specifically competing for that space.

I'm sure that the average student can get up and running with DrScheme/PLT faster than with Clojure, but I doubt anyone is going to write an angry article about that.


See, that's the common misconception with PLT. While it was built for education, it's really a nice full featured system for any use. Just use something other than the "Beginning Student" language.


I have to agree. I know CL quite well, and decided to have a look at scheme last week. I wrote a small (but useful) program with PLT and was rather impressed by the amount of library code available. Distributing the program as a small stand-alone executable to a friend was also incredibly simple. Also, I particularly liked the module system and wish CL had something similar.


It's also very elegant.


In one of the video lectures the author of Clojure seemed to claim that Clojure is as fast as Java. IME though that's not quite the case.


Clojure can be as fast as Java on benchmark-type code using type hints, Java interop and unchecked math. Idiomatic Clojure code will be slower on benchmarks. Operations on persistent data structures are slower than mutation. Reflection takes time.

Back in the real world, Clojure actually does pretty well for itself. As an example, it seems to be fairly common to generate collections of various types and then only use part of them. In Clojure, most of the time those collections would be lazy, saving computations every time the whole thing isn't needed. Also, using clojure.parallel, many operations can be parallelized trivially. I got a 50% speedup running a genetic algorithm on a dual-core machine just by changing a sort to psort.

Of course, hand-optimized Java may still be faster, but Clojure makes it easier.


From: http://news.ycombinator.com/item?id=395951

"Yes it [Common Lisp] does [look bloated]. It has at least 4 different ways to loop, 4 different types of arguments to functions, 5 or 6 different lets (functions, macros, let* , normal let, ...), 3 or 4 different kinds of variables (with no unifying underlying theme), and at least 3 different flow models (the nested lists, tagbodies, loops with returns, etc...). That is exactly the same problem with C++. Instead of finding unifying abstractions which give the same functionality with 1 idea, they have chosen to add in multiple specific quick fixes to the language. They have chosen to amend the language with a thousand small changes, each suited to its own little use case, and have ended up with a monster of a standard that takes up 15 megabytes in 2300 files with 110,000 hyperlinks. Thats 15 mega bytes mostly of text.

Scheme is a lot better but its going the way of CL, slowly but surely."

Thats exactly what we are seeing here.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: