SlideShare uma empresa Scribd logo
1 de 54
Baixar para ler offline
A Field Guide to
DSL Design
Tomer Gabel @ ScalaUA 2016
SETTING THE STAGE
DSLs
• Target specific application domains
• Designers can make more assumptions
• This enables optimized syntax for:
–Conciseness
–Correctness
–Readability
External DSL
• Standalone grammar
• Explicit library/tool
support (lexer,
parser)
• Explicit lifecycle
Examples
• Data querying with SQL:
SELECT s1.article, s1.dealer, s1.price
FROM shop s1
LEFT JOIN shop s2
ON s1.article = s2.article
AND s1.price < s2.price
WHERE s2.article IS NULL;
Examples
• Text formatting with Markdown:
Download
--------
[Markdown 1.0.1][dl] (18 KB) -- 17 Dec
2004
[dl]:
http://daringfireball.net/projects/downloa
ds/Markdown_1.0.1.zip
Internal DSL
• Extends some host language
• Exploits the host to add new syntax
–Within the confines of the host
–Cannot add new syntactic constructs
–Usage is valid code in the host language
• Lifecycle is managed by the host
Examples
• Testing with ScalaTest:
"Empty combinator" should {
"successfully validate an empty sequence" in {
val sample = Seq.empty[String]
val validator = new Empty[Seq[String]]
validator(sample) should be(aSuccess)
}
"render a correct rule violation" in {
val sample = Some("content")
val validator = new Empty[Option[String]]
validator(sample) should failWith("must be empty")
}
}
Examples
• Request routing with Scalatra:
get("/guess/:who") {
params("who") match {
case "Frank" => "You got me!"
case _ => pass()
}
}
Examples
• JSON AST construction with Play:
Json.obj("users" -> Json.arr(
Json.obj("name" -> "bob",
"age" -> 31,
"email" -> "bob@gmail.com"),
Json.obj("name" -> "kiki",
"age" -> 25,
"email" -> JsNull)
))
Shallow Embedding
• Eager evaluation
• An expression results
in effects
• I prefer the term
“imperative DSL”
• Examples:
– Ant tasks
– Assertions
Deep Embedding
• Pure and lazy
• An expression results in
an execution plan
– Prescribes behavior to
subsequent logic
– I prefer the term
“prescriptive DSL”
• Examples:
– Request routing
– Query languages
Summary
• Deep embedding is more powerful
– Evaluation can be deferred, optimized and
repeated
• But more complex to implement:
– Result domain model
– Requires separate execution logic
• Example shown with shallow embedding
STEP 1: KNOW YOUR DOMAIN
Specificity
• Identify your actors
• What actions can they take?
• What objects do they act on?
• What are the consequences of these
actions?
Example: Assertions
• Caller has a piece of data
• And an assumption on its shape
• Caller asserts that the assumption holds
• If not, an exception is thrown
Actor
Object
Object
Action
Consequenc
e
Audience
• Know your users
• Which actor do they represent?
• What consequences do they desire?
• How would they express this desire?
Example: Assertions
• Only one actor and consequence
• But how to best express this desire?
• Start with the user’s perspective:
–We already have some data
–We need a way to define assumptions
–And concise syntax for assertions
Articulation
• Choose a vocabulary:
– Nouns describe objects
– Adjectives qualify objects
– Verbs describe actions
– Adverbs qualify actions
Example: Assertions
• An assertion is a sentence:
“list should be empty”
Object
(noun)
Action
(verb)
Qualifier
(adjective)
Actor is implied
Example: Assertions
• Assumptions (simple)
– empty
– null
– true
– false
– left
– right
– defined
– completed
– …
• Assumptions
(parameterized)
– equalTo
– startWith
– endWith
– contain
– matchRegex
• Modifiers (adverbs)
– not
STEP 2: KNOW YOUR LANGUAGE
Infix Notation
• Also known as “dot free syntax”
• Basic building block in fluent DSLs
• Applies to arity-1 function applications
object.method(parameter)
object method parameter
Infix Notation: Caveats
• Chaining must be done with care
list should be empty
• This is what we expect.
Object Method Parameter
Infix Notation: Caveats
• Chaining must be done with care
list should be empty
• Infix notation is bloody literal!
• What is the type of be?
– Probably not what you meant
Object Method Parameter
Infix Notation: Caveats
• Workaround 1: Contraction
 list shouldBe empty
• Workaround 2: Parentheses
 list should be(empty)
