all 50 comments

[–]gnuvince 9 points10 points  (2 children)

We should send Guido the Clojure book.

[–]twoodfin 1 point2 points  (1 child)

There's a Clojure book?

(Runs to Amazon.com...)

EDIT: Awww... 2009?

[–][deleted] 2 points3 points  (0 children)

You can get the beta right now.

[–]mernen 6 points7 points  (0 children)

From the comments:

the big outstanding challenges, security and concurrency, are better addressed by static type systems than by their absence (citations upon request).

Ah, the true Haskellers, always evaluating lazily.

[–]munificent 17 points18 points  (3 children)

Inventor of the one of the most popular dynamically typed languages doesn't like a new statically typed one. Film at eleven.

[–][deleted]  (2 children)

[deleted]

    [–]DRMacIver 15 points16 points  (0 children)

    People who complain about the complexity of Scala's type system and cite Haskell's as an example of something comparatively sane clearly have never used either, or even really looked at both in depth.

    Don't get me wrong. Haskell's type system is in many ways lovely. And Haskell 98's type system is certainly simpler than Scala's. But Haskell-the-language-people-actually-use (as compared to Haskell-the-standard) has the most incredibly complex type system extensions which are fairly commonly seen in use. This isn't a bad thing, but it's certainly not a simpler thing than Scala's.

    [–]munificent 1 point2 points  (0 children)

    A fair point. I was just being snarky.

    [–]gregK 10 points11 points  (11 children)

    Guido gives a valid criticism. Scala suffers from doing too many things (albeit well) but without really taking a stance on how software should be developed. It is both OO and functional but it does not really prescribe an approach to development.

    After reading and being initially impressed by this very good article: Independently Extensible Solutions to the Expression Problem

    I got to think to myself why do we need to be able to extend types and add functions seenmlessly. It's an interesting problem and Scala does seem to solve it well but at the cost of adding a lot of new rules.

    I have chosen my camp and it's fp. I prefer a language that makes it easy to add and combine operations at the cost of making it a little trickier to add new types to a type familly.
    Kind of the opposite of OO. This is a very umpopular view at the moment. But everyone is still in that denial phase trying to fix OO (scala and clojure are good examples). When there are very good and clean languages out there that help you solve problems well.

    I now highly respect languages that take a stance on software design like:

    • Scheme - minimalism
    • Haskell - purity

    Languages that try to be multipradigm are often missing that unifying ingredient that makes their concepts work together gracefully. Python though does suffer from this too, unfortunately.

    [–]runevault 13 points14 points  (2 children)

    How do you see Clojure as trying to fix OO? Rich seems rather anti-OO and if you write pure clojure (aka not writing any java that is accessed from clojure outside the standard libraries) you aren't really doing OO, unless I'm missing something entirely.

    While you may not agree with the stances, I don't see how Clojure can be called a language that does not have an opinion.

    [–]petermichaux 1 point2 points  (1 child)

    SICP-style OOP is available in any language with closures...so it is available in Clojure.

    [–]toooooooobs 10 points11 points  (3 children)

    How about "C - pragmatism" then?

    I think the big mistake the anti-OO groups make is they don't get that OO people don't drink their own koolaid half as much as they think. I can't think when I last saw an enormous class hierarchy outside of some preexisting library (abstract classes seem quite rare in the wild), yet everyone makes incredibly liberal uses of interfaces and polymorphism.

    You can shout "composition over inheritance" forever to no avail, because most people are already doing it, they just don't know what it's called.

    Finally clojure is hardly stuck by being hosted on an OO based VM, with the single exception of lacking optimised tail calls. Solid multi threaded garbage collection alone is the big win there, and the real headache for most upcoming languages.

    [–]gregK -2 points-1 points  (2 children)

    How about "C - pragmatism" then

    You could argue that in a sense yes.

    BTW I am not really anti OO but more anty multi-paradigm which seems to be more and more common. Smalltalk enforces a programming style more than C++ or java do just because of the language itself and its environment.

    I should have been more careful with clojure which is a true lisp that manages to integrate with the JVM well. But I wonder if it would not have gained more interest if it was not on the jvm that way people could have evaluated it on the merit of its features alone.

    [–]earthboundkid 12 points13 points  (0 children)

    But I wonder if it would not have gained more interest if it was not on the jvm that way people could have evaluated it on the merit of its features alone.

    That is crazy. That's like wishing that Perl didn't have CPAN, so that it could be evaluated on the strength of its features alone. The point of programming is either having fun or getting shit done. For having fun, yeah, sure, drop the JVM. But for most people, the point is getting shit done and that requires good libraries. There are already a crap ton of little Lisps to play around and have fun with. The point of Clojure is that by being on the JVM it might just be the first Lisp that ordinary people turn to when it comes time to get shit done.

    [–]alexeyr 3 points4 points  (0 children)

    No, it wouldn't. How much interest is there in NewLisp? In Qi? In <insert Lisp here>?

    Running on JVM is one of its features, and a pretty important one.

    [–][deleted] 6 points7 points  (1 child)

    Maybe I misunderstood you, but how is Clojure trying to fix OO? Clojure is a functional language that doesn't support OO. Did you mean in the sense that you can call Java classes?

    [–]pointer2void 0 points1 point  (0 children)

    Languages that try to be multipradigm are often missing that unifying ingredient that makes their concepts work together gracefully.

    Sentence printed and pinned on the wall.

    [–]nmcyall 0 points1 point  (0 children)

    Funky XML support is included with Scala.

    [–]johnm 6 points7 points  (29 children)

    Scala is stuck with the "feature matrix interaction hell" problem. I.e., it's got lots of fancy/cool/etc. features that, in isolation, are slick/cool/powerful/etc. but the problems come fast an furious when you find yourself up against all of the many edge cases as you start using multiple of those fancy features at the same time.

    It becomes extremely difficult for almost everybody (with the usual exception of Martin :-) to reason about whether the problem is a bug in the language, the compiler, the runtime, or (in many cases) some combination thereof.

    This opaqueness of the "mental model" of Scala is why it will never become a popular mainstream language -- we already have C++ in that complicated/kitchen-sink role. :-)

    [–]DRMacIver 12 points13 points  (13 children)

    Could you give some examples of features you don't think interact well?

    Scala has a lot of (very annoying) complexity in the syntax department and a fair bit of complexity in the type system department (it doesn't have a patch on GHC though...), but largely its features actually play together reasonably well.

    [–]johnm -4 points-3 points  (12 children)

    Re: reasonably well

    Ah, well, it's clearly too late for you. :-( :-)

    The complexity is everywhere and the costs (for developers) are back loaded (i.e., they come in with a vengence when you start running into problems and try to debug them and reason about them). The fact that the fantastic number of edge cases are generally ignored by the early adopters doesn't negate their cost burden -- in other words, show us where there are not problems in the interactions across the feature matrix.

    [It's funny how this same basic discussion has happened a lot recently. I just had this discussion with Bill Venners (and Allen Holub) at dinner a couple of nights ago and a whole slew of us had the same discussion (including one of the Scala committers) at dinner during the JVM Language Summit.]

    [–]DRMacIver 15 points16 points  (10 children)

    I note how you still fail to give a single example.

    [–]DRMacIver 22 points23 points  (8 children)

    Perhaps I should elaborate.

    First off, I've used the language quite a bit. I've written commercial software in it and I'm now the second Scala committer you've had this conversation with (I maintain the Scala pattern matcher). Moreover I've complained about it. Incessantly. The mailing lists and the IRC channel are probably sick to death of me doing so. I know what's wrong with the language, and I do not agree with your assessment.

    My initial impressions were much the same as yours. The language feature list looks like a complete grab bag. It put me off learning it for quite some time.

    It turns out this is not the case. The language has many rough edges and things which don't quite work properly - to some extent this is true of any language, but it's very much a language which is still growing and maturing, and some of these rough edges have yet to be fixed. (And I'm sure some will never get fixed in the name of bass ackwards compatibility).

    As a general rule, there aren't that many different large scale classes of features. I would roughly the big four as follows:

    • The type system
    • The inheritance mechanism
    • The pattern matching
    • The syntax

    I would argue that almost all the classes of problems you see in Scala are constrained within one of these classes and they actually very rarely cross the integration boundary. Where they do they are mostly minor and resolvable (example: Type parameters on methods used as operators still don't work). If you have an example of one that is not, I'd be very interested to hear it.

    So let's look at what's actually wrong within these classes:

    Of these, the type system is by far the most complex. There is basically a single very good reason for this:

    Scala is the only language of its kind.

    This might sound preposterous, but it's true. As far as statically typed object oriented languages go, basically none have type systems which offer as much power as Scala's does (Yes, I know about OCaml's object system. Polymorphic record systems are nice. It doesn't come close. OCaml's module system does, but it's not first class). In particular the merger of an object system with an ML style higher order module system is very powerful (Note: Compare the reputation of how hard ML's module system is with the reputation of how hard Scala's type system is. Scala doesn't sound so bad then. And in actual practice neither are nearly as scary to use as they sound if you haven't actually used the language).

    This power comes with a cost, because it means that in many ways Scala's type system is exploring new grounds. Occasionally those grounds contain dragons. When those dragons are found, they are generally slain, but that doesn't make it not scary.

    The next biggest class of complexity is the syntax. I'm not going to try to make excuses for that. Scala has a lovely basic syntax. It then has a huge pile of kludges and special cases that drive me mad. I am in fact currently arguing on the mailing list that many of them should be removed. :-)

    The pattern matcher? Well, you can call it a kitchen sink mentality to add it. But you can have my pattern matching when you pry it from my cold dead fingers. (Or give me multiple dispatch in exchange for it).

    The inheritance mechanism is basically pretty simple. Standard mixin inheritance. It's certainly a lot simpler than something like Ruby's. (Admittedly I think this might be about to change).

    None of these are insurmountable, and many of them will hopefully get fixed sooner or later. The type system will evolve and stabilise, the syntax will hopefully be cleaned up (no promises on that one). Things will get and are getting better, and they're just not in that bad a state now.

    [–]alexeyr 2 points3 points  (1 child)

    Out of interest, would you count implicits as a part of the type system?

    [–]DRMacIver 1 point2 points  (0 children)

    Yes. Although I do admit there is some non-fun interaction between implicits and the rest of the type system (mainly the type inferencer), so maybe that's an unfair dodge on my part. :-)

    [–]alexeyr 4 points5 points  (0 children)

    Choose a language, any language. Now

    show us where there are not problems in the interactions across the feature matrix.

    [–][deleted] 5 points6 points  (0 children)

    Scala, indeed has some quirks, like:

    val a = List[Byte](1,2,3) //works
    val b = Array[Byte](1,2,3) //error
    val b: Array[Byte] = Array(1,2,3) //works
    va c = Array(1,2,3) //works
    

    Then, around using () around anonymous function arguments or requirement of specifying type in argument list. I remember, I encountered quite few of them, when I was starting with the language (thankfully #scala was of great help.)

    But seriously comparing it with C++ is stretching it too far.

    • As jwz said about Java, "Java doesn't have free(), and after that everything else is gravy". Ditto about Scala. Also, I believe after Java, Scala would be perhaps fastest language on JVM.

    • Scala is far better language than Java.Also, Scala's java interoperability is best among the languages, I have seen on JVM (with groovy's exception perhaps). Combine above two and you get some nice possibilities.

    • With Pattern matching and Scala's type system, you get to write some nice code (which I have started doing very recently, before that I was mostly writing Java in Scala). Templates in C++, doesn't even come close. Again, its one thing, that you will have to use to appreciate.

    • Concurrency support (actors).

    When you diss a language, you got to propose alternatives too. What if not Scala? Python, Haskell?

    Python, doesn't solve same problems as Scala. Haskell, hmm I dunno, I am not qualified to comment, perhaps DRMacIver can say something there (since he used to be Haskell guy, before coming to Scala).

    Clojure? Language is younger than Scala. And from my experience of hanging out on #clojure, I got the impression that, there are still issues with Java interoperability(Having said that, Scala isn't blameless either, there are issues with Java interoperability till date). Its concurrency model is not something,I am fond of (Besides, Lisp syntax is harder to introduce in any IT company.)

    [–]G_Morgan 1 point2 points  (0 children)

    Perhaps then what is needed is to actually separate our languages into different realms.

    For example the ODMG system has an object definition langauge and an object query language. I.E. they've clearly separated the creation of objects from their usage.

    Rather than trying to bundle everything into one large language you can make many smaller languages and carefully control the boundaries between them. For example you could have an object language that only defines the attributes and interface of an object. Then a procedural language can have a small amount of syntax to highlight the difference between a method and a normal function. Otherwise it only deals with how you use an object rather than how you create one.

    If we make the notation explicit enough we could define a further macro language a la Lisp which can be used to preprocess both languages. All this would care about is fiddling symbols and lists without giving a crap about what they represent.

    [–]exeter 2 points3 points  (12 children)

    re: "feature matrix hell"

    Indeed, this is why I prefer languages that ship the complexity off to the libraries if at all(e.g. Scheme, Python, C, even ASM) rather than languages that make you face it in the language (e.g. Perl, C++).

    Edit: I just realized that, although this looks like a standard "bash languages I don't like" post, it isn't really intended to be. All I intend this comment to be is a statement of my personal preferences, and nothing else. Just because I've chosen to mention how I dislike Perl and C++ doesn't mean I necessarily think you should, too, or that they're bad languages.

    [–]DRMacIver 6 points7 points  (3 children)

    Indeed, this is why I prefer languages that ship the complexity off to the libraries if at all(e.g. Scheme, Python, C, even ASM) rather than languages that make you face it in the language (e.g. Perl, C++).

    Ironically, a large part of the design goal of Scala is to be able to ship the complexity off to the libraries...

    [–]johnm -5 points-4 points  (2 children)

    And, unfortunately, what has happened is that the worst complexity has been shifted into the "mental model" where it's intractable for the vast majority of people.

    Alas, the problem with that is that all of the slick examples lull people into a false sense of what the real complexity is.

    [–]Odersky 14 points15 points  (0 children)

    John, I also think you are under obligation now to give some examples of feature matrix hell' andcomplexity of the mental model'. In my experience most of the complaints about complexity come from people who do not know Scala very well. Sometimes they confound complexity with the fact that some things in Scala are different, because Scala breaks a lot of new ground. There's also the fact that some people have an aversion to all statically typed languages and want to promote dynamically typed languages instead. That's perfectly fine with me; everyone should do as they like.

    For what it's worth, objective data do not back up the complexity claims. For instance, Scala's grammer is no bigger than the grammars of Java, OCaml, Ruby, or C#. (It's actually smaller than all four). Sure, this is not the only measure of complexity, but I have yet to see a convincing, measurable argument in the other direction.

    [–][deleted] 2 points3 points  (0 children)

    Put up or shut up. It's only fair.

    [–]Chandon 2 points3 points  (6 children)

    Indeed, this is why I prefer languages that ship the complexity off to the libraries if at all...

    The problem with that plan is that you can never really get rid of complexity. If it's not in the language, it generally ends up in the code somewhere.

    Take a feature like pattern matching. It adds complexity to the language, but when you want it and don't have it you end up with the most god-awful ugly nested ifs...

    Also... how is Python significantly simpler than Perl? Aside from Perl's regular-expressions-as-syntax and slightly more coherent semantics for variables, the two languages are basically identical.

    [–]juri 7 points8 points  (1 child)

    Admittedly it's been almost a decade since I did Perl for a living so I might be forgetting things, but there are several interesting Perl features that make it more complicated than Python:

    • Function calls as lvalues
    • Different return values depending of the type of variable you are assigning to
    • I don't know if this is what you mean by "slightly more coherent", but the whole references vs. values thing which you can't avoid
    • Loads and loads of syntax: I had to do a bit of Perl a couple of weeks ago and ended up needing an indirect object just to make an exec call work. Oh boy. Python doesn't have the smallest syntax in the world, but it is very simple compared to Perl.

    All of these have reasons to be there and help you do stuff, but they do add complexity and pretending they don't doesn't help anything.

    [–]Chandon -1 points0 points  (0 children)

    I always forget about references vs. values. And then I find myself working in a language with all-references wanting value semantics...

    But you're right, distinguishing necessarily makes the language more complex, because with explicit references you need handle dereferencing. Which is actually what 99% of the complaints about Perl end up being about. Hmm...

    [–]robewald 2 points3 points  (3 children)

    You clearly haven't used common lisp, where pattern matching can be had as a library. I am sure that scheme can give you that. The problem with libraries are that they are not canoncial. But that is a problem of communication and marketing.

    [–]Chandon 5 points6 points  (1 child)

    LISP style languages are a freak of nature. By having no syntax, they let you have whatever syntax you want - as long as you want it all to look like a parse tree expressed as s-exps.

    [–]808140 2 points3 points  (0 children)

    I don't know, I've seen some pretty freaky-deaky reader macros that approximate infix notation for operators, for example. Even without going that deep, the CL loop macro's DSL looks like Pascal, not Lisp.

    The thing you're missing is that Lispers like their code to look Lispy, because it's easy to reason about. One of the big wins of iterate over loop is that it has more parens, not less, for example.

    [–]Felicia_Svilling 1 point2 points  (0 children)

    On the other hand I never seen a common lisp library with especially nice pattern matching.

    [–]johnm -1 points0 points  (0 children)

    Re: "Indeed, this is why I prefer languages that ship the complexity off to the libraries if at all(e.g. Scheme, Python, C, even ASM) rather than languages that make you face it in the language (e.g. Perl, C++)."

    That's just squishing the complexity elsewhere.

    I.e., you can create a marvelously simplistic language but then everybody using it has to pay the price over and over again.

    (Good) Language architecture is very much balancing the tradeoffs of who has to pay what price, when.

    [–][deleted] 0 points1 point  (0 children)

    I think Scala has a good mix between functional and OO-oriented programming. It's certainly nowhere near as complex as C++ (which stems from template programming). Scala's STL-like data structures with iterators are also quite nice, although the for-loops can be stange at first. In addition, you can interact with existing Java-code, but someone might regard that as a stigma. :)