I looked a few things up after Michael's post, and it seems there are a lot of resources and codified idioms around writing chess engines in C. (E.g. tons of bit-twiddling hacks, many related to the fortuitous existence of 64-bit integers. [Not that you can't do those in Haskell.])
Though I likely haven't completely understood each of the authors gripes, each problem to me seems to have a notable solution provided by Clojure (with the exception of tail-call optimization).
Clojure:
is compiled to JVM byte-code and is fast.
has a good parallelism story (parallel map, parallel fold, channels)
is almost completely backwards compatible.
has a sequence abstraction that leverages the same operations over many different types (string, vecctor, list, set, map, etc.).
has a standard compose function.
has reduce, map and filter in the standard library. Transducers (also first class) further extend their usefulness.
's closures allow statements and there's even sugar for annonymous functions.
has macros to reduce boilerpate.
has a conditional macro.
I'm sure this list isn't unique to Clojure but I'm most familiar with it.
All of the above is good except for transducers. They are a necessary hack in Clojure because the data is immutable running a large number of functions across changing data is rife with overhead in Clojure. So the hack is mutate the code many times, so you only have mutate the data once.
I see what you mean and although the definition of a from-scratch transducer looks a bit ugly to me, the idea of composing existing transducers together seems rather elegant.
I recommend Peter Attia's (currently unfinished) series, "The straight dope on cholesterol". He's a surgeon interested in health and fitness. http://eatingacademy.com/?s=cholesterol
Basically Tuesday was the weekly deploy day. Master got screwed up from both a code perspective (incorrect conflict resolution), and then my fixes to rewrite history messed things up even more, blocking the release. Basically I didn't understand how Git worked (and me nor anyone else at my company apparently knew about reflogs).
Well I wasn't scared of being fired for that one mistake. But I didn't want to make it again, because after the second time you've just shown yourself to be an ass. Most places I've worked at are like "we allow you to make mistakes, but not the same mistake twice."
I've heard it said that Clojure's macro system is most similar to Common Lisp's macro system and that Racket (and Scheme) style macros are more powerful. Can anyone compare the differing approaches?
It is more similar to CL's macro system in that it doesn't force you to write hygienic macros -- though I think CL's macro system is actually more powerful than Scheme's since it does let you write unhygienic macros.
Clojure doesn't allow user defined _reader macros_, which means it is less flexible than either CL or Scheme. Basically, you can't really define your own syntax parser in Clojure, you are limited to what the Clojure reader can already parse. In CL and Scheme you don't have this restriction.
Scheme has historically been used as a research vehicle for macros. When the fifth revised specification of Scheme (known as R5RS) was written there were no consensus on the best practices for writing a system supporting unhygienic macros.
Since then both R6RS and R7RS has support for unhygienic macros.
Note that there are two important properties of the macro systems of modern Scheme implementations: hygiene and referential transparency. The second property is often overlooked.
The standard syntax-rules macro system of R5RS Scheme is hygienic
If a macro transformer inserts a binding for an identifier (variable or keyword),
the identifier will in effect be renamed throughout
its scope to avoid conflicts with other identifiers.
and referentially transparent
If a macro transformer inserts a free reference to
an identifier, the reference refers to the binding
that was visible where the transformer was specified,
regardless of any local bindings that may surround
the use of the macro.
The first property (automatically renaming of identifiers) is
prevents common errors. This property is easy to hack around in macro systems without automatic renaming. The macro writer simply generates a new identifier (gensym) each time a new identifier is needed.
The second one referential transparency is the killer feature. Names inserted by a macro refers to binding where the macro is defined. This means that the macro writer has control over the meaning of the binding of identifiers in the expansion. In other words: a user of a macro can not by accident rebind or assign values to identifiers inserted by a macro use.
When referential transparency is not supported, then one must be careful to load libraries in the right order:
It seems to me that Apple has had a rich history of interesting languages: Squeak, Dylan, Hypertalk, AppleScript and Swift. Those are just the ones I know of.
Pedantic note: it was called Macintosh Common Lisp (MCL), not to be confused with MacLisp, which predates both Apple and Common Lisp and is from MIT's Project MAC.
I wrote this: http://freeconsignmentsoftware.com It's been on the first page of Google results for "consignment software" for several years now. I've also written a lot of production software for a variety of businesses. Rebol is still ridiculously productive for certain types of work. Maintaining old projects in Rebol is always simpler than with any other development tool/language I've used in 30+ years.