• There is no “right” answer
– It’s an aesthetic preference
Infix Notation: Caveats
• Chaining must be done with care
list should be empty
Object Method Parameter
Infix Notation: Caveats
• Chaining must be done with care
list should be empty
• Must have odd number of participants
• This expression is illegal in Scala!
– (Unless you use postfix operators. Don’t.)
Object Method Parameter
?
Implicit Classes
• Provide an entry point into your DSL
• The extended type is domain-specific
list shouldBe empty
• Also used to lift values into your domain
– More on this later
Known a-priori Extension Method
STEP 3:
PUTTING IT TOGETHER
Foundation
• An assertion is a sentence with the shape:
data shouldBe predicate
• We first need a predicate definition:
trait Predicate[-T] {
def test(data: T): Boolean
def failure: String
}
Foundation
• Next, we need an entry point into our DSL
• Data is the only known entity
• We’ll need to extend it:
implicit class ValidationContext[T](data: T) {
def shouldBe(predicate: Predicate[T]) = ???
}
Foundation
• This is a shallowly-embedded DSL
• Assertion failure has consequences
• In our case, an exception is thrown:
implicit class ValidationContext[T](data: T) {
def shouldBe(predicate: Predicate[T]) =
require(predicate.test(data),
s"Value $data ${predicate.failure}")
}
Foundation
• We can start implementing predicates:
someList shouldBe empty
• A generic solution is fairly obvious:
def empty[T <: Iterable[_]] =
new Predicate[T] {
def test(data: T) = data.isEmpty
def failure = "is not empty"
}
NOW THINGS
GET HAIRY
So far,
so good.
Keywords
• What about booleans?
(3*4 > 10) shouldBe true
• Booleans are reserved keywords
– Can’t provide a def
– Can’t provide an object
• Can we support this syntax?
Keywords
• Workaround: Lift via an implicit class
implicit class BooleanPredicate(b: Boolean)
extends Predicate[Boolean] {
def test(data: Boolean) = data == b
def failure = s"is not $b"
}
Keywords
• There’s a similar issue with null:
val ref: String = null
ref shouldBe null
• But lifting won’t work:
def shouldBe(predicate: Predicate[T]): Unit
• Null is bottom type, extends Predicate[T]
• Implicit search does not take place!
Keywords
• Workaround: Specific method overload
– Should only apply when T is a reference type
implicit class ValidationContext[T](data: T) {
// ...
def shouldBe(n: Null)
(implicit ev: T <:< AnyRef): Unit =
require(data == null,
s"Value $data is not null")
}
Parameterization
• What about parameterized predicates?
3*4 shouldBe equalTo 12
• The equality predicate is simple enough:
def equalTo[T](rhs: T) = new Predicate[T] {
def test(data: T) = data == rhs
def failure = s"is not equal to $rhs"
}
• But we have an even number of parts!
Parameterization
• Workaround: Parentheses
3*4 shouldBe equalTo(12)
• There is no way* to avoid this entirely
– Some sentences are shorter
– Impossible to guarantee the odd part rule
* … that I know of
Grammar Variance
Assumption Example
startWith "ScalaUA" should startWith("Scala")
endWith "ScalaUA" should endWith("UA")
contain List(1, 2, 3) should contain(2)
equalTo 5 shouldBe greaterThan(2)
Can you spot the difference?
Grammar Variance
• We must support predicate families:
– Simple modal form:
List(1, 2, 3) should contain(2)
– Compound subjunctive form:
3*4 shouldBe equalTo(12)
• In other words, we need another verb
Grammar Variance
• A simple solution:
implicit class ValidationContext[T](data: T) {
private def test(predicate: Predicate[T]): Unit =
require(predicate.test(data),
s"Value $data ${predicate.failure}")
def shouldBe(predicate: Predicate[T]): Unit =
test(predicate)
def should(predicate: Predicate[T]): Unit =
test(predicate)
}
Grammar Variance
• A simple solution:
implicit class ValidationContext[T](data: T) {
private def test(predicate: Predicate[T]): Unit =
require(predicate.test(data),
s"Value $data ${predicate.failure}")
def shouldBe(predicate: Predicate[T]): Unit =
test(predicate)
def should(predicate: Predicate[T]): Unit =
test(predicate)
}
Grammar Variance
• Incorrect grammar is legal:
List(1, 2, 3) shouldBe contain(2)
• We lack differentiation between families
• First, define adequate base traits:
trait ModalPredicate[-T] extends Predicate[T]
trait CompoundPredicate[-T] extends Predicate[T]
Grammar Variance
• Next, modify the verbs accordingly:
def should(predicate: ModalPredicate[T])…
def shouldBe(predicate: CompoundPredicate[T])…
• We must also enforce the decision:
– Make the base trait Predicate[T] sealed
– Move it to a separate compilation unit
• Finally, modify all predicates to comply
Negation
• Negation (“not” adverb) is not just syntax
– Predicate[T] must support negation
– Requires a negative failure message
• We must extend the model
• But we must first decide on grammar
Negation
• Modal?
– "Programmers" shouldNot startWith("Java")
– "Programmers" should not(startWith("Java"))
• Compound?
– List(1, 2, 3) shouldNotBe empty
– List(1, 2, 3) shouldBe not(empty)
– List(1, 2, 3) shouldNot be(empty)
• Again, an aesthetic choice
Negation
• Predicate[T] extended with negation:
sealed trait Predicate[-T] {
def test(data: T): Boolean
def failure: String
def failureNeg: String
type Self[-T] <: Predicate[T]
def negate: Self[T]
}
Negative messages
Generic negation
Negation
• Adding negation support to each family:
trait ModalPredicate[-T]
extends Predicate[T] { self ⇒
type Self[-T] = ModalPredicate[T]
def negate = new ModalPredicate[T] {
def test(data: T) = !self.test(data)
def failure = self.failureNeg
def failureNeg = self.failure
}
}
Negation
• Finally, add the not modifier (adverb):
def not[T](pred: Predicate[T]): pred.Self[T] =
pred.negate
• Et voilà:
List(1, 2, 3) shouldBe not(empty)
"Programmers" should not(startWith("Java"))
STEP 4: PROFIT
WE’RE DONE HERE!
Thank you for listening
tomer@tomergabel.com
@tomerg
http://il.linkedin.com/in/tomergabel
Sample code at:
http://tinyurl.com/scala-dsl-guide

