Scala book redux
Reading through the book Programming in Scala: A Comprehensive Step by Step Guide, but this time I am actually using Scala in my day job so I think it will be more meaningful. Also I have written two of my own Python envy, Scala envy, Groovy envy, functional programming libs in Java with tons of other utilities (one I threw away, it was horrible, and the other one is Boon). Also now I have some experience with Java 8 lambda expressions and functional programming, and some experience with Python functional programming so I feel like the book makes more sense then it did when I attempted a few goes at it before.
Java vs. Scala
The Scala book which predates Java 8 uses a name
exists
example and shows a for
loop vs. Scala exists
.Scala
val name: String = "Hello World"
val nameHasUpperCase = name.exists(_.isUpper)
println(nameHasUpperCase)
Java
final String name = "Hello World";
final boolean nameHasUpperCase = name.chars().mapToObj(i -> (char)i)
.anyMatch(c -> c.isUpperCase(c));
System.out.println(nameHasUpperCase);
The issues with Java is mainly that it does not include chars() that returns a CharacterStream instead it returns a IntStream, and I can't fathom why.
We can close the verbosity gap by using a static import and a method reference.
final String name = "Hello World";
final boolean nameHasUpperCase = name.chars().mapToObj(i -> (char)i)
.anyMatch(Character::isUpperCase);
out.println(nameHasUpperCase);
Clearly Scala still wins. Scala is easier to read and smaller. But the difference is smaller if you choose Java 8. (Or a library like Boon where this type of operation would be a one liner in Java as well.)
Scala's big win here (in this small example) is mainly due to its implicit typing, and
String.chars
returning an IntStream
instead of a ChararacterStream
. Java would lose less bad with a more complete lib for handling Strings.Type system
For instance, Alan Kay, the inventor of the Smalltalk language, once remarked: "I'm not against types, but I don't know of any type systems that aren't a complete pain, so I still like dynamic typing."[13] We hope to convince you in this book that Scala's type system is far from being a "complete pain." -- Odersky, Martin; Spoon, Lex; Venners, Bill (2010-12-13). Programming in Scala: A Comprehensive Step-by-Step Guide (Kindle Locations 536-538). Artima Press. Kindle Edition.
I find that larger systems always need strong typing which could be less of an issues with Microservices. Perhaps. But I find when I wrote code in Groovy that I use types. When I write code in Python, I add type information to the here docs and to the comments so I often wonder if I always feel the need to add type information (from being burned a lot on larger Python projects) then why not have types in the system. If you are going to have types in the system, then why not make the implicit like Scala (and others).
I agree with the Scala approach.
Implicit arguments
This book is older so again it misrepresents Java by not including implicit typing added in Java 7 and present in Java 8. This book did come out after Java 7.
Clearly, it should be enough to say just once that x is a HashMap with Ints as keys and Strings as values; there's no need to repeat the same phrase twice. --Odersky, Martin; Spoon, Lex; Venners, Bill (2010-12-13). Programming in Scala: A Comprehensive Step-by-Step Guide (Kindle Locations 564-567). Artima Press. Kindle Edition.
val x = new HashMap[Int, String]()
final Map<Integer, String> x = new HashMap<>();
Note that I prefer the Scala syntax here. This has been adopted by the two other Java programming langauges that adopted Scala's implicted typing. Implicted and strong typing will be Scala's legacy. It is terse, yet unlike Dynamic typing, exact.
What I don't like about Scala is this:
Scala operators instead of methods
val x = new HashMap[Int, String]()
x += (1 -> "foo")
println (x.get(1).get)
Versus Java.
Java methods instead of operators
final Map<Integer, String> x = new HashMap<>();
x.put(1, "foo");
out.println(x.get(1));
At least I don't like it yet. Strangely I feel that Python's operators for Maps make sense as do Groovy's. But Scala's look weird. There is so much prior art dealing with associative arrays, dictionaries and hash maps, that this seems to be an odd choice at best. Also, I am not a fan of using operators when a method will do. I saw this in C++ and in Python. It tends to make code very hard to read, unless you are working with a real well known lib. I feel this has so much potential for abuse and leads to undreadable code. This goes against my instincts to comment and carefuly think about method names. I would likely use the standard built-in libs operators (no choice for many things), but shy away from using this feature (mis-feature).
I also wonder why Scala supports non-implict types. You can specify the type.
val y : Map[Int, String] = new HashMap[Int, String]()
One wonders what dark corners of the langauge exist where you would want to use an explicit type when an implicit one seems to work so well. My guess would be interface design. We will see. Still on chapter 1.
I did write my first real world microservice in Scala. But I have to admit. There are things that I wrote to make the compiler happy that I do not fully understand which is why I am reading the book (other times I more skimmed it). I can't stand using a language the wrong way. Unless I do it for a good reason (performance).
Scala influences
At the surface level, Scala adopts ... syntax from Java and C#, which in turn borrowed ... from C and C++. Expressions, statements, and blocks are mostly as in Java, as is the syntax of classes, packages and imports. (What did it borrow from C#?) (Basic type system from Java, libs, execution model.) ... (Its) uniform object model (is from) Smalltalk (mention of Ruby to make Ruby guys happy I suppose). Its Universal nesting ...(is from) in Algol, Simula (Beta and gbeta). Its uniform access principle for method invocation and field selection... from Eiffel. Its ... functional programming is ... similar... to ML family of languages (SML, OCaml, and F#)... Many higher-order functions in Scala's standard library are also present in ML or Haskell. --Odersky, Martin; Spoon, Lex; Venners, Bill (2010-12-13). Programming in Scala: A Comprehensive Step-by-Step Guide (Kindle Locations 577-585). Artima Press. Kindle Edition.
I can see why so many CS majors love Scala. It incorporates many of their favorite langauges that they are forced to learn in school which are not used in the industry very much at all. Lookup all of those languages other than C#, Java and Ruby on the Tiobe index, and they are not very popular. What no mention of Icon? You are missing out on the Tucson AZ market. (Scala is 27th on the list with .7 percent. Groovy is at .5 percent. Scala is the only "cool" langauge that makes it in the top 50. I imagine Scala is going to keep climbing due to Apache Spark.
I find that Ruby, Perl, JavaScript and Python developers who would never dream of touching Java sort of like Scala. This is one reason for me to learn it. The other is Apache Spark. I run into a lot of Python developers. Scala does not bring on the hatred that Java does from Python folks. (I like Python, Groovy and Java a lot.) It seems given this that more thought would have been given to adopt closer syntax support for Python/JavaScript ways of indexing maps (assocaitive arrays).
Functions
object MainScala {
def max (x : Int, y : Int): Int = if (x > y) x else y
...
val abc = max(1, 2)
println(s"Max $abc")
public class Main {
public static int max(int x, int y) {
return (x > y) ? x : y;
}
...
final int abc = max(1, 2);
out.printf("Max %d\n", abc);
Those are roughly equivalent at this point. I prefer the return type after the parameter list. This makes reading/finding the method name easier. (Point goes to Scala).
The Scala version can be simplified further as Scala can infer the type. The book does not mention this (older book, or covered later).
def max (x : Int, y : Int) = if (x > y) x else y
I am very used to the C/C++/Java terenary operator so its use does not bother me. I can see how the Scala if/else would be more appealing to Python and Ruby developers.
Performance wise: The Java version is using primitives not objects so unless Scala does some magic in a tight loop the Java version is going to be much better with a lot less GC pressure. This will not concern Python and Ruby devs. It concerns me. I do write things that at times need a bit of punch when it comes to performance (parsers, event system, queue systems, etc.). If I did adopt Scala, I would still use Java for core things that needed performance.
Book just covered how the return type was optional. :)
While loops says the book are not the preferred style. I had to use a while loop once. I was moving Java code to Scala. Good to know that there is a better way.
They just covered imperative while loop style vs.
foreach
. There are times in Java when I get the underlying array and I iterate using a for / loop. I do it when I know something is going to iterate in one or more loops. The difference when you are working with millions of users per node can be pretty large. I can see where I would write some features in Java to avoid the extra GC just like where I would avoid iterators and streams in Java 8 in certain places. It is good there is a Java escape valve in Scala. You won't need it often, but when you do. :)
That covers the first two chapters.
No comments:
Post a Comment