I actually have very similar thoughts on clojure versus racket. I admire both languges for different reasons, but if I were to pick one to get the job done it would be Clojure. I cry every time I see the idiomatic construct in any Scheme of converting a vector or string into a list just so you can do the normal core operations on it, and then converting it back to a vector or string, but this kind of code is quite common due to the design of almost every Lisp.
Another issue I have with racket, which the article touched on a little, is the overall lack of cohesion between different libraries and language features. I believe this is an unfortunate consequence of starting out with such a simple core language as all Scheme's do. Everything that is built has a different style to it and doesn't necessarily interoperate well with other parts of the language.
For example, structures are entirely orthogonal to objects and the class and interface system are entirely orthogonal to units, even though these two pairs of features can heavily overlap in their use cases.
When it comes down to it, if I want to get something done in Clojure I feel like I have a clear path as to how to go about it, but in Racket it seems much easier to get lost inside the language for the reasons mentioned in the article.
> this kind of code is quite common due to the design of almost every Lisp
Scheme != Lisp (maybe a "lisp")
I was trying to figure out what you mean from a Common Lisp perspective. Are you referring to the author's example?
All of Clojure's collections can be treated as if they
were a list, and you can write algorithms to traverse
them using the same pattern of empty?/first/rest that
you'd use on a list. This means that all the powerful
higher-order functions like map/filter/reduce work just
as well on a vector as a list.
Just off the top of my head, CL's map and reduce can operate on lists or vectors. Pretty much anywhere you see the word "sequence" in the spec, you can work with a vector or a list (and several other types). I can understand the point that it might be awkward in Racket; does it get awkward in CL?
I cannot speak for Racket/Scheme's limitations, but I am looking to see where Clojure might be a better choice for me than CL other than interoperability with Java. I have not seen a good data structures argument yet.
CL ostensibly comes with a built-in sequence class. The problem is none of the various utility methods that are included are generic functions, so in practice it doesn't do much good. Christophe Rhodes worked on an extensible sequence standard:
In summary: CL comes with some nicer datastructures than Scheme (hash tables, multidimensional and adjustable arrays), but other than that it has the same problems.
My takeaway for this is this -- If the utility methods are not generic functions, it is fairly trivial to write a generic function that wraps around the utility method and then play with additional types as needed. So if the problem with the data structures in scheme and Lisp are that people are spending a whole lot of time repeating conversion patterns, shouldn't those people be developing abstractions, at least for their own use/libraries?
When I read this kind of complaint, I get the feeling people tend to want Batteries Included Their Way. They do not go the one step further to wrap things in the manner they desire. Like-minded folks do not get the benefit of those wrappers. jQuery was a hit because someone deployed his library of common JavaScript patterns.
The problem is that any time you want to interface to code outside of that library, you run into the same "convert vector to list" problem the OP was talking about. The solution really is to cram down Rhodes' proposal into every implementation's throat, so that all existing code can start handling new sequence types.
Another issue I have with racket, which the article touched on a little, is the overall lack of cohesion between different libraries and language features. I believe this is an unfortunate consequence of starting out with such a simple core language as all Scheme's do. Everything that is built has a different style to it and doesn't necessarily interoperate well with other parts of the language.
For example, structures are entirely orthogonal to objects and the class and interface system are entirely orthogonal to units, even though these two pairs of features can heavily overlap in their use cases.
When it comes down to it, if I want to get something done in Clojure I feel like I have a clear path as to how to go about it, but in Racket it seems much easier to get lost inside the language for the reasons mentioned in the article.