SlideShare una empresa de Scribd logo
1 de 54
Descargar para leer sin conexión
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

Más contenido relacionado

La actualidad más candente

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
 

La actualidad más candente (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
 

Destacado

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
 

Destacado (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?
 

Similar 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
 

Similar 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
 

Más 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
 

Más 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

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
 
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
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
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
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
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
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number SystemsJheuzeDellosa
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Intelisync
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
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
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 

Último (20)

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
 
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...
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
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
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
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...
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number Systems
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
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
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 

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 del 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