Draft scala slides
This commit is contained in:
parent
4f37d64944
commit
cfa49abf4f
457
src/teaching/cse-562/2021sp/slide/2021-02-04-Scala.erb
Normal file
457
src/teaching/cse-562/2021sp/slide/2021-02-04-Scala.erb
Normal file
|
@ -0,0 +1,457 @@
|
|||
---
|
||||
template: templates/cse4562_2021_slides.erb
|
||||
title: Scala Introduction
|
||||
date: Feb 4, 2021
|
||||
---
|
||||
|
||||
<section>
|
||||
<section>
|
||||
<h3>My assumptions</h3>
|
||||
|
||||
<p>(assuming you don't already know Scala)</p>
|
||||
<ul>
|
||||
<li>You know Java (or at least some other object oriented language like C++ or C#)</li>
|
||||
<li>You are familiar with the JVM ecosystem (Java, Kotlin, JRruby, Jython, etc...)</li>
|
||||
</ul>
|
||||
<p class="fragment">This lecture will focus on <u>syntax</u>.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>Some Terms</h3>
|
||||
|
||||
<dl>
|
||||
<dt>Package</dt>
|
||||
<dd>An organizational unit clustering related functionality</dd>
|
||||
<dt>Object</dt>
|
||||
<dd>A 'singleton' class. (Like Java's <b>static</b>)</dd>
|
||||
<dt>Companion Object</dt>
|
||||
<dd>A 'singleton' class implementing methods related to a class</dd>
|
||||
<dt>Case Class</dt>
|
||||
<dd>A class with bonus features (we'll discuss shortly).</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<section>
|
||||
<h3>Hello World</h3>
|
||||
|
||||
<pre><code class="scala">
|
||||
package edu.buffalo.myapp
|
||||
|
||||
import java.io.File
|
||||
import scala.io._
|
||||
|
||||
object MyApp
|
||||
{
|
||||
val message: String = "Hello World"
|
||||
|
||||
def main(args: Array[String]): Unit = {
|
||||
println(message)
|
||||
var stream: Stream = Stream.fromFile(new File("Hello.txt"))
|
||||
for(line <- stream.getLines){
|
||||
println(line)
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
package edu.buffalo.myapp
|
||||
</code></pre>
|
||||
|
||||
Package definitions are exactly like Java.
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
import java.io.File
|
||||
</code></pre>
|
||||
Import statements bring classes into the namespace, making them available for use.
|
||||
|
||||
<div class="fragment">
|
||||
<pre><code class="scala">
|
||||
import scala.io._
|
||||
</code></pre>
|
||||
<tt>'_'</tt> acts like a wildcard in scala.<br/> This is like <tt>import scala.io.*</tt> in Java.
|
||||
</div>
|
||||
|
||||
<div class="fragment">
|
||||
<pre><code class="scala">
|
||||
import java.io.{ File, FileInputStream }
|
||||
</code></pre>
|
||||
Curly braces group class names together as a shorthand when you import multiple classes from the same package.
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
object MyApp {
|
||||
</code></pre>
|
||||
Objects in scala are "singletons". They act like Java classes with only static methods. E.g., you could call <tt>MyApp.main(...)</tt>
|
||||
|
||||
<div class="fragment">
|
||||
<pre><code class="scala">
|
||||
class MyClass(name: String, age: Int) {
|
||||
</code></pre>
|
||||
Classes are defined much like java, except constructor fields are given directly in the class definitions. e.g., you would instantiate this class as <tt>new MyClass("Bob", "102")</tt>.
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
class MyClass(name: String, age: Int)
|
||||
extends MyAncestorClass
|
||||
with MyTrait
|
||||
with MyOtherTrait {
|
||||
</code></pre>
|
||||
|
||||
Inheritence is defined with the <tt>extends</tt> keyword. Like Java, Scala only allows single inheritance, but you add define interfaces and mixins through the <tt>with</tt> keyword.
|
||||
|
||||
<div class="fragment">
|
||||
Objects can also use the <tt>extends</tt> and <tt>with</tt> keywords.
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
trait MyTrait {
|
||||
...
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<p>Traits are (almost) like what Java calls interfaces.</p>
|
||||
|
||||
<p>Unlike Java, a trait can define methods with implementations.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
sealed trait MyTrait {
|
||||
...
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<p>Sealed traits can only be extended/with-ed within the same file.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
val message: String = "Hello World"
|
||||
</code></pre>
|
||||
|
||||
<p>Variables are defined by the <tt>val</tt> or <tt>var</tt> keywords. <tt>val</tt> variables are immutable (like Java's <tt>final</tt> keyword).</p>
|
||||
|
||||
<p>Anywhere a variable is declared, it <u>may</u> be followed by a colon and a type. If omitted, Scala will guess.</p>
|
||||
|
||||
<p class="final">Generally prefer to use <tt>val</tt> wherever you can.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
args: Array[String]
|
||||
</code></pre>
|
||||
|
||||
Generic types use square brackets (<tt>[]</tt>). This is like Java's angle brackets (<tt><></tt>)
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
def main(args: Array[String]): Unit = {
|
||||
</code></pre>
|
||||
|
||||
<p>Define functions with the <tt>def</tt> keyword.</p>
|
||||
|
||||
<p class="fragment">The Colon-Type syntax is used to define the return type. <tt>Unit</tt> is like Java's <tt>void</tt>.</p>
|
||||
|
||||
<p class="fragment">The last line of the function will be returned by default, but you can use <tt>return</tt> to return a value sooner.</p>
|
||||
|
||||
<p class="fragment">Don't forget the <tt>=</tt></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
for(line <- stream.getLines){
|
||||
...
|
||||
}
|
||||
</code></pre>
|
||||
This is scala's iterator syntax (Like Java's <tt>for(line : stream.getLines</tt>)
|
||||
|
||||
<div class="fragment">
|
||||
<pre><code class="scala">
|
||||
stream.getLines.foreach { line =>
|
||||
...
|
||||
}
|
||||
</code></pre>
|
||||
This is another way to write the same thing. <br/>
|
||||
<tt>{ line => ... }</tt> is a <b>lambda</b> function <br/>
|
||||
with <tt>line</tt> as a parameter.
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
class Foo(bar: String) {
|
||||
def apply(baz: String): String =
|
||||
{ bar + " " + baz }
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
The special function <tt>apply</tt> is used to let a class instance (or object) pretend to be a function.
|
||||
|
||||
<pre><code class="scala">
|
||||
val myFoo = new Foo("Abe")
|
||||
val result = myFoo("Lincoln")
|
||||
println(result)
|
||||
</code></pre>
|
||||
prints <tt>Abe Lincoln</tt>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<section>
|
||||
<h3>Collections</h3>
|
||||
|
||||
<p>Scala has a robust library of collection types. Collections are usually referenced by their role.</p>
|
||||
|
||||
<p>Collections are immutable by default, and already in the namespace (no more import <tt>java.util.*</tt>).</p>
|
||||
|
||||
<p class="fragment">Mutable collections live in the <tt>collections.mutable</tt> package if needed.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<ul style="font-size: 80%">
|
||||
<li><tt>Seq[T]</tt>: An ordered sequence of items of type <tt>T</tt>.</li>
|
||||
<li><tt>IndexedSeq[T]</tt>: An ordered sequence of items with O(1) access to individual elements of type <tt>T</tt>.</li>
|
||||
<li><tt>Set[T]</tt>: An unordered collection of unique elements of type <tt>T</tt>.</li>
|
||||
<li><tt>Map[K,V]</tt>: A map from unique keys of type <tt>K</tt> to values of type <tt>V</tt>.</li>
|
||||
<li><tt>Iterator[T]</tt>: A stateful, usually non-repeatable traversal of some collection of elements of type <tt>T</tt></li>
|
||||
<li><tt>Option[T]</tt>: A 0 or 1 element collection of type <tt>T</tt></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
For example <tt>List[T]</tt> and <tt>Array[T]</tt> are both <tt>Seq[T]</tt>, but only the latter is also an <tt>IndexedSeq[T]</tt>.
|
||||
</section>
|
||||
|
||||
<section>
|
||||
You almost never create collections of a specific type. The following all create collections:
|
||||
<pre><code class="scala">
|
||||
val seq = Seq[Int](1, 2, 3, 4)
|
||||
val iseq = IndexedSeq[Int]("Alice", "Bolesław", "Coreline")
|
||||
val map = Map(
|
||||
"Cookie" -> "Chocolate Chip",
|
||||
"Cake" -> "Red Velvet",
|
||||
"Confection" -> "Gulab Jamun"
|
||||
)
|
||||
val opt = if(yes) { Some("A thing") } else { None }
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Scala uses round brackets to access collection elements (remember <tt>apply</tt>?).</p>
|
||||
|
||||
<pre><code class="scala">
|
||||
println(seq(1))
|
||||
println(iseq(2))
|
||||
println(map("Cookie"))
|
||||
</code></pre>
|
||||
|
||||
prints <tt>2</tt>, <tt>Coreline</tt>, and <tt>Chocolate Chip</tt>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>Tuples</h3>
|
||||
|
||||
<pre><code class="scala">
|
||||
val a = (1, "Cookie", "Alice")
|
||||
val b = (2, "Cake", "Bolesław")
|
||||
val all = Seq(a, b)
|
||||
</code></pre>
|
||||
|
||||
<p>Scala also has a "Tuple" type (like Python).</p>
|
||||
|
||||
<p>The type is also parenthesized. The elements above would have type <tt>(Int, String, String)</tt></p>
|
||||
|
||||
<p>Access elements of a tuple by <tt>a._1</tt>, <tt>a._2</tt>, and so forth. <br/>
|
||||
For example <tt>all(1)._2</tt> is <tt>"Cake"</tt></p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
Hint: <tt>x -> y</tt> is shorthand for <tt>(x, y)</tt>. Use this with Map constructors.
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<ul>
|
||||
<li><tt>.map { v => ... }</tt>: Get a new collection by transforming every element of the collection using the lambda.</li>
|
||||
<li><tt>.filter { v => ... }</tt>: Get a new collection by deleting every element of the collection on which the lambda returns false.</li>
|
||||
<li><tt>.flatten</tt>: Assuming the target is a collection of collections, get a new collection by concatenating all of the nested collections.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
all.filter { x => x._2.equals("Cookie") }
|
||||
.map { x => x._3 }
|
||||
</code></pre>
|
||||
Returns <tt>Seq("Alice")</tt>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<ul>
|
||||
<li><tt>.foldLeft(x) { (accum, v) => ... }</tt>: Start with x. Apply the lambda to (x, firstElement) to get a new x. Repeat for every element of the target and return the final value of x.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
all.fold(0) { (accum, v) => accum + v._1 }
|
||||
</code></pre>
|
||||
Returns <tt>3</tt> (the sum of the first tuple field)
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>A Shorthand</h3>
|
||||
<pre><code class="scala">
|
||||
all.fold(0) { _ + _._1 }
|
||||
</code></pre>
|
||||
|
||||
Underscores can <i>sometimes</i> be used as shorthands for lambda functions when a variable is only used once.
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
foo match {
|
||||
case "bar" => println("It was bar")
|
||||
case "baz" => println("Baz be here")
|
||||
case x => println("It was actually "+x+" the whole time!")
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
<p><tt>match</tt> is like a <tt>switch</tt> statement in C/C++, or an <tt>elif</tt> chain in Python...</p>
|
||||
|
||||
<p class="fragment">... but far more powerful.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
val longFoo = foo match {
|
||||
case x:String => x.toLong
|
||||
case y:Int => y * 100l
|
||||
case _ => println("giving up!")
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
You can match based on type.
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
val longFoo = foo match {
|
||||
case (x, y) => x.toLong
|
||||
case y:Int => y * 100l
|
||||
case _ => println("giving up!")
|
||||
}
|
||||
</code></pre>
|
||||
|
||||
You can match based on tuple nesting.
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>Case Classes</h3>
|
||||
<pre><code class="scala">
|
||||
case class Foo(a: String, b: Int)
|
||||
case class Bar(foo: Foo, baz: String)
|
||||
</code></pre>
|
||||
|
||||
<p>Case classes give you a bunch of stuff for "free"</p>
|
||||
|
||||
<pre><code class="scala">
|
||||
val myFoo = Foo("Abe", 1)
|
||||
</code></pre>
|
||||
|
||||
<p>For example, you don't need to use "new" to construct one.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
val name = bar match {
|
||||
case Foo(name, id) => name
|
||||
}
|
||||
</code></pre>
|
||||
<p>But the big perk is that you can use them in match blocks.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<pre><code class="scala">
|
||||
val name = bar match {
|
||||
case Bar(Foo(name, id), baz) => name
|
||||
}
|
||||
</code></pre>
|
||||
<p>... even nested.</p>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Scala uses case classes to make implementing union types easy.</p>
|
||||
<pre><code class="scala">
|
||||
sealed trait MyFooOrBar
|
||||
case class Foo(a: String, b: Int) extends MyFooOrBar
|
||||
case class Bar(foo: Foo, baz: String) extends MyFooOrBar
|
||||
</code></pre>
|
||||
|
||||
<p>Scala's compiler will warn you if you have a match block for a sealed trait that doesn't match every possible case.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<section>
|
||||
<h3>SBT</h3>
|
||||
|
||||
<p>Scala relies on the <a href="https://www.scala-sbt.org/">Scala Build Tool</a> for compilation. It's similar to Maven.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<ul>
|
||||
<li><tt>build.sbt</tt>: Project definition</li>
|
||||
<li><tt>src/</tt>: Source code <ul>
|
||||
<li><tt>main/</tt>: Production code <ul>
|
||||
<li><tt>scala/</tt>: Scala code <ul>
|
||||
<li><tt>package/package/class.scala</tt></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
<li><tt>test/</tt>: Testing code <ul>
|
||||
<li><tt>scala/</tt>: Scala code <ul>
|
||||
<li><tt>package/package/testClass.scala</tt></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
One class should have an <tt>object</tt> with a method defined as:
|
||||
<tt>def main(args: Array[String])</tt>.
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>A simple <tt>build.sbt</tt></h3>
|
||||
|
||||
<pre><code>
|
||||
name := "myproject"
|
||||
version := "0.1"
|
||||
organization := "edu.buffalo.cse.odin",
|
||||
</code></pre>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<p>Many IDEs provide SBT integration. See the Scala <a href="https://docs.scala-lang.org/getting-started/index.html">Getting Started Page</a> and Scala <a href="https://scalameta.org/metals/">Metals Page</a> for more details.</p>
|
||||
</section>
|
||||
</section>
|
|
@ -46,6 +46,8 @@
|
|||
*
|
||||
* This theme is Copyright (C) 2012 Owen Versteeg, https://github.com/StereotypicalApps. It is MIT licensed.
|
||||
* reveal.js is Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
|
||||
*
|
||||
* with edits (C) 2017-2021 Oliver Kennedy.
|
||||
*/
|
||||
/*********************************************
|
||||
* GLOBAL STYLES
|
||||
|
@ -157,6 +159,10 @@ body {
|
|||
bottom: -10px;
|
||||
text-align: right;
|
||||
}
|
||||
.reveal tt {
|
||||
font-family: courier;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Ensure certain elements are never larger than the slide itself */
|
||||
.reveal img, .reveal video, .reveal iframe {
|
||||
|
|
Loading…
Reference in a new issue