3 ms·
> Let's consider one of the features you mention that Scala actually has, and see how it fits: structural typing. Scala doesn't have structural typing because a
by laureny 13y ago
> Let's consider one of the features you mention that Scala actually has, and see how it fits: structural typing. Scala doesn't have structural typing because all the cool kids are doing it or some other non-sense: it serves a purpose in the language, and solves a number of problems in a coherent manner, with a single set of rules and in a way that combines together with other parts of the language.
I'm surprised you're pointing out bad design decisions in Java (that I agree with) and point structural type as a good Scala design decision.
Structural typing is terribly designed and avoided overall for all these reasons. For example, asInstanceOf doesn't work with structural types but works fine with traits and classes. That's bad design.
Here is an example showing how broken structural types are:
scala> type Mappable[A] = AnyRef { def map[B](f: A => B): Mappable[B] }
<console>:7: error: recursive method map needs result type
type Mappable[A] = AnyRef { def map[B](f: A => B): Mappable[B] }
I have about three other mystifying compiler errors due to the fact that structural types are very badly integrated in the language overall.
> It's not that Scala has many disparate features: it has a core of well designed features, and they are well designed because they allow use in many different ways.
I think you are not being very objective in the way you see Scala. A lot of its features are terribly at odds with each other, such as mixing inheritance and type classes (which one should I use and when?), the eleven ways in which the underscore character can be used, currying and its bizarre syntax, the odd rules when you can omit parentheses and when you can't, when to use parentheses and when you should use braces, etc...
Scala has tons of disparate features that don't fit very well with each other, and it's very similar to C++ in that respect.
- dancapo 13y agoOne of the goals of Scala was having good interoperability with Java. This might not look important today, where considering different languages is ok, but it was certainly the case years ago, when programming environments were monolingual and proud of it. There are bad consequences arising from that, but it was a trade off that was made taking into account the failure of Scala's predecessor, Pizza. Among these things there's asInstanceOf, which you should generally not be using in first place. That said, you can use asInstanceOf with structural types: scala> object X { | def f(a: Int, b: Int) = a + b | } defined object X scala> val y: Any = X y: Any = X$@aebbca6 scala> val z = y.asInstanceOf[Any { def f(x: Int, y: Int): Int }] z: Any{def f(x: Int,y: Int): Int} = X$@aebbca6 scala> z.f(2, 3) res6: Int = 5 Your example definitely doesn't show structural types being broken: it only shows that type refinements cannot be recursive. This might be limiting, but it is not broken, and it was a necessary trade off to integrate structural types into a nominal type system -- something that was thought to be impossible. Inheritance and type classes: type class is not a Scala feature, it is a design pattern that uses other Scala features together, so there's no "clash" here, because there's no feature. The eleven ways in which underscore can be used is not something "at odd" either -- it's just the same symbol used in eleven different contexts to mean eleven different things. It saves on reserved keywords/characters, at the cost of making the language more difficult to learn, but there's no conflict between their uses. There's nothing bizarre about currying syntax -- you may not like how it looks, but it's perfectly functional. Maybe you like point free programming, but that is NOT a style favored by Scala, intentionally so. The rules for omitting parenthesis are actually rather simple: you can omit parenthesis around the parameter of a single-parameter method when that parameter is enclosed in braces itself; you can also omit parenthesis around a parameter of a single-parameter method whose parameter type is a tuple. Now, even if I had not an answer for each case you raised, you have failed to show that they don't fit well with each other. You have criticized each one on their own, in isolation, and, in fact, failed to appreciate how they actually show their strength when combined. Some examples of that: * Omitting parenthesis combined with by-name method parameter passing allows for DSLs that look like native language constructs; * Implicit parameters, type inference and nominal typing can be used together to produce the type class pattern; * Abstract data types and inheritance can be used together to create a module system.