Mais conteúdo relacionado

Mais procurados

What To Leave Implicit
What To Leave ImplicitWhat To Leave Implicit
What To Leave ImplicitMartin Odersky
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to ScalaRahul Jain
 
Martin Odersky - Evolution of Scala
Martin Odersky - Evolution of ScalaMartin Odersky - Evolution of Scala
Martin Odersky - Evolution of ScalaScala Italy
 
What To Leave Implicit
What To Leave ImplicitWhat To Leave Implicit
What To Leave ImplicitMartin Odersky
 
Scala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentationScala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentationMartin Odersky
 
Scala : language of the future
Scala : language of the futureScala : language of the future
Scala : language of the futureAnsviaLab
 
flatMap Oslo presentation slides
flatMap Oslo presentation slidesflatMap Oslo presentation slides
flatMap Oslo presentation slidesMartin Odersky
 
The Road to Lambda - Mike Duigou
The Road to Lambda - Mike DuigouThe Road to Lambda - Mike Duigou
The Road to Lambda - Mike Duigoujaxconf
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to ScalaSaleem Ansari
 

Mais procurados (16)

What To Leave Implicit
What To Leave ImplicitWhat To Leave Implicit
What To Leave Implicit
 
Quick introduction to scala
Quick introduction to scalaQuick introduction to scala
Quick introduction to scala
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
Martin Odersky - Evolution of Scala
Martin Odersky - Evolution of ScalaMartin Odersky - Evolution of Scala
Martin Odersky - Evolution of Scala
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
DSLs in JavaScript
DSLs in JavaScriptDSLs in JavaScript
DSLs in JavaScript
 
What To Leave Implicit
What To Leave ImplicitWhat To Leave Implicit
What To Leave Implicit
 
Scala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentationScala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentation
 
Scala : language of the future
Scala : language of the futureScala : language of the future
Scala : language of the future
 
flatMap Oslo presentation slides
flatMap Oslo presentation slidesflatMap Oslo presentation slides
flatMap Oslo presentation slides
 
The Road to Lambda - Mike Duigou
The Road to Lambda - Mike DuigouThe Road to Lambda - Mike Duigou
The Road to Lambda - Mike Duigou
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
Devoxx
DevoxxDevoxx
Devoxx
 
pebble - Building apps on pebble
pebble - Building apps on pebblepebble - Building apps on pebble
pebble - Building apps on pebble
 
C++ chapter 1
C++ chapter 1C++ chapter 1
C++ chapter 1
 
Overview of CoffeeScript
Overview of CoffeeScriptOverview of CoffeeScript
Overview of CoffeeScript
 

Destaque

Simple Scala DSLs
Simple Scala DSLsSimple Scala DSLs
Simple Scala DSLslinxbetter
 
Fantastic DSL in Python
Fantastic DSL in PythonFantastic DSL in Python
Fantastic DSL in Pythonkwatch
 
Writing DSL in Clojure
Writing DSL in ClojureWriting DSL in Clojure
Writing DSL in ClojureMisha Kozik
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Jonas Bonér
 
Why Scala Is Taking Over the Big Data World
Why Scala Is Taking Over the Big Data WorldWhy Scala Is Taking Over the Big Data World
Why Scala Is Taking Over the Big Data WorldDean Wampler
 

Destaque (7)

Simple Scala DSLs
Simple Scala DSLsSimple Scala DSLs
Simple Scala DSLs
 
Scala DSLの作り方
Scala DSLの作り方Scala DSLの作り方
Scala DSLの作り方
 
Fantastic DSL in Python
Fantastic DSL in PythonFantastic DSL in Python
Fantastic DSL in Python
 
Writing DSL in Clojure
Writing DSL in ClojureWriting DSL in Clojure
Writing DSL in Clojure
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)
 
Why Scala Is Taking Over the Big Data World
Why Scala Is Taking Over the Big Data WorldWhy Scala Is Taking Over the Big Data World
Why Scala Is Taking Over the Big Data World
 
Why Scala?
Why Scala?Why Scala?
Why Scala?
 

Semelhante a A Field Guide to DSL Design in Scala

