Skip to content

Instantly share code, notes, and snippets.

View joel113's full-sized avatar

Johannes Ehm joel113

View GitHub Profile
@joel113
joel113 / Scala2FutureSequence.scala
Created March 12, 2021 16:37
Waiting for the completion of a sequence of scala futures
// waits for the completion of a sequence of futures
for {
_ <- Future.sequence(futureSequence)
} yield somethingElse
case class SortableSeq[A](seq: Seq[A]):
// Transform converts an A to B so you can order using the Bs, but a sequence of As is returned.
// The first two methods show the familiar Scala 2 syntax, which can still be used in 3.0
def sortByImplicits2[B](transform: A => B)(implicit o: Ordering[B]): SortableSeq[A] =
new SortableSeq(seq.sortBy(transform)(o))
def sortByImplicits2[B : Ordering](transform: A => B): SortableSeq[A] =
new SortableSeq(seq.sortBy(transform)(implicitly[Ordering[B]]))
// New Scala 3 using clauses. Note that we use 'using' when passing values explicitly:
def sortBy1a[B](transform: A => B)(using o: Ordering[B]): SortableSeq[A] =
// defines the Ord trait using a type parameters and the methods of the type class
trait Ord[T] {
def compare(x: T, y: T): Int
def (x: T) < (y: T) = compare(x, y) < 0
def (x: T) > (y: T) = compare(x, y) > 0
}
// defines Int as a member of the type class using given
given intOrd: Ord[Int] {
def compare(x: Int, y: Int) =
val a = Array("apple","banana","cherry")
a.mkString // res1: String = applebananacherry
a.mkString(" ") // res2: String = apple banana cherry
a.mkString(", ") // res3: String = apple, banana, cherry
a.mkString("[", ", ", "]") // res4: String = [apple, banana, cherry]
val a = Array(Array("a", "b"), Array("c", "d"))
a.flatten.mkString(", ") // res5: String = a, b, c, d
@joel113
joel113 / Scala3RepeatedParameters.scala
Last active February 27, 2021 14:29
Scala 3 Repeated Parameters
// T* indicates that zero or more values can be provieded, scala holds these in a collection, which is why there is a call
// to ts.size
def count[T](ts: T*): Int = ts.size
val seq = Seq(1,2,3)
count(seq) // Returns 1!
count(seq*) // Returns 3. Use seq* instead of seq: _*
Seq('a', 'b', 'c', 'd', 'e') match {
case Seq('a', tail*) => s"Found a, $tail" // Instead of Seq('a', tail: _*)
case Seq('b', _*) => "Found b" // Instead of Seq('a', _: _*)
@joel113
joel113 / Scala3Exports.scala
Created February 27, 2021 14:27
Scala 3 Exports
class Authenticate(authService: AuthService):
private var authenticated = false
def isAuthenticated: Boolean = authenticated
final def apply(username: String, password: String): Boolean =
authenticated = ...
authenticated
object Service:
def doStuff[T](f: => T): Try[T] = ...
@joel113
joel113 / Scala3Backticks.scala
Created February 27, 2021 14:24
Scala 3 Backticks
import Matrix.`*`
def `1 + 1 == 2 test` = assert(1+1 == 2) // Readable test names!
def contains(i: Int, seq: Seq[Int]): Boolean = seq match {
case Nil => false
case `i` +: _ => true // Must use back ticks, or i is just a new variable that shadows the method argument.
case _ +: tail => contains(i, tail)
}
import scala.util.* // Instead of _
import scala.concurrent.{given, *} // Everything in concurrent, including givens
import java.util.Queue as JQueue // "as" replaces => and no braces needed for one import
import java.util.{HashMap as _, *} // Need {} for a list. Still use _ to hide HashMap
// Input a sequence of any element type and constructs a string:
def tos(seq: Seq[?]): String = seq.mkString("[", ", ", "]")
tos(Vector(1,2,3)) // "[1, 2, 3]"
// mkString makes Strings from Sequences
// cmp. https://learning.oreilly.com/library/view/scala-cookbook/9781449340292/ch10s30.html
// A reminder of given imports, but specifically how to import all
// givens of a parameterized type:
trait Marker[T]
// Case class validation, e.g. of fields in a web form as an example how an underscore is used in Scala 3 for-comprehensions.
case class User(name: String, password: String)
def checkName(user: User): Either[String,User] =
if (user.name.isEmpty) Left("Empty name")
else Right(user)
def checkPassword(user: User): Either[String,User] =
if (user.password.length < 8) Left("Password needs 8+ characters")
else Right(user)