|
That just becomes a debate about the definition of a functional language. The point is that unlike Haskell, SML, and OCaml (the last two aren't "pure" in the sense of syntactically enforcing referential transparency like Haskell, but they strongly encourage a functional design), Racket is first and foremost a LISP. You can use it to write and make use of a lot of functional abstractions, and it certainly is better suited to that style of programming than C or Java is, but Python and Ruby are just about equally suited for that style of programming, and they even have equivalents of map, filter, fold, lambda, etc. Racket code doesn't look like Haskell, the MLs, or even dynamically typed "functional" languages (like Erlang). It looks like LISP. What drives your coding is not functional abstractions or object-oriented data structures (which it can do equally well) or anything like that. What drives your coding is the fact that syntax itself is a first-class data structure. You have access to the reader. You can write macros that adapt the language to anything you want. You can write a DSL in a few hundred lines that might save you tens of thousands of lines. Now, Racket is certainly good for functional programming. In fact, some Racket developers prefer the Scheme-style tail recursion method of iteration (via the named let or letrec) to the looping constructs provided in the library, even when for loops would be just as effective. In the same way, not all Common Lisp programmers like the loop macro, and some (e.g. pg) actually use Common Lisp in a style that resembles functional programming. However, don't think of Racket as a functional language. That's as misleading as calling C++ a procedural one, even though you could write all your code C-style without ever using objects. Racket is a LISP, which means it can be adapted to fit virtually any paradigm. Racket is far closer to Common Lisp and Clojure than it is to literally any non-LISP. |
Another point: yes, Racket programmers know and use tail-calls, but that has nothing to do with "the looping constructs provided in the library" since those are implemented in terms of the same facility. The existence of these loops is therefore not making the language any less functional than the fact that you can implement a while loop in Haskell. The bottom line is that Racket is as functional a language as the interpretation of the term was before Haskell kidnapped it and turned it into some religious point.
(BTW, if you want to bash lisps, do yourself a favor and drop the all-caps "LISP" -- it immediately demonstrates the kind of limited knowledge you have on it.)