Principle of Least Power (Scala)
In this video Martin Odersky shares an analogy of using a stapler when you need a stapler (not a power tool). He highly recommends reading Li Haoyi’s article, Principle of Least Power.
In this video Martin Odersky shares an analogy of using a stapler when you need a stapler (not a power tool). He highly recommends reading Li Haoyi’s article, Principle of Least Power.
On June 25, 2020, I tweeted that Coursier was providing a way to make installing Scala and Scala-related tools easier. I’ll look into that more soon, but in this tutorial I’ll show something different: How to install multiple JVMs/JDKs with Coursier.
As a brief tip, here’s an example of how to capitalize every word in a string in Scala:
"foo bar baz".split(" ").map(_.capitalize).mkString(" ")
The output of that expression is:
Foo Bar Baz
Also, instead of using the underscore character inside of map
, you can write that anonymous function like this, if you prefer:
"foo bar baz".split(" ").map(s => s.capitalize).mkString(" ")
If you wanted to see how to capitalize every word in a Scala string, I hope that’s helpful. Also, if the map method doesn’t make any sense to you, check out my How to write a 'map' function in Scala lesson.
Imagine that you have a method that requires an InputStream
, and you want to test that method. How can you test it?
In the Scala Cookbook I wrote how your method can accept a Source
instead of a File
to make it easier to test, so I won’t write any more about that right now.
But if you have a method that accepts an InputStream
and you want to be able to test it with a String
, here’s what you can do:
Whenever I used to get the Scala REPL warning message, "There were deprecation warnings, re-run with -deprecation", I used to have to restart the REPL with the -deprecation
flag to see the warning message, like this:
$ scala -deprecation
That works, but sadly, you had to lose your entire REPL session to run it.
Thanks to the Scala gods, this is no longer necessary in Scala 2.10 (and newer). Now, when you get the REPL deprecation warning message, like this:
I haven't had the need for this syntax yet, but I just saw some code that shows how to create a private primary constructor in Scala, and I thought I'd test it and share an example of it.
In the example below, I've made the primary constructor of the Order class private:
Here’s a quick look at how to convert a Java Map (such as HashMap) to a Scala Map
using the JavaConverters
object:
// import what you need
import java.util._
import scala.collection.JavaConverters._
// create and populate a java map
val jMap = new HashMap[String, String]()
jMap.put("first_name", "Alvin")
jMap.put("last_name", "Alexander")
// convert the java map to a scala map
val sMap = jMap.asScala
Scala file FAQ: How do I open and read text files in Scala?
When you’re writing Scala scripts, you often want to read text files. Fortunately it’s pretty easy to open and read from text files in Scala. You can just use an approach like this:
import scala.io.Source val filename = "fileopen.scala" for (line <- Source.fromFile(filename).getLines()) { println(line) }
If you like reading PDFs of presentations, here’s a PDF from a Twitter employee named How We Built Tools That Scale to Millions of Lines of Code.
June 20, 2020: I’ve finished writing 600 pages of the second edition of the Scala Cookbook. The book is projected to be about 720 pages long, so that makes it 83% complete.
And now, I get 24 hours off before I have to ramp up to meet my next deadline.
I recently had a problem with VS Code, Scala Metals, SBT, and Bloop, and VS Code said that I needed to manually run “build import.” Problem is, it didn’t tell me how to run build import.
The short story is that if you need to manually run build import in VS Code, you need to execute the “Import build” command through the VS Code command palette. On a Mac you do this by opening the command palette with the [Cmd][Shift][p]
keystroke, and then start typing the word “import”. When you see “Import build” appear in the drop-down list, click it, and it will run the build-import/import-build process.
Not having a computer science background, I was curious about how to write a Scala function that would find a list of all prime numbers up until some maximum value I supply. I was aware of the Sieve of Eratosthenes, but I didn’t want to implement that, at least not today.
What I ended up doing looks like other Scala prime number solutions you can find on the internet. To make things look a little different, I wrote the code using the current Scala 3 (Dotty) syntax, and the result looks like this:
def isPrime(i: Int): Boolean =
if (i <= 1)
false
else if (i == 2)
true
else
!(2 until i).exists(n => i % n == 0)
As a brief note to self, this is some code I wrote to update my GUI in a JavaFX application:
val runnable = new Runnable { override def run(): Unit = { val htmlPane = new HtmlDialogPane htmlPane.htmlTextArea.setText(html) GuiUtils.showHtmlDialog("Your HTML", htmlPane) } } Platform.runLater(runnable)
These days I’m pretty consistent in how I take notes when reading an online article or blog post, so I’m writing a little “CliffsNotes” app to make that process faster. The basic app consists of a browser on the left, and some controls at the bottom of it so I can rapidly put notes in the notepad on the right.
If you run into a problem where a Scala shell script won’t run on MacOS — it hangs indefinitely without doing anything — hopefully this bug report will help. The solution is to change this line at the beginning of the Scala shell script:
exec scala -savecompiled "$0" "$@"
to this:
exec scala -nocompdaemon -savecompiled "$0" "$@"
I just had this problem with Scala 2.12.x and Java 8 running on MacOS 10.14.4, and I can confirm that adding -nocompdaemon
solved the problem for me.
Note to self: I often get the following Mac LSOpenURLsWithRole failed with error ...
error message when trying to open a Java application I’ve just built on a Mac OS X system:
LSOpenURLsWithRole() failed with error -10810 for the file
This happens when I try to open my new application like this:
I’ve written this before, but when I saw this “pseudocode to Scala code” example in the book Functional Thinking, I thought it was worth mentioning again: If you have trouble grokking the Scala map
method, think of it as being named transform
instead. It transforms an input collection to an output collection, based on the algorithm you supply.
For those coming from the OOP world, I think “transform” is a better word because it is more meaningful, at least initially.
As a brief note, here are a few examples of how I add some keystroke handlers/listeners to a JavaFX project written in Scala:
// add keystroke listeners/handlers to the scene
def addKeystrokeHandlers(scene: Scene, stage: Stage, theMainPane: MainSplitPane): Unit = {
configureCommandMHandler(scene, stage)
// other code was here ...
}
// Minimize (needed to implement manually)
private def configureCommandMHandler(scene: Scene, mainStage: Stage): Unit = {
val keyComboCommandM: KeyCombination = new KeyCodeCombination(
KeyCode.M,
KeyCombination.META_DOWN
)
scene.addEventHandler(KeyEvent.KEY_RELEASED, (event: KeyEvent) => {
if (keyComboCommandM.`match`(event)) {
mainStage.setIconified(true)
}
})
}
The current Dotty (Scala 3) documentation uses the term context parameter in many places, but I haven’t seen a formal definition of it anywhere. After a little bit of research, here’s a Dotty “context parameter” definition that I pieced together from several different pages:
Here in May, 2020, I was just experimenting with Dotty 0.24 (Scala 3), and I just noticed that the Dotty compiler (dotc
) does not have a “strict” flag that’s referred to in the documentation. Instead, when working with open classes, I was able to get the compiler error/warning I was looking for by adding the -source 3.1
flag, as shown in these two examples:
$ dotc -source 3.1 OpenClass* there were 1 feature warning(s); re-run with -feature for details $ dotc -source 3.1 -feature OpenClass* -- Feature Warning: OpenClass2.scala:2:23 -------------------------------------- 2 |class Employee extends Person | ^^^^^^ |Unless class Person is declared 'open', its extension in a separate file should be enabled |by adding the import clause 'import scala.language.adhocExtensions' |or by setting the compiler option -language:adhocExtensions. |See the Scala docs for value scala.language.adhocExtensions for a discussion |why the feature should be explicitly enabled. 1 warning found
In my case I put a Person
class in one file and an Employee
class that extends Person
in another file, and I didn’t expect them to compile without a warning because of what I read in the docs. But then I read that you’ll only get the warning message if the -strict
flag is used with dotc
, and then I further discovered there is no strict
flag, but you can use the command line arguments shown with dotc
to see the warning message.
Note: The docs on this page currently state, “open
is a new modifier in Scala 3. To allow cross compilation between Scala 2.13 and Scala 3.0 without warnings, the feature warning for ad-hoc extensions is produced only under -strict
. It will be produced by default from Scala 3.1 on.”