LecccccccccccccProgrammingLecture-09.pdf
LecccccccccccccProgrammingLecture-09.pdfLecccccccccccccProgrammingLecture-09.pdf
LecccccccccccccProgrammingLecture-09.pdfAmirMohamedNabilSale
 
Scala Style by Adform Research (Saulius Valatka)
Scala Style by Adform Research (Saulius Valatka)Scala Style by Adform Research (Saulius Valatka)
Scala Style by Adform Research (Saulius Valatka)Vasil Remeniuk
 
Presentation 4th
Presentation 4thPresentation 4th
Presentation 4thConnex
 
Normalization.pdf
Normalization.pdfNormalization.pdf
Normalization.pdfabhijose1
 
Advanced c c++
Advanced c c++Advanced c c++
Advanced c c++muilevan
 
Code Like Pythonista
Code Like PythonistaCode Like Pythonista
Code Like PythonistaChiyoung Song
 
Object Oriented Programming Principles
Object Oriented Programming PrinciplesObject Oriented Programming Principles
Object Oriented Programming PrinciplesAndrew Ferlitsch
 
Дмитрий Нестерук, Паттерны проектирования в XXI веке
Дмитрий Нестерук, Паттерны проектирования в XXI векеДмитрий Нестерук, Паттерны проектирования в XXI веке
Дмитрий Нестерук, Паттерны проектирования в XXI векеSergey Platonov
 
The Road To Damascus - A Conversion Experience: LotusScript and @Formula to SSJS
The Road To Damascus - A Conversion Experience: LotusScript and @Formula to SSJSThe Road To Damascus - A Conversion Experience: LotusScript and @Formula to SSJS
The Road To Damascus - A Conversion Experience: LotusScript and @Formula to SSJSmfyleman
 
Tdd is Dead, Long Live TDD
Tdd is Dead, Long Live TDDTdd is Dead, Long Live TDD
Tdd is Dead, Long Live TDDJonathan Acker
 
Functional Programming in C#
Functional Programming in C#Functional Programming in C#
Functional Programming in C#Tadeusz Balcer
 
CLEAN CODING AND DEVOPS Final.pptx
CLEAN CODING AND DEVOPS Final.pptxCLEAN CODING AND DEVOPS Final.pptx
CLEAN CODING AND DEVOPS Final.pptxJEEVANANTHAMG6
 
Under the hood of scala implicits (kl10tch 10.03.2015)
Under the hood of scala implicits (kl10tch 10.03.2015)Under the hood of scala implicits (kl10tch 10.03.2015)
Under the hood of scala implicits (kl10tch 10.03.2015)Alexander Podkhalyuzin
 
Design Patterns in Modern C++
Design Patterns in Modern C++Design Patterns in Modern C++
Design Patterns in Modern C++Dmitri Nesteruk
 
Get Testing with tSQLt - SQL In The City Workshop 2014
Get Testing with tSQLt - SQL In The City Workshop 2014Get Testing with tSQLt - SQL In The City Workshop 2014
Get Testing with tSQLt - SQL In The City Workshop 2014Red Gate Software
 
Linq To The Enterprise
Linq To The EnterpriseLinq To The Enterprise
Linq To The EnterpriseDaniel Egan
 

Semelhante a A Field Guide to DSL Design in Scala (20)

LecccccccccccccProgrammingLecture-09.pdf
LecccccccccccccProgrammingLecture-09.pdfLecccccccccccccProgrammingLecture-09.pdf
LecccccccccccccProgrammingLecture-09.pdf
 
Scala Days NYC 2016
Scala Days NYC 2016Scala Days NYC 2016
Scala Days NYC 2016
 
Scala Style by Adform Research (Saulius Valatka)
Scala Style by Adform Research (Saulius Valatka)Scala Style by Adform Research (Saulius Valatka)
Scala Style by Adform Research (Saulius Valatka)
 
Presentation 4th
Presentation 4thPresentation 4th
Presentation 4th
 
Hpd 1
Hpd 1Hpd 1
Hpd 1
 
Normalization.pdf
Normalization.pdfNormalization.pdf
Normalization.pdf
 
Advanced c c++
Advanced c c++Advanced c c++
Advanced c c++
 
NLP from scratch
NLP from scratch NLP from scratch
NLP from scratch
 
Code Like Pythonista
Code Like PythonistaCode Like Pythonista
Code Like Pythonista
 
Object Oriented Programming Principles
Object Oriented Programming PrinciplesObject Oriented Programming Principles
Object Oriented Programming Principles
 
Дмитрий Нестерук, Паттерны проектирования в XXI веке
Дмитрий Нестерук, Паттерны проектирования в XXI векеДмитрий Нестерук, Паттерны проектирования в XXI веке
Дмитрий Нестерук, Паттерны проектирования в XXI веке
 
The Road To Damascus - A Conversion Experience: LotusScript and @Formula to SSJS
The Road To Damascus - A Conversion Experience: LotusScript and @Formula to SSJSThe Road To Damascus - A Conversion Experience: LotusScript and @Formula to SSJS
The Road To Damascus - A Conversion Experience: LotusScript and @Formula to SSJS
 
