The fact that Kotlin has fewer features than Scala is what makes it appealing to me.
Scala has become a kitchen sink with too many features, it's kind of the C++ of the 21st century in that respect.
The fact that Kotlin has fewer features than Scala is what makes it appealing to me.
Scala has become a kitchen sink with too many features, it's kind of the C++ of the 21st century in that respect.
This misunderstanding mostly happens because some people start learning Scala in the hope of finding a better Java. But Scala is not a Java++, but something else entirely, being the kind of language that makes sense outside the boundaries of the JVM.
As a piece of advice, if you aren't interested in trolling, you might want to name actual things that you don't like, as in things that you can talk about, instead of things that are non-falsifiable. That way, in case you have a point, then other people or even Scala's or Kotlin's language designers can learn from your feedback. And if you don't have a point, then you might get some useful piece of advice.
On Kotlin - I don't like that it doesn't diverge enough. This is because when picking a non-mainstream language, you lose the advantages of mainstream languages, like easily available documentation, copy/paste-able samples, big developers pool, etc, etc... so the advantages of the non-mainstream language would better be worth it to balance the disadvantages ;-)
Sure, I could name things that I don't like but they will be by definition non falsifiable as well, so I don't really see the point of what you're asking.
Overall, I just find the surface area of Scala way, way too big. I felt the same way about C++ compared to C in the 90s, hence my comparison. I've used Scala for five years and over that period of time, I've seen the language adding feature over feature instead of addressing critical aspects such as good IDE support or decent build tools.
I'm still stuck with Scala at work but I'm really hoping Kotlin takes off because using it on my personal projects has been a breath of fresh air compared to Scala. It's like getting 90% of the power of Scala with 5% of the cognitive load.
- Case classes + sealed hierarchies (algebraic types, in other words)
- Implicit parameters
- Collections library
- Traits
- Function types, currying, partial application
- for-yield
- Pattern matching
None of those concepts on their own are especially complicated. In fact, I find Scala to have a bunch of orthogonal features that are easy to understand on their own and that compose in a variety of useful ways.
You'll find plenty of disagreement with that feeling everywhere you ask...
The fact that you choose to use a small subset of all these features is irrelevant: eventually, you have to hold all the language in your head because you will work with other people and other organizations that have different standards than you do.
Which is why it's so important for a language to learn how to say "no" to new features, something I feel Scala has been unable to do.
Hmm I'll try to think of some features that we don't use at work that would add additional semantic overhead:
- Inheritance? I mean okay but nobody I work with makes heavy use of this anyways and if I were working in a Scala shop where inheritance was used heavily it would be like working in a different language. So I suppose I'll give you that although I don't see how that makes the language hard to learn or work with.
- Mutable collections + references (vars)? Once again nobody I work with uses these outside of local mutability when they fail to be able to leverage immutable abstractions that do the same thing. If I worked in a Scala shop where mutability was used without care, it would be like working in a different language entirely true.
- while loops? I don't know what else I'm grasping for straws here.
If anything, the additional 'complicated' things we use in Scala aren't language features but rather libraries, mostly scalaz/shapeless.
One thing with Scala is that various features of the language allow libraries to reshape the "feel" of the language, because a number of things that would be fixed in the language in many other languages can be modified by libraries in Scala.
To some, this is a strength for Scala -- to others, it is a weakness.
The only implicit (I can think of) from the standard library that needs to be explicitly imported is ExecutionContext.Implicits.global. It's a form of dependency injection meant for working with Future and the error message tells you exactly what to do, but it can't be automatically imported because the thread-pool used is a pretty big deal and you should pause for a second to think about it. Other than that, the implicits you need are probably your own doing, because common libraries usually have a design where you get everything needed with sensible defaults.
In other words, if it's painful to import, then you should probably rethink it. This is actually a very good rule for Java as well. People too often rely on IDEs to do the boring parts, not noticing the stench until it is too late.
The (web) app I'm working on uses several ExecutionContexts (database access has a specific one for example.)
> I've seen the language adding feature over feature instead of addressing critical aspects such as good IDE support or decent build tools
Well, Scala 2.11 hasn't added any features, being a release meant for stabilizing, modularizing and optimizing the compiler and the library, fixing many non-withstanding issues. So zero new features.
Scala 2.10, released Jan/04-2013 (2 and a half years ago, OK?), was the release that added some features which included Value Classes / Implicit Classes (they are linked, for providing extension methods, as a refinement of implicit conversions), String interpolation (any sane language has it, plus Scala can now deprecate the conversion to String that was imported from Java), plus macros as experimental. Besides macros, everything else is minor and macros are meant for library authors as a neater way of building compiler plugins.
Scala 2.9, released May/12-2011, only includes changes to the standard library and not the language.
Scala 2.8, released Jul/14-2010 (5 years ago), introduced named and default arguments, package objects, changes to implicits, type constructor inference and a completely redesigned collections library. This release was so big for its users that it should have been called Scala 3. Before Scala 2.8 the language wasn't suitable for usage and Scala 2.11 is pretty much the same language as Scala 2.8.
So I'm really wondering what "feature after feature" you're referring to. Really, take other programming languages that aren't Java and compare the features added in the last 5 years to Scala's history. You'll have a surprise ;-)
Also IntelliJ IDEA is pretty awesome for Scala, I've been using it for the last 3 years. It's worse than IntelliJ IDEA for Java, but it is better than Eclipse for Java or Visual Studio for C#. There's also Scala IDE (built on top of Eclipse) and Ensime (a pretty capable Emacs / Atom / SublimeText plugin). Other platforms can only dream of such support, including Kotlin, or C# for that matter. I'm not joking.
> Sure, I could name things that I don't like
So why don't you name those things that you don't like?
Because then you will tell me that I don't like these features because I don't understand them?
But alright, here are a few:
- The type projector lambda syntax is absurdly arcane: `({type λ[α] = Either[A, α]})#λ]`
- The curry syntax is silly as well (multiple parentheses)
- The "_" character has eleven different meanings depending on where it's used [1]
[1] http://stackoverflow.com/questions/8000903/what-are-all-the-...
I'm not saying they aren't issues, but none of the things you mention is about Scala having "too many features".
Some newer languages have this kind of functionality (in Haskell it's a GHC extension, I think).
The "_" character is a placeholder for things that can be named, but for which you don't care about that name. And because you don't care about the name, it can function as a wildcard (i.e. any). To me all use-cases of the underscore make perfect sense and I can't remember a single instance in which I was confused by its meaning.
Type lambdas are arcane, but as @lmm points out, this is more about the absence of a feature. Basically in Scala type lambdas do not have first class support and so they are based on Scala's abstract types.
As to why they don't have first class support? Well, because people complain about too many features ;-) But it's worth pointing out that the TypeLevel folks have plans to introduce first-class support in their fork and thus propose an improvement. And also, because of the work that happened in Dotty, Scala the language is heading towards a DOT calculus foundation, along with a unification of higher kinded types with abstract types, which should iron out the edge cases.
The curry syntax seems silly if you come from SML, Ocaml, Haskell or languages from the ML family in general. In such languages all functions have exactly one argument. But Scala is not an ML language and so it doesn't do currying by default. It's annoying sometimes, but as with all design choices there are disadvantages and benefits.
To dismiss the similarities is disingenuous.
I can't really answer to your argument because it is superficial and there isn't anything in there to answer to. Whenever I ask folks what makes Scala complex or bloated, or what the conflicting "styles of writing it" are there, they always shy away. Because it's easier to be handwavy than it is to construct a good argument.
Unfortunately handwavy arguments are subject to marketing and social forces. This is how people end up worshiping Python's spirit and included batteries, which must be some of the biggest lies in our industry, since I can name more non-orthogonal and half-baked features in Python than in Scala, plus several clusterfucks in its standard library and ecosystem, starting from the build management tools, the async-I/O libraries and the web libraries, all of them screaming anything else but "there is only one way to do it". But that's just the herd mentality in action.
I think Scala library authors would love some links to those things where you consider the documentation to be lacking.
Yes, Scala isn't exactly the C++ formula applied to java and functional programming; it doesn't, for example, strive for source compatability (C++ has to because of header files, it likely wouldn't otherwise).
Whenever I ask folks what makes Scala complex or bloated, or what the conflicting "styles of writing it" are there, they always shy away.
I don't think there's a good way to identify concrete examples for "bloatedness" because it's kind of a fundamentally handwavy concept. It's a feeling that you get while learning and using the language. One that people don't get with C, or Go, or Haskell or Scheme, but tend to get with Scala and C++ and Common Lisp, to name examples.
Complexity is easier to point to though. The interaction of inheritance and generics, the mutability semantics, the fact that it's not clear from the call site when arguments get evaluated (with defered evaluation and macros), anything that can result from an abuse of implicits, mutability semantics.
The various styles of writing Scala? Well there's the people who wanted to write Haskell but settled for Scala because it's what their bosses gave them, who write it with a lot of immutability and use the type system to a great extent. There's the people who wanted to write java but write Scala because their bosses make them, who write java in Scala because that's a totally viable way to do it. And there's a lot of people in the middle.
Addressing your python point: I agree that the "there's only one way to do it" mantra is kind of wrong in pythonland, but there are a lot of conventions in that community that people adhere to that make it true in a way. This comes with a lot of dogma unfortunately. Other languages have fewer "non-orthogonal and half-baked" features. Go, for all its issues, doesn't have many of those because it seems its designers are content to just not have the features at all rather than have them be imperfect. C doesn't either, really, nor Haskell.
I think
I believe that such claims are unwarranted,
mostly coming from beginners with a superficial
understanding of the language
fits fairly well here ...I know the grammar is really difficult to parse and that has hindered static analyzers in the past, for example, but what else are you talking about? Also, how good or bad is clang's static analyzer compared to those of other languages?
C++ goal was that Bjarne didn't want to code ever again in plain C, after being forced to use it.
It just felt wrong to him such a primitive language after his experience with Simula and other proper languages of the day.
So when he joined AT&T, he started to work a way to have Simula for his work. Then the language grew from there.
There a few Bjarne interviews were he tells this.
C++ is a great language. Scala is a great language. Both are huge and require knowing which parts to work with.
I'm honestly wondering what the reasoning is behind the dislike of too many features, and how people justify the "right" amount of features. I can think of at least one argument against too many features, and that's managing what features a team should use in production, but there are solutions to that and I think that's a weak argument for the original assertion, which was entirely unsubstantiated.
I haven't used C++ or Java in over a decade, and I've never used Scala, so I don't have a horse in this race, but vague assertions deserve substantiation.
Languages like Go fall completely on the side of readable. I found that in my first few hours of Go, I could easily read through all the code that I found online and found it incredibly easy to reason about. But, as you'll hear time and again in critiques of the language, there's a lot of boilerplate that makes things explicit and many programmers dislike the lack of expressiveness.
Which brings me to Scala. Scala is on the entirely opposite end of the spectrum. When I first dove into Scala, I was constantly having to look up language constructs to understand the code that I was reading. And, worse yet, there was often no keyword or other indicator to tell me which feature was being used. In short, it was a nightmare to learn to read. But I'm sure the author loved it. S/he could express what s/he wanted from the computer in a few short lines that were entirely comprehensible to h[er|im].
My own personal view is that it's a right tool for the job situation. I think Go is a great language for large teams with high turnover. The fact that you could onboard a new Go developer and s/he would be able to read everything in your codebase and start contributing on day 1 is a huge plus. But if you've got a small, cohesive team that can agree on the subset of Scala features and overall patterns to use when developing, Scala could be a good choice since it would allow the team to move very quickly. There's a cost to both and it's important to consider when choosing a language. The main difference is that people too often evaluate the cost of a language based on their experience writing it rather than reading it.
I find programming languages follow the same rules, but often you are communicating with yourself (sometimes time shifted by minutes, hours or days). If you are an expert in a language that allows complex concepts to be defined concisely, you can use those idiomatic constructs to express your intent and another expert may easily grasp that intent, but a novice may find that much harder to comprehend. Conversely, a language that does not allow complex concepts to be expressed concisely will be easier for a novice to understand, but there is an inherent loss in efficiency for experts in that language that must resort to continuously defining complex concepts with the simpler concepts the language supports (boilerplate, in this case).
Neither type of language is inherently better than the other (as much as people like to assume so), they are just trade-offs that have different benefits and drawbacks based on the people or teams that use them. A team with low turnover and high experience could benefit greatly from the long-term use of a language that supports higher level concepts succinctly, while a a team with lower expertise or high turnover might find that extends the learning period of new hires. It's fairly easy to point out languages that have chosen one path over the other, such as Java and Haskell. I think an interesting case is Perl, which supports both, and I think that's a large source of the idea that Perl code is unreadable. It's made to be easy enough to understand in many cases at first glance, while also supporting a lot of higher level concepts. This can cause people that use it to experience very different levels of complexity in close proximity, which can be jarring for the novice, and sometimes the competent user as well.
Good design has the smallest number of features making the greatest amount of things efficiently possible. Scheme and Forth are brilliant designs by this metric, Haskell, Python, and Go good ones, while C++ and Scala, well, not so much, frankly. BTW, Odersky himself admits it.
It's perfectly fine to have an opinion, but it shouldn't be stated as fact without any substantiation (as in the GP) or with evidence consisting entirely of subjective elements unless those elements are further explored and explained in less subjective term (using "good language design" as evidence does not count as less subjective).
> BTW, Odersky himself admits it.
Was I supposed to know who that was referencing prior to googling? I'm not sticking up for Scala, I'm interested in exploring the concept of too many features as a negative in language design.
Not sure what you mean, the ABI compatibility doesn't require any feature to work. Does Scala support higher kinded types to be compatible with Java? This does not make sense to me.
For the sentence "Scala is compatible with Java", there is almost no interpretation of "compatible" that would make the sentence untrue.
If you work alone, you're right. Problems start when working in a team. The average lifetime of a codebase is about a decade, in which time it is read and touched by many hands, and falls under several management administrations. We know that languages that are too feature-rich can prove troublesome under these conditions.
> sounds suspiciously subjective
Of course its's subjective -- like many things that have to do with the choice of languages -- but unlike many other debates, we actually have some very good data on this: C++. For a few years, C++ was considered a blessing. Expressive, sophisticated, powerful. But after a few years, as codebases started to mature, the industry as a whole discovered that maintaining C++ codebases is a nightmare. Every team had its own style and its own subset of features it chose to use. Some features (like operator overloading and esp. cast and assignment operators) while useful, ended up making long-lasting, large-project collaboration extremely costly. Java's design was very much a reaction to C++, eliminating features right and left, and declaring from the get-go that it aims to be less expressive and more verbose. It worked. The question now is whether any new "rich" language would share C++'s troubles or not, and that is indeed subjective (so far). But at least we know that sometimes a combination of too many features can be really bad, especially when working in large teams.
BTW, today C++ is quite effective because it's become a (relative) niche language (even according to its creator). Niche languages are used by specialized teams that are good at enforcing discipline, and/or tend to be smaller.
I also think that complex languages may be harder for teams with high turnover or a lower average skill set within that language (and as such the average allowed complexity per expression may play a role in this). I went into some depth on this in a cousin thread[1], but my conclusion may not be quite the same as yours. Part (well, most actually) of my original question on this topic was to ask for clarification, because I thought the assertion was inherently ambiguous.
That said, if you have actual numbers or studies to bolster your statements about C++ I would love to see them. What you assert is a common refrain here, but I'm truly not sure how much of it is confirmation bias and squeaky wheel. There are plenty of C++ supporters as well as detractors, but I'm not sure how to sort through the noise here to get an accurate assessment of the landscape. Interestingly, my relative distance from C++ may actually help here since my own experiences may not sway me as much, but that might be entirely overshadowed by C++'s similarities and differences to other languages that I like or dislike in some aspect that I am more familiar with.
In the end, since it's not as simple as "less features us better, more features is worse" (otherwise we would all be writing assembly), I suspect there are a few other important axes of comparison that actually describe the situation better, and language features is a useful abstraction but only over a very short range of values, outside of which it becomes increasingly useless as a metric for how hard or easy it is to manage a codebase.
> BTW, today C++ is quite effective because it's become a (relative) niche language (even according to its creator). Niche languages are used by specialized teams that are good at enforcing discipline, and/or tend to be smaller.
Is it? I know there have been other systems eating into the market share for C++ for a while, but my impression has always been that it's still extremely popular in certain segments where there hasn't been much new competition for a while. E.g. high performance computation, cutting edge/AAA games, etc.
"Extremely popular in certain segments" is typical of "niche languages" -- those segments are its niche(s).
If the niche is well-defined, the size doesn't really matter in many respects, because its effectively a completely different market, and it doesn't matter whether that markets large or small in terms of what goes on outside that market.
Arguably, assembly is the most feature-full language - everything is possible. But those features are very expensive, which is why it's only used where there is no alternative.
That is, both C and Perl can implement Hash data objects, but C requires a library or implementation, and Perl makes it a core data type of the language.
And C, Java, Perl, etc, also don't have anything like "enter supervisor mode". But if the CPU supports it, assembly will let you do it.
Note that most real-world case studies were done in the late '90s-early '00s so they are not that easy to find. A quick Google search, however, came up with this[1].
> There are plenty of C++ supporters as well as detractors
It's not about C++ supporters and detractors today. It is an undisputed fact is that the industry as a whole abandoned C++ (except for its relevant niches) and practically no one has looked back.
> In the end, since it's not as simple as "less features us better, more features is worse"
I'm not saying it is simple. I am saying that we have one experiment with conclusive results. Perhaps there are other variables, but given the strength of the results, the burden of proof -- IMO -- lies with those who claim that their super-feature-rich language will not meet the same fate.
> it's still extremely popular in certain segments
It is, and those are its niches. They form a largeish share of the market, but not anywhere as large as the segments that used C++ in the 90s or the segments that use, say, Java today. It is most certainly no longer a general-purpose cross-market industry-wide language.
[1]: http://www.lanl.gov/projects/CartaBlanca/webdocs/PhippsPaper...
> the burden of proof -- IMO -- lies with those who claim that their super-feature-rich language will not meet the same fate.
All you are doing is reducing the discussion to something so hand-wavey that it can't be argued anymore. I'm interested in how much is too much and what type of features increase tihs load. I assert that some features don't increase errors, but in fact decrease them (e.g. Java's automatic memory management), and if that's true, than the statement "more features is worse than less features" is trivially proven false. Is it really that hard to move the argument beyond the simplistic point of view that "features" are the problem?
It is handwavy because designing languages is an art, but usually providing too many ways to achieve the same thing or allowing code that hides its operation (or appears to violate the "normal" language semantics while looking innocuous) is, in general, bad (for large teams), as it hinders readability. Of course, things need to be balanced, and you have to consider what kind of projects the language is for, what would be the "average" code size, etc..
And I've been trying to get people to at least define what they are talking about in every single comment I made. Kudos to you for doing so. :)
> Automatic memory management is what's known as an extra-linguistic feature.
While that makes your position easier to support (but it's not what the original comment stated, which is why I asked for clarification from them), I'm not sure I buy it entirely. I need an explanation why a language with more language level abstractions is worse than one with less, given that you can enforce the restriction of some abstractions. Why is artificially limiting yourself the better solution than enforcing restraint, which leaves the possibility to work outside those constraints when the conditions are correct?
[1]: This is less true of C++ today, when it's mostly a specialist language used by specialist teams working in fields that have always required a lot of restraint. They know how to do restraints (well, at least better than the industry at large).
So? the language's themselves change over the time frame you are looking at. You seem to be arguing that having the language enforce it is better than policy, but name one language that's seen any serious use that hasn't seen change to add new features over the last then years, of the exact sort you are saying cause problems. So we're supposed to entrust this to a third party that really doesn't care about our specific needs. The Java standards committee doesn't know who you are. And if they do, you are not a representative case of the vast majority of Java programmers. I would rather control my future, so I choose freedom with restraint.
I'm really not buying your C++ is niche argument. C++ is one of the top 3-5 languages in the world in every metric. Java is more popular, but not being the most popular has nothing to do with being niche. C++ is still in massive use in almost every industry. That is not niche. Using C++ as your go-to example and basing your argument on having lost so much market share as to be a niche language isn't really moving the discussion along. Shops switched to Java from many languages, not just C++, and for many reasons, not just because C++ features caused problems. That argument is far too simplistic and ignores far too many things for me to give it much credence.
If you see how Bjarne Stroustrup[1] describes C++ today, you'll probably agree that it's a niche language (he sees it that way today).
> That argument is far too simplistic and ignores far too many things for me to give it much credence.
Of course. But ignore it at your peril. If you want to use a language that is similar to C++ in many respects (many of the same respects that the industry complained about), you should at least acknowledge the risk and try to be damn sure that this is what you want or be sure that this wasn't a contributing factor to C++'s fall from dominance.