The regex version is indeed slower, 5-20x depending on the length of the string and the location of the uppercase character, etc.
> It does do the job of showing that simple (and by inference (?) not so simple)
> algorithms can be more succinctly expressed in Clojure than in Java. (not that
> that is particularly difficult)
My point was not that Java is/can be as concise as Clojure (or Ruby or Python or some other version of Java or whatever) but that if you are focusing on comparing things, don't use examples that are so easy to write off. It is not clear to me, as a person experienced with Java but not with Clojure, that the Clojure method deals with many types of character sequences, nor is it clear to me that it's faster or slower than a regex match. If the argument solely lies on lines of code, my mind will think "is he comparing code optimized for performance from one language to code optimized for conciceness from another?" Is that ability to traverse sequences some bona-fide intelligence on the languages part or just a mess of instanceof expressions that really only work for a few expressions?
This just struck me because I've been evaluating a lot of languages lately (Clojure is up soon) and it's frustrating to wade through people talking about languages using examples that are ignorant of all but their own, or contrived solely to make a point. Demonstrate the language in how powerful it is, how efficiently it runs, how gracefully it handles errors, how many lines of code it takes to solve specific problems, not standard utility ones that could easily be tucked into some library somewhere and it doesn't really matter if its 2 lines or 20.
I don't know, that is a lot to ask. You yourself state that you can't understand this example in Clojure, which as you admit is almost trivially simple. Again, I'm 99% positive the Clojure as written is exactly equivalent to the full Java versions, so he really couldn't be clearer on this particular example.
It is a hard task in the end as an author, to come up with an example that CAN be understood by someone who likely only knows one of the languages talked about, yet still provide some comparison. I think he deserves some credit in that he does try to make them exactly the same code (probably very similar bytecode even), just expressed in that language.
To your contrived point, I would say running through the elements in a list and operating on them is far from contrived, rather it is one of the most common operations we do day to day. That Java is particularly verbose about that isn't the fault of Clojure.
To keep this constructive, what piece of Java code / functionality would you use as an example?
Well, it's asking more, but not necessary a lot, especially in term of the thorough job this particular author did in the remainder of the article.
Running through elements in a list is obviously common, but that's not what was done here, he was checking for a particular validation that just so happens to have been easy in Clojure and messy in Java.
Here's an example that I think is a little more realistic, but not so complicated that it requires a lot of work. It doesn't use anything outside of the standard SDK, and yet it illustrates some i/o, data structures, error handling and return values, and useful logging, all in a pretty small amount of code that you could definitely see in a real project:
This is clearly not Java at it's best, the finally block shows how some basic scoping can get verbose, and the nested try/catch isn't great, but it's tough to improve it without refactoring some of the messy bits out, which would really only help with organization, not verbosity.
26 lines. I expect Clojure or most other languages to do it in fewer lines, but I'd be surprised if they can do it in half and still account for the requirements. My overall point here is that you could probably read a file into a list in some languages in a couple of lines, but when you start adding some reality in, they pack on some pounds.
If someone wants to prove me wrong, please do, you might have a convert :)
I think the biggest advantage of Clojure over Java for code like this is how easy it is to use lazy sequences and higher-order functions.
In this example there isn't much to be gained in the error-handling and logging; however, if there were other similar functions it might be easier to factor out some of the common patterns in Clojure, since functions like the predicate to ignore a line can be easily passed through. Or, for example, you could write a custom version of with-open or line-seq to do the desired logging behind-the-scenes.
Thanks, that's a very helpful illustration and gives a good idea of where it ends up. It's actually more readable than most of the other examples I've seen which I think err on the side of being too simple or too clever.
It will be shorter, maybe not by half. But keep in mind that the "reality" you are talking about is in some aspects an artifact of the language in which the rest of the software system has been constructed. For instance, some edge cases (such as special treatment of nulls, some exceptions) happen to be less important in Clojure and other "Java.next()" languages.
I do hope someone will post an equivalent Clojure program. Unfortunately, my knowledge of Java is limited, and I have not touched Clojure in many months now, so cannot do it myself. Sorry.
This just struck me because I've been evaluating a lot of languages lately (Clojure is up soon) and it's frustrating to wade through people talking about languages using examples that are ignorant of all but their own, or contrived solely to make a point. Demonstrate the language in how powerful it is, how efficiently it runs, how gracefully it handles errors, how many lines of code it takes to solve specific problems, not standard utility ones that could easily be tucked into some library somewhere and it doesn't really matter if its 2 lines or 20.