Tdd is Dead, Long Live TDD
Tdd is Dead, Long Live TDDTdd is Dead, Long Live TDD
Tdd is Dead, Long Live TDD
 
Functional Programming in C#
Functional Programming in C#Functional Programming in C#
Functional Programming in C#
 
CLEAN CODING AND DEVOPS Final.pptx
CLEAN CODING AND DEVOPS Final.pptxCLEAN CODING AND DEVOPS Final.pptx
CLEAN CODING AND DEVOPS Final.pptx
 
Under the hood of scala implicits (kl10tch 10.03.2015)
Under the hood of scala implicits (kl10tch 10.03.2015)Under the hood of scala implicits (kl10tch 10.03.2015)
Under the hood of scala implicits (kl10tch 10.03.2015)
 
Design Patterns in Modern C++
Design Patterns in Modern C++Design Patterns in Modern C++
Design Patterns in Modern C++
 
Database intro
Database introDatabase intro
Database intro
 
Get Testing with tSQLt - SQL In The City Workshop 2014
Get Testing with tSQLt - SQL In The City Workshop 2014Get Testing with tSQLt - SQL In The City Workshop 2014
Get Testing with tSQLt - SQL In The City Workshop 2014
 
Linq To The Enterprise
Linq To The EnterpriseLinq To The Enterprise
Linq To The Enterprise
 

Mais de Tomer Gabel

How shit works: Time
How shit works: TimeHow shit works: Time
How shit works: TimeTomer Gabel
 
Nondeterministic Software for the Rest of Us
Nondeterministic Software for the Rest of UsNondeterministic Software for the Rest of Us
Nondeterministic Software for the Rest of UsTomer Gabel
 
Slaying Sacred Cows: Deconstructing Dependency Injection
Slaying Sacred Cows: Deconstructing Dependency InjectionSlaying Sacred Cows: Deconstructing Dependency Injection
Slaying Sacred Cows: Deconstructing Dependency InjectionTomer Gabel
 
An Abridged Guide to Event Sourcing
An Abridged Guide to Event SourcingAn Abridged Guide to Event Sourcing
An Abridged Guide to Event SourcingTomer Gabel
 
How shit works: the CPU
How shit works: the CPUHow shit works: the CPU
How shit works: the CPUTomer Gabel
 
How Shit Works: Storage
How Shit Works: StorageHow Shit Works: Storage
How Shit Works: StorageTomer Gabel
 
Java 8 and Beyond, a Scala Story
Java 8 and Beyond, a Scala StoryJava 8 and Beyond, a Scala Story
Java 8 and Beyond, a Scala StoryTomer Gabel
 
The Wix Microservice Stack
The Wix Microservice StackThe Wix Microservice Stack
The Wix Microservice StackTomer Gabel
 
Scala Refactoring for Fun and Profit (Japanese subtitles)
Scala Refactoring for Fun and Profit (Japanese subtitles)Scala Refactoring for Fun and Profit (Japanese subtitles)
Scala Refactoring for Fun and Profit (Japanese subtitles)Tomer Gabel
 
Scala Refactoring for Fun and Profit
Scala Refactoring for Fun and ProfitScala Refactoring for Fun and Profit
Scala Refactoring for Fun and ProfitTomer Gabel
 
Onboarding at Scale
Onboarding at ScaleOnboarding at Scale
Onboarding at ScaleTomer Gabel
 
Scala in the Wild
Scala in the WildScala in the Wild
Scala in the WildTomer Gabel
 
Speaking Scala: Refactoring for Fun and Profit (Workshop)
Speaking Scala: Refactoring for Fun and Profit (Workshop)Speaking Scala: Refactoring for Fun and Profit (Workshop)
Speaking Scala: Refactoring for Fun and Profit (Workshop)Tomer Gabel
 
Put Your Thinking CAP On
Put Your Thinking CAP OnPut Your Thinking CAP On
Put Your Thinking CAP OnTomer Gabel
 
Leveraging Scala Macros for Better Validation
Leveraging Scala Macros for Better ValidationLeveraging Scala Macros for Better Validation
Leveraging Scala Macros for Better ValidationTomer Gabel
 
Functional Leap of Faith (Keynote at JDay Lviv 2014)
Functional Leap of Faith (Keynote at JDay Lviv 2014)Functional Leap of Faith (Keynote at JDay Lviv 2014)
Functional Leap of Faith (Keynote at JDay Lviv 2014)Tomer Gabel
 
Scala Back to Basics: Type Classes
Scala Back to Basics: Type ClassesScala Back to Basics: Type Classes
Scala Back to Basics: Type ClassesTomer Gabel
 
5 Bullets to Scala Adoption
5 Bullets to Scala Adoption5 Bullets to Scala Adoption
5 Bullets to Scala AdoptionTomer Gabel
 
Nashorn: JavaScript that doesn’t suck (ILJUG)
Nashorn: JavaScript that doesn’t suck (ILJUG)Nashorn: JavaScript that doesn’t suck (ILJUG)
Nashorn: JavaScript that doesn’t suck (ILJUG)Tomer Gabel
 
