1. 6
  1.  

  2. 7

    One problem I’ve found with Scala is that it’s full of lies. A great example is PartialFunction. For starters, it implies that every other function is total, which is just isn’t going to be true. Secondly, the little trick with a pattern match only sort-of works. It will build the conditional for one layer of pattern matches, but not for the others, so you can still fail on input even though the conditional says it will succeed. It doesn’t sound like much but if you can’t get your foundation right you can’t build anything on top. Scala has seemed, to me, like a language quick to adopt aspects that sound nice but have no reasonable way to provide to the user. Instead one just gets sort-of-working components.

    1. 1

      You mean, like a research language with commercial users it never intended to support? Yeah, that sounds about right.

      1. 2

        I don’t know if the example I gave would really have anything to do with being a research language or not. A research language like Agda or Coq actually do have concepts of total functions that makes sense. I think Scala just suffers from being poorly designed. But so does C++, Python, and Javascript. I think what I personally find annoying about Scala’s faults is that it appears to have convinced people it’s a thinking mans language, which I disagree with.

        1. 2

          Maybe not your examples, but what plagues Scala is that during it’s early years it was strictly research. This meant that new features got added, but none ever got culled, and so you have this huge language with some good and some bad ideas. One other example is the problems that used to exist with binary compatibility. As a research language, who cares? As a language which people are using in production, and have to upgrade and actually use without downtime, it’s a huge deal.

          The other languages you mentioned are poorly designed for other reasons though. JavaScript has remained basically unchanged since the 2 week sprint to get it into Netscape, for reasons of backwards compatibility. Sure, new features have been added, but nothing has ever been taken away. Python is the only language listed that has actually all out broken backwards compatibility in the name of fixing stuff going forward. Is it a well designed language? No, not really, but they’re at least reflecting on it and iterating, successful or not.

          Programming languages are often “poorly” designed from a theoretical point of view, and maybe that’s OK. Programming languages exist to help people get work done. If it’s productive but has a few warts, inconsistencies and broken features, it’s often easy to write a book and avoid the mess. Could a theoretically perfect language be productive? Absolutely, but it turns out, we suck at programming language design almost as much as we suck at developing and maintaining any other software.

      2. 1

        1) All functions A=>B in scala are total after accounting for exceptions. A=>B is more accurately expressed as A=>Either[Throwable, B]. However, that’s also the case in Haskell. During the execution of a function a->b, an out of memory error can occur, the CPU can malfunction, error(“foobar”) can be evaluated, etc. Scala isn’t perfect, but neither is any other implementable model of computation.

        2) Nesting partial functions is the wrong way to pattern match on complex structures. It’s entirely possible to match on complex structures using nested structures in a single partial function. For example:

        case (a::as, b::bs) => (…)

        case => GET(Path(Seg(“users” :: name :: “bookmarks” :: Nil))) => (…)

        It’s entirely possible to pattern-match safely with arbitrarily deep nesting. There are also ways to safely combine partial functions if you need to, such as andThen.

        Scala might not be perfect, but it’s simply false to say that you can’t build anything on top of it.

        1. 2

          I respectfully disagree.

          All functions A=>B in scala are total after accounting for exceptions

          That is not a definition of total that anybody else uses. It is also false. And what about infinite loops? You’re also arguing every Python function is total, do you agree with this?

          A=>B is more accurately expressed as A=>Either[Throwable, B]

          No it isn’t. Infinite loops.

          However, that’s also the case in Haskell

          Correct, and Haskell doesn’t act like its functions are total.

          Scala isn’t perfect, but neither is any other implementable model of computation

          But you’re missing the point. Scala has a Function type and a PartialFunction type. But all functions in Scala are partial. The model is simply wrong.

          Nesting partial functions is the wrong way to pattern match on complex structures.

          But that is not what I’m talking about. I’m talking about Scala’s magic to create PartialFunctions but doing something over cases. This completely breaks down at 1 more level of comparison.

          1. 2

            First, thanks for the clarifications. I’m new to this site and I’m enjoying the high level of discourse.

            But you’re missing the point. Scala has a Function type and a PartialFunction type. But all functions in Scala are partial. The model is simply wrong.

            I would argue that there is value in functions that know when they’re not defined, despite the possibility of false positives for isDefinedAt(x). PartialFunction may be a misleading name for such functions, but they are still very useful in a variety of cases.

            No it isn’t. Infinite loops.

            Fair enough, I hadn’t considered the non-terminating case. (non-serious snarky counterpoint: any infinite loop will necessarily terminate no later than the heat death of the universe)

            But that is not what I’m talking about. I’m talking about Scala’s magic to create PartialFunctions but doing something over cases. This completely breaks down at 1 more level of comparison.

            To clarify: are you talking about code like the following (trivial) example?

            {
            case List(a, b) => (a, b) match
                {
                    case ("foo", "bar") => println("foobar!")
                }
            }
            

            My position is that such code should be refactored to be more like the following, allowing arbitrarily deep safe pattern matching.

            {
                case List("foo", "bar") => println("foobar!")
            }
            
      3. 6

        From a comment:
        “Scala is like the house of cards - on first glance everything might look rosy from the outside but thats just a facade to cover up the giant pile of mess, trickery and lies. watch this eye opening presentation from Paul Phillips (ex scala fanboy and a committer)”

        Some of the virulent anti-scala commenters are beginning to sound like 9/11 truthers. It’s healthy for the community to have detractors who get feel strongly about it, but this kind of tone is not productive.