Scala Environment

Default environment for Scala

This notebook describes and creates the default Scala environment in Nextjournal. Check out the showcase if you want to see what the environment contains. To see how it’s built, see setup.

Nextjournal's Scala environment uses the Almond Jupyter kernel, and has Scala versions 2.13, 2.12, and 2.11 installed, running on OpenJDK 8.

To change the Scala version (see image below):

  • Scroll to the bottom of the notebook.

  • Expand the Runtime Languages section.

  • Access the ··· menu, then Configure...

  • In the expanded panel, re-select Scala in the top menu.

  • Once loaded, select the Scala version you want to use in the lower menu.

  • Click the Save & Add button to insert a cell with the new Scala runtime.

Showcase

Importing Scala Artifacts

Scala dependencies and compiler plugins can be loaded with either of two syntaxes supported by the Ammonite API:

  • interp.load.ivy() and interp.load.plugin.ivy()

  • import $ivy and import $plugin.$ivy

The former allows for more verbosity and adjusting parameters...

interp.load.ivy(
  // replace with linux-gpu-x86_64 on linux with nvidia gpu or with darwin-cpu-x86_64 on macOS 
  ("org.platanios" %% "tensorflow" % "0.4.1").withClassifier("linux-cpu-x86_64")
)
3.3s
Scala 2.12 (Scala 2.12.8)
Scala

...while the latter syntax allows use of the imported artifact immediately after, within the same code cell:

import $plugin.$ivy.`org.spire-math::kind-projector:0.9.9`
// example of use
trait T[F[_]]
type T2 = T[Either[String, ?]]
3.3s
Scala 2.12 (Scala 2.12.8)
Scala
import $plugin.$ // example of use defined trait T defined type T2

Plotting

Two easy supported graphical libraries are Plotly and Vegas. Plotly currently requires Scala 2.12 or 2.11, while Vegas requires 2.11.

Plotly

The Scala Plotly library supports a subset of the full plotly.js API, including most common 2D plot types as well as multi-axis and subplot capabilities.

import $ivy.`org.plotly-scala::plotly-almond:0.7.0`
import plotly._, plotly.element._, plotly.layout._, plotly.Almond._
def rlist(n:Int) : Sequence = { 
  return for (i <- 1 to n) yield scala.util.Random.nextInt(42) 
}
var plen = 7
val trace1 = Scatter( 1 to plen, rlist(plen) )
val trace2 = Scatter( 1 to plen, rlist(plen), 
  xaxis = AxisReference.X2, yaxis = AxisReference.Y2)
Seq(trace1, trace2).plot(title = "Mulitple Custom Sized Subplots",
    xaxis  = Axis(anchor = AxisAnchor.Reference(AxisReference.Y1),
      domain = (0, 0.45)),
    yaxis  = Axis(anchor = AxisAnchor.Reference(AxisReference.X1)),
    xaxis2 = Axis(anchor = AxisAnchor.Reference(AxisReference.Y2),
      domain = (0.55, 1)),
    yaxis2 = Axis(anchor = AxisAnchor.Reference(AxisReference.X2)))
8.9s
Scala 2.12 (Scala 2.12.8)
Scala

Vegas

The Vegas library is a wrapper around Vega-Lite.

interp.load.ivy("org.vegas-viz" %% "vegas" % "0.3.11")
21.7s
Scala 2.11 (Scala 2.11.12)
Scala

Vegas enables echoing to the console, so we'll override that with a withOut wrapper. For rendering, we'll write the Vega-Lite JSON to a file in /results, to be parsed by Nextjournal's built-in handler.

// disable console echo
scala.Console.withOut(
  new java.io.PrintStream(
    new java.io.FileOutputStream("/dev/null"))) {
import vegas._
import vegas.data.External._
import java.io._
var plot = Vegas("A simple bar chart with embedded data.",
                 width=600,height=300).
  withData(Seq(
    Map("a" -> "A", "b" -> 28), Map("a" -> "B", "b" -> 55), 
    Map("a" -> "C", "b" -> 43), Map("a" -> "D", "b" -> 91), 
    Map("a" -> "E", "b" -> 81), Map("a" -> "F", "b" -> 53),
    Map("a" -> "G", "b" -> 19), Map("a" -> "H", "b" -> 87), 
    Map("a" -> "I", "b" -> 52)
  )).
  encodeX("a", Ordinal).
  encodeY("b", Quantitative).
  mark(Bar)
// Write Vega-Lite JSON to file
val pw = new PrintWriter(new File("/results/out.vl.json"))
pw.write(plot.toJson)
pw.close
// Write Vega-Lite JSON to file
val pr = new PrintWriter(new File("/out.vl.json"))
pr.write(plot.toJson)
pr.close
}
1.2s
Scala 2.11 (Scala 2.11.12)
Scala
Loading viewer…

Setup

Java & Scala

apt-get -qq update
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends \
  openjdk-8-jdk-headless
apt-get clean
rm -r /var/lib/apt/lists/* # Clear package list so it isn't stale
23.8s
Scala (Bash)
java -version
0.8s
Scala (Bash)
mkdir -p /tmp/scalas
cd /tmp/scalas
for scala in $SCALA_VERSION $SCALA_EX_VERSIONS; do
  url="https://downloads.lightbend.com/scala/${scala}/scala-${scala}.tgz"
  list="$url ${list:-}"
done
wget -q --show-progress --progress=bar:force $list
tar -cf /results/scalas.tar scala-*.tgz
rm -r /tmp/scalas
4.8s
Scala (Bash)
scalas.tar
mkdir -p /opt/scalas
cd /opt/scalas
tar -xf NJ__REF_
for scala in scala-*.tgz; do
  tar -zxf $scala
done
ln -sf scala-${SCALA_VERSION} default
rm scala-*.tgz
1.3s
Scala (Bash)
ls -l /opt/scalas
0.8s
Scala (Bash)

Install Coursier.

curl -Lo /opt/scalas/default/bin/coursier https://git.io/coursier-cli
chmod +x /opt/scalas/default/bin/coursier
mkdir -p /opt/scalas/coursier
1.6s
Scala (Bash)
scala -version
2.1s
Scala (Bash)

Almond

Install Jupyter.

pip install --upgrade jupyter jupyter_client
2.0s
Scala (Bash)

Install the Almond Jupyter kernel for all Scala versions.

cd /tmp
almond_inst () {
  coursier bootstrap -r jitpack -i user -o almond \
    -I user:sh.almond:scala-kernel-api_$1:$2 \
    sh.almond:scala-kernel_$1:$2
  ./almond --install --id $3 --display-name "Scala $1"
  rm almond
}
almond_inst 2.13.1  0.9.1 scala213
almond_inst 2.12.10 0.9.1 scala212
almond_inst 2.11.12 0.6.0 scala211
51.0s
Scala (Bash)

Check.

du -hsx /
jupyter kernelspec list
2.4s
Scala (Bash)

Test

case class Hello(i: Int, s0: String)
1.5s
Scala 2.12 (Scala 2.12.8)
Scala
defined class Hello
Hello(3, "Hello Scala!")
0.8s
Scala 2.12 (Scala 2.12.8)
Scala
res6: Hello = Hello(3, "Hello Scala!")
Runtimes (3)
Runtime Languages (2)