If only my successes were as successful as that failure. Back then, if you had a code base in C, migrating to C++ was easier than migrating to Smalltalk or Eiffel.
Similarly, today, migrating a C code base to C++ or and using its functional 'extensions' or starting to use those features in a C++ code base is easier than migrating it to Haskell or Scheme.
C++ is far from perfect, but it beat other contenders because of that feature.
And yes, if, as I expect, C++ remains popular, we will have books describing the pitfalls of functional-style programming (Stroustrup: "There are only two kinds of languages: the ones people complain about and the ones nobody uses"). For example, we will see blog posts lamenting the heavy nesting of map/apply/select chains because the resulting code, in some cases, will run out of instruction cache space, degrading performance.
It also failed in the sense that it didn't eliminate all competition.
Right. But until we have a comparable body of production software written in pure functional code -- and by comparable, I mean closer to the volume of code written in today's mainstream languages and by average developers, not a few applications written by elite developers -- we can't say for sure whether the pure functional approach does in fact prevent buggy software, or whether it simply leads to different kinds of bugs.
A lot of advocacy for functional programming and languages like Haskell makes claims about being safer because certain types of programmer error are prevented. However, relatively little commentary also highlights downsides like the need for accumulating parameters and strictness annotations just to achieve acceptable performance, or the maintenance hazards of having both monadic and non-monadic implementations of algorithms. Until someone finds a way to prove that a large-scale lazy functional program can't exceed the available system resources with an explosion of thunks, any claim that this approach is inherently safe seems rather premature.
So not sure where you are getting at.
In the vast majority of cases, it's about delivering customer value--whether through good, buggy, or nonexistent software.
A buggy language used to make buggy software beats a perfect solution every time if it gets you paid.
EDIT:
Downvote all you'd like; in the vast majority of cases the pain point of a customer getting solved is what matters, not how we solve it.
And of course this is a false dichotomy anyway.
And again, the question there is "Did Heartbleed keep people from getting value out of OpenSSL?". The answer is no, even if the value provided wasn't as advertised. It was more useful to have something--anything!--than nothing.
Arguably, though the limited sandboxes in wide deployment are sufficiently full of holes that most code provides some access to something that might be considered critical infrastructure.
'And again, the question there is "Did Heartbleed keep people from getting value out of OpenSSL?". The answer is no, even if the value provided wasn't as advertised. It was more useful to have something--anything!--than nothing.'
Possibly. Belief that you're secure when you aren't can quite definitely be much worse than no belief that you're secure, but I'm significantly less sure that Heartbleed moved many people from "sufficiently secure" to "insufficiently secure" in many individual cases (the possibility exists, I just lack the data to make any determination).
Also, for many use cases, there exist (and existed then, of course) alternatives that are probably more secure. If "nothing" meant using those instead it was quite a bit better to have "nothing".
You're falling for the trap of thinking that pursuing a theoretically pure discipline will result in a language with less flaws; in reality, even theoretically pure concepts have issues and can be superior and inferior to other theoretical concepts/constructs [which may or may not be invented later]. Pursuing one theoretical framework may make some issues either disappear or be invisible (like garbage collection makes the issue of memory management appear to disappear -- but it still has to be done at some level, and this causes new issues, as evidenced by many talks given and books written about how to deal with $LANGUAGEs garbage-collector) but that doesn't mean that you won't have issues remaining or even create new issues.
You call "Aversion to Extremes" a cognitive bias that doesn't work well in practice, but you should realize that the opposite is true; the more extreme a language pursues a theoretical concepts, the less used it typically ends up being in practice. For every success-story you can give me about Agda (pursues dependent typing), haskell (pursues functional purity) or smalltalk (pursues object-orientedness) I can give you a thousand success-stories of people using C++, java or C#.
I can't imagine that you will be able to come up with any measure of "how well something works in practice" that is remotely sensible and makes these "purity-oriented" languages appear to "work better in practice". The reality of programming is just that there are many different requirements one might have to a language and its implementation, and properties that are very clear advantages in a theoretical framework seldomly translate to practical benefits in a nontrivial way.
A nice example (IMO) of a language that pursues functional programming without attempting to be needlessly pure about it is erlang; each "process" itself is written in a functional language that promotes separation of side-effects and communication, but from a "further up" perspective, each process is like an object, holding onto state. That way it gains the [for erlang] important advantages of having functional traits, while not sacrificing flexibility through needlessly strictly adhering to the functional paradigm.
Yes, people use languages with solid theoretical foundations less because they perceive them to be extreme. That was my point.
Quote: "I can't imagine [... any measure that] makes these 'purity-oriented' languages appear to "work better in practice".
How about SLOC required to implement a task? Take a look at this: http://web.cecs.pdx.edu/~apt/cs457_2005/hudak-jones.pdf Its an old paper, but the findings are still perfectly valid.
Quote: "each process is like an object, holding onto state".
This is the actor model. Erlang is an uncompromisingly pure implementation of the actor model, which is why it is so effective. Again, I think you are making my case for me.
Your use of the term "sacrificing flexibility" sets up a false dichotomy between purity and flexibility, as though there were programs that are difficult to write in Haskell.
Measuring LOC required to implement a task is meaningless. If you implement a task in python in fewer LOCs than what I need in C, that doesn't necessarily mean anything, because my code might fit on an 8-bit microcontroller, run faster, ... or meet any other number of imaginary or real additional requirements I might think of (and people always have lots of those!) "Have 10% fewer lines of code" is pretty much never a given requirement, though.
Sure, erlang is a "uncompromisingly pure implementation of the actor model", but then python is an uncompromisingly pure implementation of the python model, and C is an uncompromisingly pure implementation of the C model, so that's hardly an interesting argument. Erlang is pretty much what popularized the actor model as we consider it nowadays in mainstream programming, so that's tautological.
The point (which you have not actually argued against) is that erlang is also a functional language, but not a pure one; it allows side-effects, it allows sending messages, it allows storing data in your (destructibly updatable) process dictionary, et cetera.
That means erlang benefits from the features it inherits from the functional languages, even though it doesn't go "full functional" in the sense some other languages do.
If you don't think there are programs that are difficult to write in haskell, agda, miranda, ML, ..., I have to doubt that you have done a substantial amount of them, and/or that you have applied it to any actual real-world task.
At some point it stops beings the people's problem and its a problem of the language?
Or do we know (by divine intuition?) that those languages are perfect, and we don't need any stinking reality to verify it?
It's not. To pick just the first issue I remember, PIDs are forgeable. (I spent a day once trying to survey what you'd have to do to capability-tame Erlang, and it looked like a lot of work. The Erlang developers did not wear a hair-shirt.)
C++ "failed"?
> the OO and functional features don't interact well
How don't they? Before C++ had lambdas, programmers would define a class with overloaded operator() and use that instead, every time. Now the language provides a way to easily generate the class with its members and constructor and operator() automatically - which is basically what functional languages turn lambdas into. You could make the same argument that "procedural and OO features don't interact well", but C programmers were (and still are) using structures and function pointers to accomplish much the same effects.
Same goes for a value of type Employee; if I might or might not have an Employee (for instance, if the lookup function doesn't find someone with that employee number) then I have to use Maybe Employee.
Scala has the same concept with (IIRC) the Option type. But Scala also inherits null references from Java. In Java a reference to an Employee might be an optional value (so null is allowed) or it might be a required value (so null is not allowed). Scala has to play well with Java so anything has to be allowed to be a null reference. Except that Integers in Java (and hence Scala) aren't references, so I can't have a null reference to an Integer.
So now my "Option Employee" might wind up being a null reference to the Option, or it might be an Option that is empty, or it might be an Option that contains a null reference to the Employee, or it might actually have an Employee in it.
Gahh.
The same is true of C++. Values and references in C++ can't be null. Pointers can be null, but that's a lower-level feature that doesn't have an equivalent in idiomatic Haskell.
In idiomatic Haskell, if you need something like a pointer you have several choices. If you're writing parallel code your best bet is STM. If you're writing code in IO, you can use an IORef. If you don't want that restriction, you can use an STRef.
(I'm aware that you probably know all this, but other people reading the thread might not.)
x,y::Integer
x = x + 1
y = undefined a,b::Integer
a = div 1 0
b = sum [1..]If you have a mutable object anywhere in your codebase, the compiler can not reuse calculated values, ignore unneeded code, or map a set of independent output sequences[1] at your source code into highly interleaved single threaded asynchronous output, like Haskell's green threads do.
[1] I'm yet to see an imperative language (and "mostly functional" is imperative) that has the concept of "output sequence", instead of "execution sequence", but I don't know enough to claim it's impossible.
Scheme is not a pure functional language, it's pretty far from it (see all the "something!" functions). Heck, it could even be argued that Haskell isn't given the existence of unsafePerformIO, though most people think of it as such. (Since unsafeXXX functions are generally vehemently discouraged in the Haskell community it's not really a problem that crops up in practice.)
I think OP wittily conflates 2 senses of pure. Scheme is purely functional in the sense that it's _only_ functional, as opposed to a hybrid like Scala, as OP points out.
But it's not purely functional in the sense of Haskell, that famous flagship of effect-less programming. Here 'pure' is contrasted against _effectful_ functions.
There's FP vs imperative and then there's FP vs OOP. Scala is the FP-OOP hybrid and Scheme is the FP-imperative hybrid.
These are vast simplifications but useful to start a conversation with. Thanks!
Unfortunately if you want a language with industrial strength tools and libraries that is pure in the effect-less sense, Haskell is the only choice. So when I try to talk about the issue of effect management it sounds like I'm merely plugging my favourite language instead of making an argument about the importance of a fundamental property.
There's also O'Haskell, and in regular Haskell you can get something like polymorphism (implemented under the hood with actual polymorphism) with forall-qualified datatypes.
It's not OO and functions that class... it's functions and state. There's (literally) no law of computer science that says objects and functions must clash.
Don't bother. Go straight to Haskell and just Haskell.
No excuses, no compromises, no mental backflips to justify not learning something new. Learn Haskell properly and then see for yourself why "hybrids" are a waste of time.
Hybridized approaches are like asking for a hole in your bathroom floor when you're being offered indoor plumbing with a porcelain toilet instead of an outhouse.
But let me do something you didn't do, which is to actually explain my position. Hybrid languages afford a flexibility and power not available to language puritans. It's very nice to have things first-class DSLs that don't rely on slow monad stacks, heterogeneous lists that don't rely on existential qualification, stateful programming that isn't a type system hack (do I really need to understand existential uninstantiated types to twiddle a bit in a vector?), first-class side-effects without monad stack weirdness (unsafe escapes don't count), Turing-complete macros at load time, inheritance and class qualification that isn't crippling and/or dependent on weird compiler extensions... In the course of learning Haskell I find myself banging my head against a type-system wall to do something that would be trivial in Clojure or Scala.
Now I like Haskell, but Clojure and even Scala offer very flexible and powerful defaults together with programming escape hatches anywhere you want them. This is very powerful. It's not clear how to have a similar in a strongly typed strict language. Monads and weird compiler extensions don't cut it.
You can easily, easily spend more time debating it - learning nothing - than you would just checking it out for yourself.
If you were banging your head against the wall, you were suffering from bad pedagogy, not a bad language.
I went through the same experience! I know exactly what you're talking about, but you don't know what you're missing!
So lets stop debating and instead focus on fixing the pedagogy. You won't regret it.
Try this course: http://www.seas.upenn.edu/~cis194/lectures.html
Ping me via my email if you need help.
Why are you talking to me about Applicatives? Applicatives are easy. I'm not complaining about what the type system can do. I'm complaining about what it can't do. And it can't do a lot. For instance, it can't "safely" twiddle a bit in a vector without resorting to a compiler trick involving uninstantiable existentially typed monads. It can't produce DSLs that live outside the type straitjacket, so you get really complicated stuff, like the kudzu-like system of the Lens library, full of existential types and higher-rank types and restrictions, that still is not actually typesafe. And so on. I'm repeating myself already.
Monads and weird compiler extensions are not the same as a language that respects the programmer who wants to do something unusual. This is what I'm saying. Don't tell me about applicatives as a response. It's not a response, and it's insulting.
When you say "uninstantiable existentially typed monads" you're showing off your knowledge and being verbose when you actually mean "ST". There's no actual problem here, you're using big words to seem impressive despite the fact that by being obscure you're condescending to them and to me. ST works the way it does so you can't accidentally leak mutable references. There's nothing particularly limiting about it beyond that. ST is like a generic transients that works for any data type instead of the blessed ones.
You don't need to care that ST is existentially typed in order to use it at all. That's like complaining about how difficult it is to weld steel so you live in a mud hut instead. Division of labor applies here because abstractions and types work in Haskell.
There's nothing wrong with twiddling bits in Haskell. I do it all the time. You're complaining that the type system won't let you lie to your users and say a side effect is
a -> ()
-- instead of
a -> IO ()
I happen to think knowing which functions are pure and which are actions is a plus."Can't produce DSLs that live outside the type straitjacket" What? You can build a DSL on hash-maps and symbols in Haskell the same as Clojure users do. Haskell users don't do that because it sucks. ADTs and free monads are nicer.
Name-dropping lens as if it's a negative to Haskell is nuts. You're not obligated to use lens if you're still learning Haskell, but finding it difficult to use is a sign you miscalculated your knowledge.
The foundational building block of writing one's first lens is scrubbing out the (fmap . fmap) pattern, which is a use-case even Clojurians can relate to. There's no "there" there to complain about.
Your library 'clearley' would be easier to understand if it had types.
Have you considered a book like Joy of Clojure? http://www.manning.com/fogus2/ I found the first edition of Joy of Clojure improved and clarified my Clojure. Also, back off the defprotocol/defrecord in Clojure until your design is cleaner and more firmed up.
You're not here to be learn or share anything so I'm backing out of the conversation. Provided some clarity on the obtusity before parting.
tl;dr nonsense, intentionally obscure appeals to things that are "too complicated" which are comparable to refusing to drive a car you couldn't build yourself.
You can learn how to build the car later after you understand why it was engineered that way.
They have hijacked every sane discussion about programming into a condescending -- "Do you have monads and typeclasses ?".
It's absolutely unhealthy.
State is not Evil.
Languages like clojure, scheme take imperative features and give it more beautiful abstractions.
In what profession, do you find people complaining about the very foundations and thinking it's cool ? It's like Musicians saying Rhythm is stupid.
If you haven't written a State Machine with goto's and never marvelled at it's beauty ... please just try it.
I agree!
You're mistaken if you think Haskell users don't take advantage of state or side effects. They do, you just don't understand the difference.
Try this course:
http://www.seas.upenn.edu/~cis194/lectures.html
Then see LYAH's section on the State monad:
http://learnyouahaskell.com/for-a-few-monads-more
Then reflect on ST:
http://www.haskell.org/haskellwiki/Monad/ST
Then this example using mutable variables and closures:
http://bitemyapp.com/posts/2014-03-25-when-nested-io-actions...
Side-effecting closures mutating variables!
It's not "no state or side effects".
It's about making state and side effects typed and explicit so they can be properly composed and manipulated.
I love that sentence. It makes me think Haskell is like Bartok.
http://www.sm.luth.se/csee/courses/timber/reading/VanRoy.pdf
http://www.epsa.org/forms/uploadFiles/3B6300000000.filename....
http://c2.com/cgi/wiki?ConceptsTechniquesAndModelsOfComputer...
I certainly didn't find Clojure to be a waste of time; to my mind it's a far more practically-minded language. It's philosophy of decoupling components is also interesting. For example, in Haskell, the static type system is coupled to the language; in Clojure, the static type system is an optional library.
I'm moving everything over that I can. Some legacy Clojure at work I'll have to leave alone for now, but going forward it's Haskell wherever I can.
What is your take on the "you have to write clever, complicated code to make haskell work" (1). I've read that a lot of the code use for the language shootout is far from idiomatic haskell, but just plain clever, in order to get decent performance...
(1): http://jxyzabc.blogspot.ca/2009/03/haskell-vs-ocaml-or-ravin...
Haha, no. I write pretty dumb Haskell myself. The author might've tripped into a library beyond their faculties. Also possible, they might've tried to make something "practical" before they really knew what they were doing. I made this mistake in the past myself.
The library I've been working on makes my boring Haskell obvious: https://github.com/bitemyapp/bloodhound/
I even tweeted a sample of my code making fun of how "stupid-simple" my Haskell is :)
I might refine the code later, but for now I'd rather KISS until I'm prepared to firm up the design.
You can get down a rabbit-hole with Haskell if you want, but the same is equally true of Clojure/Scala/C++/Ruby/Python/Perl.
Even then, the rabbit-hole at least has typed hand-rails.
Negatives?
Uhhh, missing libraries (which I am working to help remedy)
You develop a "nose" for libraries for which you aren't the audience. It's not a big or unavoidable negative, but there are definitely libraries on Hackage made to prove a point rather than for use in production. These libraries are easy to identify. Some of them are prefixed acme-*
The primary negative that matters is simply that Haskell is deeply unfamiliar to most working programmers, so while it's 100% worth it, the road to Haskell isn't as well-trodden or smooth as it would be going between Python <---> Ruby.
I'm working to remedy this as well. I've been teaching Haskell for the last ~6 months.
In reality this isn't necessary very often. It is important to understand persistent data structures, how they differ from imperative ones, and which to use in different situations. However with a good understanding of the fundamentals (just as in imperative code) you'll be writing idiomatic performant functional code fairly easily.
Everybody who hasn't should be learning Haskell, regardless of background.
Teaching somebody Haskell is faster than explaining why the 1,001 dumb things mainstream languages do are dumb. I don't want to waste my time explaining why null values are dropdead stupid when I can just show them "Maybe".
We can talk about where we're headed after that.
Another issue is that Haskell is somewhat weighted towards finance and they're a bunch that tends to be somewhat proprietary about their IP. Some exceptions (Ermine) exist.
Some notable projects that come to mind include git-annex and Parsec. Parsec has been preeminent parser-combinator library since forever.
Also: pugs, pandoc, gitit, Darcs, xmonad, Idris (same person that did whitespace, haha)
Recently? Cryptol. That's pretty major.
I'm building stuff in Haskell, right now. Specifically, the easiest to use Elasticsearch client in the world.
One was needed. Badly. The ES API's data structures were never specced out properly, just documented on an ad-hoc basis. The Haskell library I'm working on will, if nothing else, mean that there's a reference for how the JSON is structured.
Anyway, empower thyself, learn some Haskell: https://gist.github.com/bitemyapp/8739525
Edit:
Ah, I thought I knew that username from somewhere. The negative-nancy is Timothy Baldridge, an employee of Rich Hickey's company Cognitect. Cognitect is "the" Clojure company and represents the inner-clique.
On the other hand, I don't have to be a php'r to know facebook was built in that language or a C++ programmer to know what google has done with it.
The negative-nancy is Timothy Baldridge, an employee of Rich Hickey's company Cognitect.
By personally attacking a critic of your claims, you're only making your case weaker.
Personal attack? What personal attack? Are you reading the same comment I am? He identified someone. If identification amounts to a personal attack, then that would seem to indicate severe problems with the image of the person being identified!
Apart from the juvenile "negative-nancy", there's also the clear implication of ascribing untoward motives based on the person's identity.
Well, some projects document systems in MS WORD, you are using Haskell for documenting JSON structures. That's a step up.
The language flamewar is off-topic and inappropriate for HN. The personal attacks are beyond the pale.
> haskell + smart programming practices guarantee a crash
> free experience.
Yeah dwm, crashes all the time.
Why don't you try another approach to functional programming, like http://www.shenlanguage.org/ ?
If you think Haskell is The One True Way™, get a new pair of sun glasses.
/rant
Getting tired of puritans. You people are selling functional programming on the basis of "ideology", not merits.
Can the following be done in Haskell ?
* A Real Operating System.
* GPU programming.
* Embedded programming.
* If you can do all the above, can you replace Verilog ?
* Financial Programming.
Ocaml is one of the "hybrids". Genetically impure,
since it has "refs". But they have Jane Street.
* Games worth playing. assertion : If all the haskell programmers are put in
a gulag, they can't come up with a half-decent
game.
Nintendo Gameboy Games were written in assembly with
goto's.
Why don't you guys take a moment and pat yourselves on
the back ? Hypocrisy-2.0 is probably in the hackage.
Let's say you do all the above, GUI apps, distributed computing, <cool-buzz-word> ... without complains and ending up as a half-decent C++ or 1/10th lisp.Haskell syntax is garbage.
(Common Lisp has a goto, gee what were they thinking ?)
Mathematicians pride themselves in their rich history of syntax.
Haskellers actually type "Arrow".
"I do consider assignment statements and pointer variables to be among computer science's most valuable treasures."
-- Only an Idiot could say that.
I don't know anything about the state of GPU programming in Haskell, so I'm not going to speak to that.
Regarding embedded, GHC can target some quasi-embedded platforms these days, but it's also possible to write embedded programs in (pardon the overloading) an embedded DSL that can compile to C. Check out the Atom library.
I've heard about some people doing hardware synthesis involving (again) embedded DSLs in Haskell - I don't really know the state of it, but IIRC Conal Elliot gave a talk on some related stuff at one of the Bay Area Haskell meetups.
Jane Street is doing a lot of O'Caml stuff, and that's awesome, but there's definitely a lot of Haskell in finance these days as well (I've seen several job postings, and heard some chatter generally). I don't know which is better represented, or how it compares to other stuff - most big finance places don't talk about what they're doing inside.
Oh, and Haskellers actually type "Arrow" when they're working with a particular generalization of functions. When they're actually working with functions, they type ->.
"GHC can target some quasi-embedded platforms these days, but it's also possible to write embedded programs in (pardon the overloading) an embedded DSL that can compile to C."
Haskell can't do any useful work without relying on C. Instead of having pride in what C can do, you have invented the following adjectives "hybrid", "mathematical language", "insecure", "impure", "pure".
Either,
1) Stop with the adjectives and get Real.
2) Prove that Haskell can replace C, the "impurity".
The same holds true for mathematical heritage. I would ask mathematicians to use Mathematica, not Haskell.
(I don't consider OCaml to be a part of this debate because OCaml is hybrid and Real, like C++)
Your and the haskell community's puritan behavior.
> you really don't know what you're talking about here.
Can't Parsec English ? I define the word hypocrisy, from a dictionary no less.
And Verilog is quite well entrenched, but if/when it's going to be replaced by something else, currently it seems that it will most likely be a Haskell derivative, something similar to Bluespec perhaps.
But can you clarify your point ? The cause of the rant seems to be for the "hybrids are a waste of time" line, however, most of the examples you provide are things that are currently done by, say, C/C++ but not by the hybrid languages.
Are you claiming that the hybrid languages are (or will be) much more widely used for developing 'A Real Operating System', embedded programming or mass-market games?
But on a different note, the reason why I program in Clojure rather than Haskell is that Clojure is so pragmatic. The JVM gives me access to almost every library I need, the JIT and GC are the fastest on the planet (for this sort of language). But most of all, Clojure trusts me. Clojure doesn't attempt to slap my hand when I make an impure function. It doesn't say "hey we can't figure out what type this function returns". Because at the end of the day, I don't care about that stuff. I only really care about writing good software, that fulfills my goals. If that means certain parts of my code are impure...I don't give a crap.
At least that's the way it's been for me for 4 years working with the language.
Huh? Haskell's polymorphism capabilities are more expressive and more expansive than most other languages'. Higher-kinded polymorphism, a mainstay in Haskell, is pretty rare to find almost anywhere else.
One of the things I like about Common Lisp is its "multi-paradigm" philosophy.
The difficulty with C++ does ultimately boil down to what you describe. But IME Objective C is an easier language in which to use OO features while retaining the flexibility of C where required - so it doesn't always have to the the case that a multi paradigm language fails. While ObjC is basically C + Objects + dynamic runtime, C++ has lots more stuff in there; I guess that's the kicker.
Perhaps we can call this the Paul Phillips bashing-Scala-tour effect o_O
Hope Scala 3 addresses current issues with the language, which, if it happens, seems to be at leat 2 years away (i.e. 2.12 next year and possible Scala 3/Dotty in the 2016).
Back then there were legacy "structured" languages like C and Ada, and new exciting "object oriented" languages like Smalltalk and Eiffel. C++ was promoted as a "middle way" that let you "choose the best tool for the job". This made the pure OO languages look extremist. So, it was argued, if you had a problem best solved by structured programming you could do that, and if you were doing an application with objects in it then you could use those. It also meant that your old C programmers could pick up the tool and start using it immediately without having to relearn how to design a program.
"Aversion to Extremes" is a well-known cognitive bias, and these arguments play up to it, but of course it didn't work well in practice. OO features didn't dovetail neatly with the existing structured features, leading to an exponential explosion in the rules defining how the various features interacted. The mess was not helped by experienced structured programmers who felt they should use the new sexy OO features; the result was often a conventional structured design with some random virtual functions sprinkled around.
The book "Industrial Strength C++" is a case in point. It is basically a catalogue of C++ language features that interact in dangerous ways. http://www.amazon.com/Industrial-Strength-Recommendations-In...
Today we have the same story happening again. On one hand we have legacy OO languages like Java and C++, and on the other hand we have pure functional languages like Scheme and Haskell. So along come "hybrid functional" languages like Scala which basically make the same promise as C++: if your problem has lots of objects then you can carry on doing the same OO designs you know and love, but if you think that these magic first-class functions would be useful in some complicated algorithms then you can use those as well. And its going to fail for the same reasons that C++ failed: the OO and functional features don't interact well, so we are going to have lots of messy rules about them that cause subtle bugs, along with attempts by OO programmers to use chains of map and filter functions that work inefficiently because the compiler can't optimise them. And in ten years time there will be an "Industrial Strength Scala" book consisting of a long list of features that should be avoided if you want reliable software.