Scala Feature | Eventual Java Feature |
---|---|
lambdas, map(...) , etc. | lambdas, map(...) , etc. |
scala.Option | java.lang.Optional |
case class | record |
pattern matching | enhanced switch |
sealed classes and traits | sealed classes and interfaces |
ubiquitous type inference | inferred var type |
concurrency via Future | concurrency via Future |
concrete trait methods | default methods of interface |
_ for unnamed variables | _ for unnamed variables |
Scala
encourages programmers to express themselves cleanly and concisely with very little boilerplate.
successfully blends multiple programming-language paradigms (functional, object-oriented), enabling whichever style best models a particular problem or domain.
combines flexible syntax with extraordinary type safety, enabling construction of "dialects" that function as domain-specific languages.
Elsewhere...
opaque type Email = String
class BadEmail(msg: String, cause: Throwable = null) extends Exception(msg, cause)
// modified from https://www.regular-expressions.info/email.html
val EmailRegex = """(?i)^\s*([A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,})\s*$""".r
def toEmail(s: String): Email =
s match {
case EmailRegex(trimmed) => trimmed
case _ => throw new BadEmail(s)
}
// toString() will give us back our String
No boxing or runtime overhead! One-line custom Exception!
e.g. "tagless final" style — very optional! love it or hate it!
// from Practical FP in Scala, 2nd Ed, by Gabriel Volpe (2021)
final case class Checkout[F[_]: Background: Logger: MonadThrow: Retry](
payments: PaymentClient[F],
cart: ShoppingCart[F],
orders: Orders[F],
policy: RetryPolicy[F]
){
def process(userId: UserId, card: Card): F[OrderId] =
cart.get(userId).flatMap {
case CartTotal(items, total) =>
for {
its <- ensureNonEmpty(items)
pid <- processPayment(Payment(userId, total, card))
oid <- createOrder(userId, pid, its, total)
_ <- cart.delete(userId).attempt.void
} yield oid
}
def processPayment(in: Payment): F[PaymentId] =
Retry[F] // calls no-arg apply methods of Retry, finds implicit instance
.retry(policy, Retriable.Payments)(payments.process(in))
.adaptError {
case e => PaymentError( Option(e.getMessage).getOrElse("Unknown") )
}
// ...
}
The Scala ecosystem includes libraries for building concurrent, resilient, incredibly scalable services based on transformable "functional effects".
See also Tapir, an infrastructure agnostic endpont definition library.
These are libraries are challenging. End up here, but don't start your Scala journey with these tools, unless you are working with a team to mentor you.
Scala's best kept secret is how beautifully you can accomplish simple things very simply, while getting all the benefits of strong type safety.
Scala's built-in collections library is a superpower.
Li Haoyi writes beautiful libraries that emphasize simplicity. Some examples I enjoy include
Check out all of his libraries here.
Haoyi is also the author of the mill build tool, which like all build tools in Scala is a Swiss Army knife with which you do much more than build.
Haoyi's book Hands-On Scala Programming is a great introduction for programmers interested in getting stuff done fast.
object
, much saner than static
• case class
• infix function notation => operator overloading • opaque types • strong immutability preference • Nothing
as type hierarchy bottom • higher kinded types • apply(...)
method makes anything callable • multiplatform: Scala JVM, Scala JS, Scala native • top-level declarations • if/then
and codeblocks as expressions • strong expressive typing with convenient type inference • rich regex support • multiline String
• rich collections library • flexible, concise syntax • pattern matching with deep destructuring • extension methods • by-name params + multiple arg lists => user-defined control flow constructs • for comprehensions, convenient monad sequencing • String
interpolation • inline, macros, and metaprogramming • typeclasses / ad hoc polymorphism • singleton object
, much saner than static
• case class
• infix function notation => operator overloading • opaque types • strong immutability preference • Nothing
as type hierarchy bottom • higher kinded types • apply(...)
method makes anything callable • multiplatform: Scala JVM, Scala JS, Scala native • top-level declarations • if/then
and codeblocks as expressions • strong expressive typing with convenient type inference • rich regex support • multiline String
• rich collections library • flexible, concise syntax • pattern matching with deep destructuring • extension methods • by-name params + multiple arg lists => user-defined control flow constructs • for comprehensions, convenient monad sequencing
a shell command, minimal-config build tool in the style of golang's multifarious go
command.
will soon become the default scala
command
java
commandsupports compiling, running, packaging, and publishing libraries and applications, and running a REPL
supports graalvm
native image generation
supports scripting in Scala
#!/usr/bin/env -S scala-cli shebang
supports Java code as well and easily as Scala code!
jbang
is the closest competition, but scala-cli
is in some respects easier to use, more
"batteries included"scala-cli
supports Scala tooConsider prototyping your Java projects with scala-cli
HelloWorld.java
in scala-cli
HelloPDF.java
in scala-cli
HelloWorld.scala
poemalyzer
case class
with upickleorg.apache.pdfbox:pdfbox:2.0.28
← Javacom.lihaoyi::upickle:3.1.0
← Scalacom.lihaoyi::requests:0.8.0
← Scalarequests.get(...).text()
upickle.default.{ReadWriter, read}
https://poetrydb.org/random
Quickstart:
Recommended books:
Tools
Images
You can find the build of this presentation here.