Ponies and Unicorns With Scala
Ponies and Unicorns With ScalaPonies and Unicorns With Scala
Ponies and Unicorns With ScalaTomer Gabel
 

Mais de Tomer Gabel (20)

How shit works: Time
How shit works: TimeHow shit works: Time
How shit works: Time
 
Nondeterministic Software for the Rest of Us
Nondeterministic Software for the Rest of UsNondeterministic Software for the Rest of Us
Nondeterministic Software for the Rest of Us
 
Slaying Sacred Cows: Deconstructing Dependency Injection
Slaying Sacred Cows: Deconstructing Dependency InjectionSlaying Sacred Cows: Deconstructing Dependency Injection
Slaying Sacred Cows: Deconstructing Dependency Injection
 
An Abridged Guide to Event Sourcing
An Abridged Guide to Event SourcingAn Abridged Guide to Event Sourcing
An Abridged Guide to Event Sourcing
 
How shit works: the CPU
How shit works: the CPUHow shit works: the CPU
How shit works: the CPU
 
How Shit Works: Storage
How Shit Works: StorageHow Shit Works: Storage
How Shit Works: Storage
 
Java 8 and Beyond, a Scala Story
Java 8 and Beyond, a Scala StoryJava 8 and Beyond, a Scala Story
Java 8 and Beyond, a Scala Story
 
The Wix Microservice Stack
The Wix Microservice StackThe Wix Microservice Stack
The Wix Microservice Stack
 
Scala Refactoring for Fun and Profit (Japanese subtitles)
Scala Refactoring for Fun and Profit (Japanese subtitles)Scala Refactoring for Fun and Profit (Japanese subtitles)
Scala Refactoring for Fun and Profit (Japanese subtitles)
 
Scala Refactoring for Fun and Profit
Scala Refactoring for Fun and ProfitScala Refactoring for Fun and Profit
Scala Refactoring for Fun and Profit
 
Onboarding at Scale
Onboarding at ScaleOnboarding at Scale
Onboarding at Scale
 
Scala in the Wild
Scala in the WildScala in the Wild
Scala in the Wild
 
Speaking Scala: Refactoring for Fun and Profit (Workshop)
Speaking Scala: Refactoring for Fun and Profit (Workshop)Speaking Scala: Refactoring for Fun and Profit (Workshop)
Speaking Scala: Refactoring for Fun and Profit (Workshop)
 
Put Your Thinking CAP On
Put Your Thinking CAP OnPut Your Thinking CAP On
Put Your Thinking CAP On
 
Leveraging Scala Macros for Better Validation
Leveraging Scala Macros for Better ValidationLeveraging Scala Macros for Better Validation
Leveraging Scala Macros for Better Validation
 
Functional Leap of Faith (Keynote at JDay Lviv 2014)
Functional Leap of Faith (Keynote at JDay Lviv 2014)Functional Leap of Faith (Keynote at JDay Lviv 2014)
Functional Leap of Faith (Keynote at JDay Lviv 2014)
 
Scala Back to Basics: Type Classes
Scala Back to Basics: Type ClassesScala Back to Basics: Type Classes
Scala Back to Basics: Type Classes
 
5 Bullets to Scala Adoption
5 Bullets to Scala Adoption5 Bullets to Scala Adoption
5 Bullets to Scala Adoption
 
Nashorn: JavaScript that doesn’t suck (ILJUG)
Nashorn: JavaScript that doesn’t suck (ILJUG)Nashorn: JavaScript that doesn’t suck (ILJUG)
Nashorn: JavaScript that doesn’t suck (ILJUG)
 
Ponies and Unicorns With Scala
Ponies and Unicorns With ScalaPonies and Unicorns With Scala
Ponies and Unicorns With Scala
 

Último

HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 

Último (20)

HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 

