So here's another post in a great series that so far featured Ruby, Ocaml and various other things. So now the list of things that suck about Scheme, as defined in R5RS standard. You may want to take a look at the standard, because it's reasonably short and well-written compared to average standard.
- No support for such basic data types as arrays (vectors are not resizable, so they don't count), and hash tables/dictionaries. Most programs need both, and in Scheme one needs to either reimplement them in every program or hack around this lack. Compare with handling of numerical types, which are overspecified far beyond needs of typical program.
- The standard has horribly complex support for numeric types. Vast majority of programs require a single numeric type - bignum. Significant minority of programs require a second numeric type - hardware-native (typically IEEE754 double precission) floating point numbers. Number of programs that use rationals or complex numbers or the rest of the extremely complex type scheme is within statistical error equal to zero. I'd guess that regular expressions, XML handling, or POSIX file system operations are all >100x more common than those weird types, and resizable arrays and hash tables/dictionaries are like >1000x more common. One would think that the number system is at least any good if it takes significant portion of the standard ? Actually it sucks, it's impossible to easily extend it to add support for your own types (like vectors or matrices). In the end - huge loss.
- Character type is totally broken. What a character really is is a very short string. If we use Unicode (and we do use Unicode), a string is a series of code points. Now the characters are one or more codepoints. For example U+0041 code point is simply Latin Capital Letter "A", but U+0065 U+0301 together make a single character Small Latin Letter "e" with Acute Accent (é). So no - code point is not a character. And Scheme explicitly prohibits implementing characters as strings - they are explicitly required to be separate types. This is totally broken. Most language suck at Unicode support in implementation level, but Scheme managed to do that at standard level. I know it's older than Unicode, but back thern i18n issues existed.
- Scheme is not even minimally object oriented. So no generic comparisons (> a b), no shalow copy operator (dup x), no type queries (is_a? a 'blob). Half of that functionality is hacked in highly inelegant way, so you can ask objects whether they're strings by (string? x), but this is a new hack for every type. Goo gets it right.
- Multiple value return. This is the semantic equivalent of Sam the ugliest dog. Functions can return (values 1 2) instead of (list 1 2) and then you can do some magic to get the extra values back. It was probably marginally faster than using lists/tuples/arrays to return multiple values. Oh yeah, assembly performance hacks and let's screw the semantics.
- Highly excessive indentation levels. Compare Scheme:
(define veclen (lambda (x y) (let ((x2 (* x x)) (y2 (* y y))) (let ((z2 (+ x2 y2))) (sqrt z2) ) ) ) )
- with RLisp:
You can be a Lisp without such excess (it seems that Arc is also saner here). Oh yeah, and there are let* and letrec to confuse everyone (Ocaml has the same problem with let rec) .
(defun veclen (x y) (let x2 (* x x)) (let y2 (* x x)) (let z2 (+ x2 y2)) (sqrt z2) )
- Macro system seems harder to use and less powerful compared to Common Lisp's and RLisp's. But in the real life, all implementations of Scheme seem to provide "real" macros.
- car/cdr/lambda - come on, just throw away the historical garbage. The only true names are hd/tl/fn.