📜 ⬆️ ⬇️

OMG Scala is a complex language!

I constantly notice that "Oh, holy heavens, Scala is difficult!" . You know, maybe it's true. Let's try to look at this complexity and go through the main differences of Scala from other object-oriented languages ​​(for example, Java or C ++).



Type inference


In most cases, the compiler is able to infer a type, which allows developers to write less repetitive information that they are so used to writing in Java and C ++.
For example, it is quite clear that "john" is a string, so the compiler can infer the type itself, and I will not have to specify the type explicitly. I can just write:
')
val aGuy = "John" 

I met both approval and criticism regarding type inference, so I don’t even know what to say. Personally, I like to write less and feel a little less stupid whenever I declare a value or variable.

Simplified class definition


Since OOP is built on the basis of the definition of classes, Scala implements this as simply as possible. All my domain models are extremely simple .

 class Person (val firstName:String, val lastName:String) 

I must say that the same thing in Java or C ++ would take almost a page of code with all sorts of designers, getters, setters, etc. The Scala developers realized that people should not write a whole page of code just to tell a stupid compiler that they need the class Person , which has two fields: first name and last name. So, in Scala, the definition of such a class takes only one line, just as a table would look like in SQL.
Does it add complexity?
Well ... I need to be concerned except in those cases when I need to override the generated getters and setters. So I don’t even know if this really complicates life ...
I?! Personally, I am so delighted with this opportunity that, frankly, I absolutely do not care what you think of yourself there.

Combining methods and operators


All programming languages ​​that I know have a hard line between methods named, type “append” , and operations, type "+ =" . Some languages ​​prohibit the redefinition of existing operators (Java). Other languages ​​allow only infix notation for operators (C ++). Scala does not have all these limitations. You can use any names for method names, and infix notation is allowed for any calls:

 ListBuffer(1,2,3) append 4 //     ListBuffer(1,2,3) += 4 

The only difference will be in the priority rules. Of course, someone will say that it is “more difficult” than in Java or C ++, because it “unleashes hands” and allows you to do whatever you want. However, I believe that this is more simple than in the languages ​​mentioned. In the end, this makes Scala a perfect framework for creating natural DSL:

 "Mary" with "a purse" and "red shoes" should look "nice" 


Types


In both Java and C ++, templates have some wired, restricted behavior (that is, covariance ) and allows only a few constructs (like List <T extends Person> ).
In Scala, there is a default behavior in which List [Person] is non-variant, but everything can be customized. If you need covariance, just tell the List [+ Person] or List [-Person] compiler for countervariation. On the similarity of Java, there is a construction List [T <: Person] and List [T>: Person] . Since Scala has an implicit conversion mechanism (implicits), another construction is also available, just for such cases: List [T <% Person] .
Is it harder?
As with operators, this mechanism creates some limitations, however, on the other hand, it provides new opportunities. I personally like this type control. Did I use it? Not in everyday development, most often the usual default type control behavior is missing.

Only designers?


Most languages ​​allow you to only construct objects. Scala also allows you to deconstruct objects, while I'm not talking about the release of memory occupied by the object. Consider:

 someone match { case Person(first,last) => println (s" name is $first $last") } 

Here you can see what I mean by “deconstructing” an object. Take the already created object and deconstruct it into the first and last components. I know it looks strange and unusual for most OO supporters, but believe me, this is insanely cool and convenient! Imagine what you would have to do in order to implement something similar in Java or C ++ ... Check for type (instanceof), assign two variables to these values, and much more ...
Think of string interpolation in Scala:

 "$first $last" 


Is it more difficult? Well ... This is a completely new functionality. I like! Believe me, you will like it too!
By the way, match / case provides a wider range of possibilities than the usual switch / case , which can work only with constants. With match / case, you can deconstruct objects, match constants, match types, and much, much more! Yes, see for yourself:

 someone match { case Person(first,last) => println (" name is " + first + " " + last) case "John" | "Mary" => println ("hello, " + someone.toString) case s:String => println ("name is " + s) case _ => println ("don't know what this is…") } 

It's complicated? I don't know ... in Java or C ++ it would take from one to two pages of code. For me personally, in Scala it looks simple and intuitively understandable.

Conclusion


Of course, these are just some aspects of the language. If you have something to add, write a post, I will be glad.
I didn’t touch functional programming on Scala, for that I need to compare Scala with other functional languages, I’m not the FP'shnik ( FP guy ). C ++ now allows you to pass pointers to functions to other functions, and lambda constructs are introduced in Java 8.

Is it all difficult? Well ... You can look at it all from two sides:
Yes ,

No ,

What I think? I really don't care. Personally, I am very pleased to have met with these opportunities. This allows me to solve problems with just a few lines of code, while my friends are still writing these getters and setters ...

Negative


There are still a few things that I did not like, for a little more than six years of experience with Scala. Here are some of them:
  1. Slow compilation. Not that annoyingly slow, but still much slower than the rest.
  2. Implicit conversions. I do not like how they implemented this mechanism. You can accidentally import a conversion from Any to MyCoolThing , which was defined in an imported block.
  3. Library collections. For most people, this is not so important, but ... It all looks much more complicated than I would like.
  4. SBT . It is always difficult. Seriously, if you need to do something that goes beyond the typical work with SBT, then you are trapped. There are so many different DSLs that are not obvious that Google will go crazy trying to find what you need to do. They needed to do either a separate syntax, like JSON or some kind of internal DSL, which the compiler / IDE could understand and help with working with SBT.


PS A more detailed discussion about the complexity: Simple or Complicated?

Source: https://habr.com/ru/post/228247/


All Articles