A Field Guide to DSL Design in Scala

  • 1. A Field Guide to DSL Design Tomer Gabel @ ScalaUA 2016
  • 3. DSLs • Target specific application domains • Designers can make more assumptions • This enables optimized syntax for: –Conciseness –Correctness –Readability
  • 4. External DSL • Standalone grammar • Explicit library/tool support (lexer, parser) • Explicit lifecycle
  • 5. Examples • Data querying with SQL: SELECT s1.article, s1.dealer, s1.price FROM shop s1 LEFT JOIN shop s2 ON s1.article = s2.article AND s1.price < s2.price WHERE s2.article IS NULL;
  • 6. Examples • Text formatting with Markdown: Download -------- [Markdown 1.0.1][dl] (18 KB) -- 17 Dec 2004 [dl]: http://daringfireball.net/projects/downloa ds/Markdown_1.0.1.zip
  • 7. Internal DSL • Extends some host language • Exploits the host to add new syntax –Within the confines of the host –Cannot add new syntactic constructs –Usage is valid code in the host language • Lifecycle is managed by the host
  • 8. Examples • Testing with ScalaTest: "Empty combinator" should { "successfully validate an empty sequence" in { val sample = Seq.empty[String] val validator = new Empty[Seq[String]] validator(sample) should be(aSuccess) } "render a correct rule violation" in { val sample = Some("content") val validator = new Empty[Option[String]] validator(sample) should failWith("must be empty") } }
  • 9. Examples • Request routing with Scalatra: get("/guess/:who") { params("who") match { case "Frank" => "You got me!" case _ => pass() } }
  • 10. Examples • JSON AST construction with Play: Json.obj("users" -> Json.arr( Json.obj("name" -> "bob", "age" -> 31, "email" -> "bob@gmail.com"), Json.obj("name" -> "kiki", "age" -> 25, "email" -> JsNull) ))
  • 11. Shallow Embedding • Eager evaluation • An expression results in effects • I prefer the term “imperative DSL” • Examples: – Ant tasks – Assertions
  • 12. Deep Embedding • Pure and lazy • An expression results in an execution plan – Prescribes behavior to subsequent logic – I prefer the term “prescriptive DSL” • Examples: – Request routing – Query languages
  • 13. Summary • Deep embedding is more powerful – Evaluation can be deferred, optimized and repeated • But more complex to implement: – Result domain model – Requires separate execution logic • Example shown with shallow embedding
  • 14. STEP 1: KNOW YOUR DOMAIN
  • 15. Specificity • Identify your actors • What actions can they take? • What objects do they act on? • What are the consequences of these actions?
  • 16. Example: Assertions • Caller has a piece of data • And an assumption on its shape • Caller asserts that the assumption holds • If not, an exception is thrown Actor Object Object Action Consequenc e
  • 17. Audience • Know your users • Which actor do they represent? • What consequences do they desire? • How would they express this desire?
  • 18. Example: Assertions • Only one actor and consequence • But how to best express this desire? • Start with the user’s perspective: –We already have some data –We need a way to define assumptions –And concise syntax for assertions
  • 19. Articulation • Choose a vocabulary: – Nouns describe objects – Adjectives qualify objects – Verbs describe actions – Adverbs qualify actions
  • 20. Example: Assertions • An assertion is a sentence: “list should be empty” Object (noun) Action (verb) Qualifier (adjective) Actor is implied
  • 21. Example: Assertions • Assumptions (simple) – empty – null – true – false – left – right – defined – completed – … • Assumptions (parameterized) – equalTo – startWith – endWith – contain – matchRegex • Modifiers (adverbs) – not
  • 22. STEP 2: KNOW YOUR LANGUAGE
  • 23. Infix Notation • Also known as “dot free syntax” • Basic building block in fluent DSLs • Applies to arity-1 function applications object.method(parameter) object method parameter
  • 24. Infix Notation: Caveats • Chaining must be done with care list should be empty • This is what we expect. Object Method Parameter
  • 25. Infix Notation: Caveats • Chaining must be done with care list should be empty • Infix notation is bloody literal! • What is the type of be? – Probably not what you meant Object Method Parameter
  • 26. Infix Notation: Caveats • Workaround 1: Contraction  list shouldBe empty • Workaround 2: Parentheses  list should be(empty) • There is no “right” answer – It’s an aesthetic preference
  • 27. Infix Notation: Caveats • Chaining must be done with care list should be empty Object Method Parameter
  • 28. Infix Notation: Caveats • Chaining must be done with care list should be empty • Must have odd number of participants • This expression is illegal in Scala! – (Unless you use postfix operators. Don’t.) Object Method Parameter ?
  • 29. Implicit Classes • Provide an entry point into your DSL • The extended type is domain-specific list shouldBe empty • Also used to lift values into your domain – More on this later Known a-priori Extension Method
  • 30. STEP 3: PUTTING IT TOGETHER
  • 31. Foundation • An assertion is a sentence with the shape: data shouldBe predicate • We first need a predicate definition: trait Predicate[-T] { def test(data: T): Boolean def failure: String }
  • 32. Foundation • Next, we need an entry point into our DSL • Data is the only known entity • We’ll need to extend it: implicit class ValidationContext[T](data: T) { def shouldBe(predicate: Predicate[T]) = ??? }
  • 33. Foundation • This is a shallowly-embedded DSL • Assertion failure has consequences • In our case, an exception is thrown: implicit class ValidationContext[T](data: T) { def shouldBe(predicate: Predicate[T]) = require(predicate.test(data), s"Value $data ${predicate.failure}") }
  • 34. Foundation • We can start implementing predicates: someList shouldBe empty • A generic solution is fairly obvious: def empty[T <: Iterable[_]] = new Predicate[T] { def test(data: T) = data.isEmpty def failure = "is not empty" }
  • 35. NOW THINGS GET HAIRY So far, so good.
  • 36. Keywords • What about booleans? (3*4 > 10) shouldBe true • Booleans are reserved keywords – Can’t provide a def – Can’t provide an object • Can we support this syntax?
  • 37. Keywords • Workaround: Lift via an implicit class implicit class BooleanPredicate(b: Boolean) extends Predicate[Boolean] { def test(data: Boolean) = data == b def failure = s"is not $b" }
  • 38. Keywords • There’s a similar issue with null: val ref: String = null ref shouldBe null • But lifting won’t work: def shouldBe(predicate: Predicate[T]): Unit • Null is bottom type, extends Predicate[T] • Implicit search does not take place!
  • 39. Keywords • Workaround: Specific method overload – Should only apply when T is a reference type implicit class ValidationContext[T](data: T) { // ... def shouldBe(n: Null) (implicit ev: T <:< AnyRef): Unit = require(data == null, s"Value $data is not null") }
  • 40. Parameterization • What about parameterized predicates? 3*4 shouldBe equalTo 12 • The equality predicate is simple enough: def equalTo[T](rhs: T) = new Predicate[T] { def test(data: T) = data == rhs def failure = s"is not equal to $rhs" } • But we have an even number of parts!
  • 41. Parameterization • Workaround: Parentheses 3*4 shouldBe equalTo(12) • There is no way* to avoid this entirely – Some sentences are shorter – Impossible to guarantee the odd part rule * … that I know of
  • 42. Grammar Variance Assumption Example startWith "ScalaUA" should startWith("Scala") endWith "ScalaUA" should endWith("UA") contain List(1, 2, 3) should contain(2) equalTo 5 shouldBe greaterThan(2) Can you spot the difference?
  • 43. Grammar Variance • We must support predicate families: – Simple modal form: List(1, 2, 3) should contain(2) – Compound subjunctive form: 3*4 shouldBe equalTo(12) • In other words, we need another verb
  • 44. Grammar Variance • A simple solution: implicit class ValidationContext[T](data: T) { private def test(predicate: Predicate[T]): Unit = require(predicate.test(data), s"Value $data ${predicate.failure}") def shouldBe(predicate: Predicate[T]): Unit = test(predicate) def should(predicate: Predicate[T]): Unit = test(predicate) }
  • 45. Grammar Variance • A simple solution: implicit class ValidationContext[T](data: T) { private def test(predicate: Predicate[T]): Unit = require(predicate.test(data), s"Value $data ${predicate.failure}") def shouldBe(predicate: Predicate[T]): Unit = test(predicate) def should(predicate: Predicate[T]): Unit = test(predicate) }
  • 46. Grammar Variance • Incorrect grammar is legal: List(1, 2, 3) shouldBe contain(2) • We lack differentiation between families • First, define adequate base traits: trait ModalPredicate[-T] extends Predicate[T] trait CompoundPredicate[-T] extends Predicate[T]
  • 47. Grammar Variance • Next, modify the verbs accordingly: def should(predicate: ModalPredicate[T])… def shouldBe(predicate: CompoundPredicate[T])… • We must also enforce the decision: – Make the base trait Predicate[T] sealed – Move it to a separate compilation unit • Finally, modify all predicates to comply
  • 48. Negation • Negation (“not” adverb) is not just syntax – Predicate[T] must support negation – Requires a negative failure message • We must extend the model • But we must first decide on grammar
  • 49. Negation • Modal? – "Programmers" shouldNot startWith("Java") – "Programmers" should not(startWith("Java")) • Compound? – List(1, 2, 3) shouldNotBe empty – List(1, 2, 3) shouldBe not(empty) – List(1, 2, 3) shouldNot be(empty) • Again, an aesthetic choice
  • 50. Negation • Predicate[T] extended with negation: sealed trait Predicate[-T] { def test(data: T): Boolean def failure: String def failureNeg: String type Self[-T] <: Predicate[T] def negate: Self[T] } Negative messages Generic negation
  • 51. Negation • Adding negation support to each family: trait ModalPredicate[-T] extends Predicate[T] { self ⇒ type Self[-T] = ModalPredicate[T] def negate = new ModalPredicate[T] { def test(data: T) = !self.test(data) def failure = self.failureNeg def failureNeg = self.failure } }
  • 52. Negation • Finally, add the not modifier (adverb): def not[T](pred: Predicate[T]): pred.Self[T] = pred.negate • Et voilà: List(1, 2, 3) shouldBe not(empty) "Programmers" should not(startWith("Java"))
  • 54. WE’RE DONE HERE! Thank you for listening tomer@tomergabel.com @tomerg http://il.linkedin.com/in/tomergabel Sample code at: http://tinyurl.com/scala-dsl-guide

Notas do Editor

  1. Photo source: Renaud Camus on Flickr https://www.flickr.com/photos/renaud-camus/10940175254
  2. Image source: Brooke Hoyer at Flickr, https://www.flickr.com/photos/brookehoyer/15003017355
  3. Photo source: Chau Doan / World Bank at Flickr https://www.flickr.com/photos/worldbank/8880738432
  4. Photo source: Pedro Moura Pinheiro at Flickr https://www.flickr.com/photos/pedromourapinheiro/5075612989
  5. Photo source: Steve Corey at Flickr https://www.flickr.com/photos/stevecorey/9942526435