SlideShare a Scribd company logo
Leveraging Scala 
Macros for Better 
Validation 
Tomer Gabel, Wix 
September 2014
I Have a Dream 
• Definition: 
case class Person( 
firstName: String, 
lastName: String 
) 
implicit val personValidator = 
validator[Person] { p ⇒ 
p.firstName is notEmpty 
p.lastName is notEmpty 
}
I Have a Dream 
• Usage: 
validate(Person("Wernher", "von Braun”)) 
== Success 
validate(Person("", "No First Name”)) 
== Failure(Set(RuleViolation( 
value = "", 
constraint = "must not be empty", 
description = "firstName" 
)))
ENTER: ACCORD.
Basic Architecture 
API 
Combinator Library 
DSL 
Macro Transformation
The Accord API 
• Validation can succeed or fail 
• A failure comprises one or more violations 
sealed trait Result 
case object Success extends Result 
case class Failure(violations: Set[Violation]) 
extends Result 
• The validator typeclass: 
trait Validator[-T] extends (T ⇒ Result)
Why Macros? 
• Quick refresher: 
implicit val personValidator = 
validator[Person] { p ⇒ 
p.firstName is notEmpty 
p.lastName is notEmpty 
} 
Implicit “and” 
Automatic description 
generation
Full Disclosure 
Macros are experimental 
Macros are hard 
I will gloss over a lot of details 
… and simplify a lot of things
Abstract Syntax Trees 
• An intermediate representation of code 
– Structure (semantics) 
– Metadata (e.g. types) – optional! 
• Provided by the reflection API 
• Alas, mutable 
– Until Dotty comes along
Abstract Syntax Trees 
def method(param: String) = param.toUpperCase
Abstract Syntax Trees 
def method(param: String) = param.toUpperCase 
Apply( 
Select( 
Ident(newTermName("param")), 
newTermName("toUpperCase") 
), 
List() 
)
Abstract Syntax Trees 
def method(param: String) = param.toUpperCase 
ValDef( 
Modifiers(PARAM), 
newTermName("param"), 
Select( 
Ident(scala.Predef), 
newTypeName("String") 
), 
EmptyTree // Value 
)
Abstract Syntax Trees 
def method(param: String) = param.toUpperCase 
DefDef( 
Modifiers(), 
newTermName("method"), 
List(), // Type parameters 
List( // Parameter lists 
List(parameter) 
), 
TypeTree(), // Return type 
implementation 
)
Def Macro 101 
• Looks and acts like a normal function 
def radix(s: String, base: Int): Long 
val result = radix("2710", 16) 
// result == 10000L 
• Two fundamental differences: 
– Invoked at compile time instead of runtime 
– Operates on ASTs instead of values
Def Macro 101 
• Needs a signature & implementation 
def radix(s: String, base: Int): Long = 
macro radixImpl 
def radixImpl 
Values 
(c: Context) 
(s: c.Expr[String], base: c.Expr[Int]): 
c.Expr[Long] 
ASTs
Def Macro 101 
• What’s in a context? 
– Enclosures (position) 
– Error handling 
– Logging 
– Infrastructure
Basic Architecture 
API 
Combinator Library 
DSL 
Macro Transformation
Overview 
implicit val personValidator = 
validator[Person] { p ⇒ 
p.firstName is notEmpty 
p.lastName is notEmpty 
} 
• The validator macro: 
Macro Application 
Validation Rules 
– Rewrites each rule by addition a description 
– Aggregates rules with an and combinator
Signature 
def validator[T](v: T ⇒ Unit): Validator[T] = 
macro ValidationTransform.apply[T] 
def apply[T : c.WeakTypeTag] 
(c: Context) 
(v: c.Expr[T ⇒ Unit]): 
c.Expr[Validator[T]]
Brace 
yourselves 
Here be dragons
Walkthrough 
Search for rule 
Process rule 
Generate description 
Rewrite rule
Walkthrough 
Search for rule 
Process rule 
Generate description 
Rewrite rule
Search for Rule 
• A rule is an expression of type Validator[_] 
• We search by: 
– Recursively pattern matching over an AST 
– On match, apply a function on the subtree 
– Encoded as a partial function from Tree to R
Search for Rule 
def collectFromPattern[R] 
(tree: Tree) 
(pattern: PartialFunction[Tree, R]): List[R] = { 
var found: Vector[R] = Vector.empty 
new Traverser { 
override def traverse(subtree: Tree) { 
if (pattern isDefinedAt subtree) 
found = found :+ pattern(subtree) 
else 
super.traverse(subtree) 
} 
}.traverse(tree) 
found.toList 
}
Search for Rule 
• Putting it together: 
case class Rule(ouv: Tree, validation: Tree) 
def processRule(subtree: Tree): Rule = ??? 
def findRules(body: Tree): Seq[Rule] = { 
val validatorType = typeOf[Validator[_]] 
collectFromPattern(body) { 
case subtree if subtree.tpe <:< validatorType ⇒ 
processRule(subtree) 
} 
}
Walkthrough 
Search for rule 
Process rule 
Generate description 
Rewrite rule
Process Rule 
• The user writes: 
p.firstName is notEmpty 
• The compiler emits: 
Type: Validator[_] 
Contextualizer(p.firstName).is(notEmpty) 
Object Under Validation 
(OUV) 
Validation
Process Rule 
Contextualizer(p.firstName).is(notEmpty) 
• This is effectively an Apply AST node 
• The left-hand side is the OUV 
• The right-hand side is the validation 
– But we can use the entire expression! 
• Contextualizer is our entry point
Process Rule 
Contextualizer(p.firstName).is(notEmpty) 
Apply 
Select 
Apply 
TypeApply 
Contextualizer 
String 
Select 
Ident(“p”) 
firstName 
is 
notEmpty
Process Rule 
Contextualizer(p.firstName).is(notEmpty) 
Apply 
Select 
Apply 
TypeApply 
Contextualizer 
String 
Select 
Ident(“p”) 
firstName 
is 
notEmpty
Process Rule 
Apply 
TypeApply 
Contextualizer 
String 
Select 
Ident(“p”) 
firstName
Process Rule 
Apply 
TypeApply 
Contextualizer 
Φ 
Select 
Ident(“p”) 
firstName
Process Rule 
Apply 
TypeApply 
Contextualizer 
Φ 
Select 
Ident(“p”) 
firstName
Process Rule 
Apply 
TypeApply 
Contextualizer 
Φ 
OUV 
Φ 
Φ 
case Apply(TypeApply(Select(_, `term`), _), ouv :: Nil) ⇒
Process Rule 
• Putting it together: 
val term = newTermName("Contextualizer") 
def processRule(subtree: Tree): Rule = 
extractFromPattern(subtree) { 
case Apply(TypeApply(Select(_, `term`), _), ouv :: Nil) ⇒ 
Rule(ouv, subtree) 
} getOrElse abort(subtree.pos, "Not a valid rule")
Walkthrough 
Search for rule 
Process rule 
Generate description 
Rewrite rule
Generate Description 
Contextualizer(p.firstName).is(notEmpty) 
• Consider the object under validation 
• In this example, it is a field accessor 
• The function prototype is the entry point 
Select 
Ident(“p”) 
firstName 
validator[Person] { p ⇒ 
... 
}
Generate Description 
• How to get at the prototype? 
• The macro signature includes the rule block: 
def apply[T : c.WeakTypeTag] 
(c: Context) 
(v: c.Expr[T ⇒ Unit]): 
c.Expr[Validator[T]] 
• To extract the prototype: 
val Function(prototype :: Nil, body) = 
v.tree // prototype: ValDef
Generate Description 
• Putting it all together: 
def describeRule(rule: ValidationRule) = { 
val para = prototype.name 
val Select(Ident(`para`), description) = 
rule.ouv 
description.toString 
}
Walkthrough 
Search for rule 
Process rule 
Generate description 
Rewrite rule
Rewrite Rule 
• We’re constructing a Validator[Person] 
• A rule is itself a Validator[T]. For example: 
Contextualizer(p.firstName).is(notEmpty) 
• We need to: 
– Lift the rule to validate the enclosing type 
– Apply the description to the result
Quasiquotes 
• Provide an easy way to construct ASTs: 
Apply( 
Select( 
Ident(newTermName"x"), 
newTermName("$plus") 
), 
List( 
Ident(newTermName("y")) 
) 
) 
q"x + y"
Quasiquotes 
• Quasiquotes also let you splice trees: 
def greeting(whom: c.Expr[String]) = 
q"Hello "$whom"!" 
• And can be used in pattern matching: 
val q"$x + $y" = tree
Rewrite Rule 
Contextualizer(p.firstName).is(notEmpty) 
new Validator[Person] { 
def apply(p: Person) = { 
val validation = 
Contextualizer(p.firstName).is(notEmpty) 
validation(p.firstName) withDescription "firstName" 
} 
}
Rewrite Rule 
• Putting it all together: 
def rewriteRule(rule: ValidationRule) = { 
val desc = describeRule(rule) 
val tree = Literal(Constant(desc)) 
q""" 
new com.wix.accord.Validator[${weakTypeOf[T]}] { 
def apply($prototype) = { 
val validation = ${rule.validation} 
validation(${rule.ouv}) withDescription $tree 
} 
} 
""" 
}
The Last Mile
Epilogue 
• The finishing touch: and combinator 
def apply[T : c.WeakTypeTag] 
(c: Context) 
(v: c.Expr[T ⇒ Unit]): c.Expr[Validator[T]] = { 
val Function(prototype :: Nil, body) = v.tree 
// ... all the stuff we just discussed 
val rules = findRules(body) map rewriteRule 
val result = 
q"new com.wix.accord.combinators.And(..$rules)" 
c.Expr[Validator[T]](result) 
}
tomer@tomergabel.com 
@tomerg 
http://il.linkedin.com/in/tomergabel 
Check out Accord at: 
http://github.com/wix/accord 
Thank you for listening 
WE’RE DONE 
HERE!
Ad

More Related Content

What's hot (17)

Gorm
GormGorm
Gorm
NexThoughts Technologies
 
The Ring programming language version 1.8 book - Part 41 of 202
The Ring programming language version 1.8 book - Part 41 of 202The Ring programming language version 1.8 book - Part 41 of 202
The Ring programming language version 1.8 book - Part 41 of 202
Mahmoud Samir Fayed
 
Postgres rules
Postgres rulesPostgres rules
Postgres rules
gisborne
 
Java Cheat Sheet
Java Cheat SheetJava Cheat Sheet
Java Cheat Sheet
Saeid Zebardast
 
The Ring programming language version 1.5.1 book - Part 34 of 180
The Ring programming language version 1.5.1 book - Part 34 of 180The Ring programming language version 1.5.1 book - Part 34 of 180
The Ring programming language version 1.5.1 book - Part 34 of 180
Mahmoud Samir Fayed
 
Python : Dictionaries
Python : DictionariesPython : Dictionaries
Python : Dictionaries
Emertxe Information Technologies Pvt Ltd
 
Groovy unleashed
Groovy unleashed Groovy unleashed
Groovy unleashed
Isuru Samaraweera
 
The Ring programming language version 1.5.1 book - Part 33 of 180
The Ring programming language version 1.5.1 book - Part 33 of 180The Ring programming language version 1.5.1 book - Part 33 of 180
The Ring programming language version 1.5.1 book - Part 33 of 180
Mahmoud Samir Fayed
 
Grails GORM - You Know SQL. You Know Queries. Here's GORM.
Grails GORM - You Know SQL. You Know Queries. Here's GORM.Grails GORM - You Know SQL. You Know Queries. Here's GORM.
Grails GORM - You Know SQL. You Know Queries. Here's GORM.
Ted Vinke
 
Clojure vs Design Patterns
Clojure vs Design PatternsClojure vs Design Patterns
Clojure vs Design Patterns
Ron Toland
 
Json and SQL DB serialization Introduction with Play! and Slick
Json and SQL DB serialization Introduction with Play! and SlickJson and SQL DB serialization Introduction with Play! and Slick
Json and SQL DB serialization Introduction with Play! and Slick
Stephen Kemmerling
 
What is new in Java 8
What is new in Java 8What is new in Java 8
What is new in Java 8
Sandeep Kr. Singh
 
JS OO and Closures
JS OO and ClosuresJS OO and Closures
JS OO and Closures
Jussi Pohjolainen
 
Scala 2013 review
Scala 2013 reviewScala 2013 review
Scala 2013 review
Sagie Davidovich
 
An introduction to property-based testing
An introduction to property-based testingAn introduction to property-based testing
An introduction to property-based testing
Vincent Pradeilles
 
MCE^3 - Hannes Verlinde - Let The Symbols Do The Work
MCE^3 - Hannes Verlinde - Let The Symbols Do The WorkMCE^3 - Hannes Verlinde - Let The Symbols Do The Work
MCE^3 - Hannes Verlinde - Let The Symbols Do The Work
PROIDEA
 
Python programming : Standard Input and Output
Python programming : Standard Input and OutputPython programming : Standard Input and Output
Python programming : Standard Input and Output
Emertxe Information Technologies Pvt Ltd
 
The Ring programming language version 1.8 book - Part 41 of 202
The Ring programming language version 1.8 book - Part 41 of 202The Ring programming language version 1.8 book - Part 41 of 202
The Ring programming language version 1.8 book - Part 41 of 202
Mahmoud Samir Fayed
 
Postgres rules
Postgres rulesPostgres rules
Postgres rules
gisborne
 
The Ring programming language version 1.5.1 book - Part 34 of 180
The Ring programming language version 1.5.1 book - Part 34 of 180The Ring programming language version 1.5.1 book - Part 34 of 180
The Ring programming language version 1.5.1 book - Part 34 of 180
Mahmoud Samir Fayed
 
The Ring programming language version 1.5.1 book - Part 33 of 180
The Ring programming language version 1.5.1 book - Part 33 of 180The Ring programming language version 1.5.1 book - Part 33 of 180
The Ring programming language version 1.5.1 book - Part 33 of 180
Mahmoud Samir Fayed
 
Grails GORM - You Know SQL. You Know Queries. Here's GORM.
Grails GORM - You Know SQL. You Know Queries. Here's GORM.Grails GORM - You Know SQL. You Know Queries. Here's GORM.
Grails GORM - You Know SQL. You Know Queries. Here's GORM.
Ted Vinke
 
Clojure vs Design Patterns
Clojure vs Design PatternsClojure vs Design Patterns
Clojure vs Design Patterns
Ron Toland
 
Json and SQL DB serialization Introduction with Play! and Slick
Json and SQL DB serialization Introduction with Play! and SlickJson and SQL DB serialization Introduction with Play! and Slick
Json and SQL DB serialization Introduction with Play! and Slick
Stephen Kemmerling
 
An introduction to property-based testing
An introduction to property-based testingAn introduction to property-based testing
An introduction to property-based testing
Vincent Pradeilles
 
MCE^3 - Hannes Verlinde - Let The Symbols Do The Work
MCE^3 - Hannes Verlinde - Let The Symbols Do The WorkMCE^3 - Hannes Verlinde - Let The Symbols Do The Work
MCE^3 - Hannes Verlinde - Let The Symbols Do The Work
PROIDEA
 

Similar to Leveraging Scala Macros for Better Validation (20)

SQL data types: INT, VARCHAR, CHAR,.pptx
SQL data types: INT, VARCHAR, CHAR,.pptxSQL data types: INT, VARCHAR, CHAR,.pptx
SQL data types: INT, VARCHAR, CHAR,.pptx
dharaneshgopal
 
Java gets a closure
Java gets a closureJava gets a closure
Java gets a closure
Tomasz Kowalczewski
 
Scala
ScalaScala
Scala
suraj_atreya
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
Bastian Feder
 
Ti1220 Lecture 7: Polymorphism
Ti1220 Lecture 7: PolymorphismTi1220 Lecture 7: Polymorphism
Ti1220 Lecture 7: Polymorphism
Eelco Visser
 
Scala in Places API
Scala in Places APIScala in Places API
Scala in Places API
Łukasz Bałamut
 
Test in action week 2
Test in action   week 2Test in action   week 2
Test in action week 2
Yi-Huan Chan
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
Bastian Feder
 
Php & my sql
Php & my sqlPhp & my sql
Php & my sql
Norhisyam Dasuki
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentation
Van Huong
 
API first with Swagger and Scala by Slava Schmidt
API first with Swagger and Scala by  Slava SchmidtAPI first with Swagger and Scala by  Slava Schmidt
API first with Swagger and Scala by Slava Schmidt
JavaDayUA
 
Icsug dev day2014_road to damascus - conversion experience-lotusscript and @f...
Icsug dev day2014_road to damascus - conversion experience-lotusscript and @f...Icsug dev day2014_road to damascus - conversion experience-lotusscript and @f...
Icsug dev day2014_road to damascus - conversion experience-lotusscript and @f...
ICS User Group
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
Mario Fusco
 
An excuse to Try, Either, folding, and Future. sequence
An excuse to Try, Either, folding, and Future. sequenceAn excuse to Try, Either, folding, and Future. sequence
An excuse to Try, Either, folding, and Future. sequence
Germán Ferrari
 
Session 08 - Arrays and Methods
Session 08 - Arrays and MethodsSession 08 - Arrays and Methods
Session 08 - Arrays and Methods
SiddharthSelenium
 
Java SE 8
Java SE 8Java SE 8
Java SE 8
Murali Pachiyappan
 
SQL data types: INT, VARCHAR, CHAR,.pptx
SQL data types: INT, VARCHAR, CHAR,.pptxSQL data types: INT, VARCHAR, CHAR,.pptx
SQL data types: INT, VARCHAR, CHAR,.pptx
dharaneshgopal
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
Bastian Feder
 
Ti1220 Lecture 7: Polymorphism
Ti1220 Lecture 7: PolymorphismTi1220 Lecture 7: Polymorphism
Ti1220 Lecture 7: Polymorphism
Eelco Visser
 
Test in action week 2
Test in action   week 2Test in action   week 2
Test in action week 2
Yi-Huan Chan
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
Bastian Feder
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Hiroshi Ono
 
Java 8 presentation
Java 8 presentationJava 8 presentation
Java 8 presentation
Van Huong
 
API first with Swagger and Scala by Slava Schmidt
API first with Swagger and Scala by  Slava SchmidtAPI first with Swagger and Scala by  Slava Schmidt
API first with Swagger and Scala by Slava Schmidt
JavaDayUA
 
Icsug dev day2014_road to damascus - conversion experience-lotusscript and @f...
Icsug dev day2014_road to damascus - conversion experience-lotusscript and @f...Icsug dev day2014_road to damascus - conversion experience-lotusscript and @f...
Icsug dev day2014_road to damascus - conversion experience-lotusscript and @f...
ICS User Group
 
An excuse to Try, Either, folding, and Future. sequence
An excuse to Try, Either, folding, and Future. sequenceAn excuse to Try, Either, folding, and Future. sequence
An excuse to Try, Either, folding, and Future. sequence
Germán Ferrari
 
Session 08 - Arrays and Methods
Session 08 - Arrays and MethodsSession 08 - Arrays and Methods
Session 08 - Arrays and Methods
SiddharthSelenium
 
Ad

More from Tomer Gabel (20)

How shit works: Time
How shit works: TimeHow shit works: Time
How shit works: Time
Tomer 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 Us
Tomer Gabel
 
Slaying Sacred Cows: Deconstructing Dependency Injection
Slaying Sacred Cows: Deconstructing Dependency InjectionSlaying Sacred Cows: Deconstructing Dependency Injection
Slaying Sacred Cows: Deconstructing Dependency Injection
Tomer Gabel
 
An Abridged Guide to Event Sourcing
An Abridged Guide to Event SourcingAn Abridged Guide to Event Sourcing
An Abridged Guide to Event Sourcing
Tomer Gabel
 
How shit works: the CPU
How shit works: the CPUHow shit works: the CPU
How shit works: the CPU
Tomer Gabel
 
How Shit Works: Storage
How Shit Works: StorageHow Shit Works: Storage
How Shit Works: Storage
Tomer 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 Story
Tomer Gabel
 
The Wix Microservice Stack
The Wix Microservice StackThe Wix Microservice Stack
The Wix Microservice Stack
Tomer 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 Profit
Tomer Gabel
 
Onboarding at Scale
Onboarding at ScaleOnboarding at Scale
Onboarding at Scale
Tomer Gabel
 
Scala in the Wild
Scala in the WildScala in the Wild
Scala in the Wild
Tomer 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 On
Tomer Gabel
 
A Field Guide to DSL Design in Scala
A Field Guide to DSL Design in ScalaA Field Guide to DSL Design in Scala
A Field Guide to DSL Design in Scala
Tomer 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 Classes
Tomer Gabel
 
5 Bullets to Scala Adoption
5 Bullets to Scala Adoption5 Bullets to Scala Adoption
5 Bullets to Scala Adoption
Tomer 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 Scala
Tomer Gabel
 
How shit works: Time
How shit works: TimeHow shit works: Time
How shit works: Time
Tomer 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 Us
Tomer Gabel
 
Slaying Sacred Cows: Deconstructing Dependency Injection
Slaying Sacred Cows: Deconstructing Dependency InjectionSlaying Sacred Cows: Deconstructing Dependency Injection
Slaying Sacred Cows: Deconstructing Dependency Injection
Tomer Gabel
 
An Abridged Guide to Event Sourcing
An Abridged Guide to Event SourcingAn Abridged Guide to Event Sourcing
An Abridged Guide to Event Sourcing
Tomer Gabel
 
How shit works: the CPU
How shit works: the CPUHow shit works: the CPU
How shit works: the CPU
Tomer Gabel
 
How Shit Works: Storage
How Shit Works: StorageHow Shit Works: Storage
How Shit Works: Storage
Tomer 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 Story
Tomer Gabel
 
The Wix Microservice Stack
The Wix Microservice StackThe Wix Microservice Stack
The Wix Microservice Stack
Tomer 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 Profit
Tomer Gabel
 
Onboarding at Scale
Onboarding at ScaleOnboarding at Scale
Onboarding at Scale
Tomer Gabel
 
Scala in the Wild
Scala in the WildScala in the Wild
Scala in the Wild
Tomer 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 On
Tomer Gabel
 
A Field Guide to DSL Design in Scala
A Field Guide to DSL Design in ScalaA Field Guide to DSL Design in Scala
A Field Guide to DSL Design in Scala
Tomer 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 Classes
Tomer Gabel
 
5 Bullets to Scala Adoption
5 Bullets to Scala Adoption5 Bullets to Scala Adoption
5 Bullets to Scala Adoption
Tomer 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 Scala
Tomer Gabel
 
Ad

Recently uploaded (20)

Minitab 22 Full Crack Plus Product Key Free Download [Latest] 2025
Minitab 22 Full Crack Plus Product Key Free Download [Latest] 2025Minitab 22 Full Crack Plus Product Key Free Download [Latest] 2025
Minitab 22 Full Crack Plus Product Key Free Download [Latest] 2025
wareshashahzadiii
 
What Do Contribution Guidelines Say About Software Testing? (MSR 2025)
What Do Contribution Guidelines Say About Software Testing? (MSR 2025)What Do Contribution Guidelines Say About Software Testing? (MSR 2025)
What Do Contribution Guidelines Say About Software Testing? (MSR 2025)
Andre Hora
 
Solidworks Crack 2025 latest new + license code
Solidworks Crack 2025 latest new + license codeSolidworks Crack 2025 latest new + license code
Solidworks Crack 2025 latest new + license code
aneelaramzan63
 
Adobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest VersionAdobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest Version
kashifyounis067
 
Meet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Meet the Agents: How AI Is Learning to Think, Plan, and CollaborateMeet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Meet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Maxim Salnikov
 
Agentic AI Use Cases using GenAI LLM models
Agentic AI Use Cases using GenAI LLM modelsAgentic AI Use Cases using GenAI LLM models
Agentic AI Use Cases using GenAI LLM models
Manish Chopra
 
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
steaveroggers
 
Douwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License codeDouwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License code
aneelaramzan63
 
Landscape of Requirements Engineering for/by AI through Literature Review
Landscape of Requirements Engineering for/by AI through Literature ReviewLandscape of Requirements Engineering for/by AI through Literature Review
Landscape of Requirements Engineering for/by AI through Literature Review
Hironori Washizaki
 
Sales Deck SentinelOne Singularity Platform.pptx
Sales Deck SentinelOne Singularity Platform.pptxSales Deck SentinelOne Singularity Platform.pptx
Sales Deck SentinelOne Singularity Platform.pptx
EliandoLawnote
 
How to Optimize Your AWS Environment for Improved Cloud Performance
How to Optimize Your AWS Environment for Improved Cloud PerformanceHow to Optimize Your AWS Environment for Improved Cloud Performance
How to Optimize Your AWS Environment for Improved Cloud Performance
ThousandEyes
 
Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025
mu394968
 
Kubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptxKubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptx
CloudScouts
 
Adobe Photoshop Lightroom CC 2025 Crack Latest Version
Adobe Photoshop Lightroom CC 2025 Crack Latest VersionAdobe Photoshop Lightroom CC 2025 Crack Latest Version
Adobe Photoshop Lightroom CC 2025 Crack Latest Version
usmanhidray
 
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
Andre Hora
 
Xforce Keygen 64-bit AutoCAD 2025 Crack
Xforce Keygen 64-bit AutoCAD 2025  CrackXforce Keygen 64-bit AutoCAD 2025  Crack
Xforce Keygen 64-bit AutoCAD 2025 Crack
usmanhidray
 
Revolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptxRevolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptx
nidhisingh691197
 
Secure Test Infrastructure: The Backbone of Trustworthy Software Development
Secure Test Infrastructure: The Backbone of Trustworthy Software DevelopmentSecure Test Infrastructure: The Backbone of Trustworthy Software Development
Secure Test Infrastructure: The Backbone of Trustworthy Software Development
Shubham Joshi
 
The Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdfThe Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdf
drewplanas10
 
Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025
kashifyounis067
 
Minitab 22 Full Crack Plus Product Key Free Download [Latest] 2025
Minitab 22 Full Crack Plus Product Key Free Download [Latest] 2025Minitab 22 Full Crack Plus Product Key Free Download [Latest] 2025
Minitab 22 Full Crack Plus Product Key Free Download [Latest] 2025
wareshashahzadiii
 
What Do Contribution Guidelines Say About Software Testing? (MSR 2025)
What Do Contribution Guidelines Say About Software Testing? (MSR 2025)What Do Contribution Guidelines Say About Software Testing? (MSR 2025)
What Do Contribution Guidelines Say About Software Testing? (MSR 2025)
Andre Hora
 
Solidworks Crack 2025 latest new + license code
Solidworks Crack 2025 latest new + license codeSolidworks Crack 2025 latest new + license code
Solidworks Crack 2025 latest new + license code
aneelaramzan63
 
Adobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest VersionAdobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest Version
kashifyounis067
 
Meet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Meet the Agents: How AI Is Learning to Think, Plan, and CollaborateMeet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Meet the Agents: How AI Is Learning to Think, Plan, and Collaborate
Maxim Salnikov
 
Agentic AI Use Cases using GenAI LLM models
Agentic AI Use Cases using GenAI LLM modelsAgentic AI Use Cases using GenAI LLM models
Agentic AI Use Cases using GenAI LLM models
Manish Chopra
 
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
How to Batch Export Lotus Notes NSF Emails to Outlook PST Easily?
steaveroggers
 
Douwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License codeDouwan Crack 2025 new verson+ License code
Douwan Crack 2025 new verson+ License code
aneelaramzan63
 
Landscape of Requirements Engineering for/by AI through Literature Review
Landscape of Requirements Engineering for/by AI through Literature ReviewLandscape of Requirements Engineering for/by AI through Literature Review
Landscape of Requirements Engineering for/by AI through Literature Review
Hironori Washizaki
 
Sales Deck SentinelOne Singularity Platform.pptx
Sales Deck SentinelOne Singularity Platform.pptxSales Deck SentinelOne Singularity Platform.pptx
Sales Deck SentinelOne Singularity Platform.pptx
EliandoLawnote
 
How to Optimize Your AWS Environment for Improved Cloud Performance
How to Optimize Your AWS Environment for Improved Cloud PerformanceHow to Optimize Your AWS Environment for Improved Cloud Performance
How to Optimize Your AWS Environment for Improved Cloud Performance
ThousandEyes
 
Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025
mu394968
 
Kubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptxKubernetes_101_Zero_to_Platform_Engineer.pptx
Kubernetes_101_Zero_to_Platform_Engineer.pptx
CloudScouts
 
Adobe Photoshop Lightroom CC 2025 Crack Latest Version
Adobe Photoshop Lightroom CC 2025 Crack Latest VersionAdobe Photoshop Lightroom CC 2025 Crack Latest Version
Adobe Photoshop Lightroom CC 2025 Crack Latest Version
usmanhidray
 
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
Andre Hora
 
Xforce Keygen 64-bit AutoCAD 2025 Crack
Xforce Keygen 64-bit AutoCAD 2025  CrackXforce Keygen 64-bit AutoCAD 2025  Crack
Xforce Keygen 64-bit AutoCAD 2025 Crack
usmanhidray
 
Revolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptxRevolutionizing Residential Wi-Fi PPT.pptx
Revolutionizing Residential Wi-Fi PPT.pptx
nidhisingh691197
 
Secure Test Infrastructure: The Backbone of Trustworthy Software Development
Secure Test Infrastructure: The Backbone of Trustworthy Software DevelopmentSecure Test Infrastructure: The Backbone of Trustworthy Software Development
Secure Test Infrastructure: The Backbone of Trustworthy Software Development
Shubham Joshi
 
The Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdfThe Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdf
drewplanas10
 
Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025
kashifyounis067
 

Leveraging Scala Macros for Better Validation

  • 1. Leveraging Scala Macros for Better Validation Tomer Gabel, Wix September 2014
  • 2. I Have a Dream • Definition: case class Person( firstName: String, lastName: String ) implicit val personValidator = validator[Person] { p ⇒ p.firstName is notEmpty p.lastName is notEmpty }
  • 3. I Have a Dream • Usage: validate(Person("Wernher", "von Braun”)) == Success validate(Person("", "No First Name”)) == Failure(Set(RuleViolation( value = "", constraint = "must not be empty", description = "firstName" )))
  • 5. Basic Architecture API Combinator Library DSL Macro Transformation
  • 6. The Accord API • Validation can succeed or fail • A failure comprises one or more violations sealed trait Result case object Success extends Result case class Failure(violations: Set[Violation]) extends Result • The validator typeclass: trait Validator[-T] extends (T ⇒ Result)
  • 7. Why Macros? • Quick refresher: implicit val personValidator = validator[Person] { p ⇒ p.firstName is notEmpty p.lastName is notEmpty } Implicit “and” Automatic description generation
  • 8. Full Disclosure Macros are experimental Macros are hard I will gloss over a lot of details … and simplify a lot of things
  • 9. Abstract Syntax Trees • An intermediate representation of code – Structure (semantics) – Metadata (e.g. types) – optional! • Provided by the reflection API • Alas, mutable – Until Dotty comes along
  • 10. Abstract Syntax Trees def method(param: String) = param.toUpperCase
  • 11. Abstract Syntax Trees def method(param: String) = param.toUpperCase Apply( Select( Ident(newTermName("param")), newTermName("toUpperCase") ), List() )
  • 12. Abstract Syntax Trees def method(param: String) = param.toUpperCase ValDef( Modifiers(PARAM), newTermName("param"), Select( Ident(scala.Predef), newTypeName("String") ), EmptyTree // Value )
  • 13. Abstract Syntax Trees def method(param: String) = param.toUpperCase DefDef( Modifiers(), newTermName("method"), List(), // Type parameters List( // Parameter lists List(parameter) ), TypeTree(), // Return type implementation )
  • 14. Def Macro 101 • Looks and acts like a normal function def radix(s: String, base: Int): Long val result = radix("2710", 16) // result == 10000L • Two fundamental differences: – Invoked at compile time instead of runtime – Operates on ASTs instead of values
  • 15. Def Macro 101 • Needs a signature & implementation def radix(s: String, base: Int): Long = macro radixImpl def radixImpl Values (c: Context) (s: c.Expr[String], base: c.Expr[Int]): c.Expr[Long] ASTs
  • 16. Def Macro 101 • What’s in a context? – Enclosures (position) – Error handling – Logging – Infrastructure
  • 17. Basic Architecture API Combinator Library DSL Macro Transformation
  • 18. Overview implicit val personValidator = validator[Person] { p ⇒ p.firstName is notEmpty p.lastName is notEmpty } • The validator macro: Macro Application Validation Rules – Rewrites each rule by addition a description – Aggregates rules with an and combinator
  • 19. Signature def validator[T](v: T ⇒ Unit): Validator[T] = macro ValidationTransform.apply[T] def apply[T : c.WeakTypeTag] (c: Context) (v: c.Expr[T ⇒ Unit]): c.Expr[Validator[T]]
  • 20. Brace yourselves Here be dragons
  • 21. Walkthrough Search for rule Process rule Generate description Rewrite rule
  • 22. Walkthrough Search for rule Process rule Generate description Rewrite rule
  • 23. Search for Rule • A rule is an expression of type Validator[_] • We search by: – Recursively pattern matching over an AST – On match, apply a function on the subtree – Encoded as a partial function from Tree to R
  • 24. Search for Rule def collectFromPattern[R] (tree: Tree) (pattern: PartialFunction[Tree, R]): List[R] = { var found: Vector[R] = Vector.empty new Traverser { override def traverse(subtree: Tree) { if (pattern isDefinedAt subtree) found = found :+ pattern(subtree) else super.traverse(subtree) } }.traverse(tree) found.toList }
  • 25. Search for Rule • Putting it together: case class Rule(ouv: Tree, validation: Tree) def processRule(subtree: Tree): Rule = ??? def findRules(body: Tree): Seq[Rule] = { val validatorType = typeOf[Validator[_]] collectFromPattern(body) { case subtree if subtree.tpe <:< validatorType ⇒ processRule(subtree) } }
  • 26. Walkthrough Search for rule Process rule Generate description Rewrite rule
  • 27. Process Rule • The user writes: p.firstName is notEmpty • The compiler emits: Type: Validator[_] Contextualizer(p.firstName).is(notEmpty) Object Under Validation (OUV) Validation
  • 28. Process Rule Contextualizer(p.firstName).is(notEmpty) • This is effectively an Apply AST node • The left-hand side is the OUV • The right-hand side is the validation – But we can use the entire expression! • Contextualizer is our entry point
  • 29. Process Rule Contextualizer(p.firstName).is(notEmpty) Apply Select Apply TypeApply Contextualizer String Select Ident(“p”) firstName is notEmpty
  • 30. Process Rule Contextualizer(p.firstName).is(notEmpty) Apply Select Apply TypeApply Contextualizer String Select Ident(“p”) firstName is notEmpty
  • 31. Process Rule Apply TypeApply Contextualizer String Select Ident(“p”) firstName
  • 32. Process Rule Apply TypeApply Contextualizer Φ Select Ident(“p”) firstName
  • 33. Process Rule Apply TypeApply Contextualizer Φ Select Ident(“p”) firstName
  • 34. Process Rule Apply TypeApply Contextualizer Φ OUV Φ Φ case Apply(TypeApply(Select(_, `term`), _), ouv :: Nil) ⇒
  • 35. Process Rule • Putting it together: val term = newTermName("Contextualizer") def processRule(subtree: Tree): Rule = extractFromPattern(subtree) { case Apply(TypeApply(Select(_, `term`), _), ouv :: Nil) ⇒ Rule(ouv, subtree) } getOrElse abort(subtree.pos, "Not a valid rule")
  • 36. Walkthrough Search for rule Process rule Generate description Rewrite rule
  • 37. Generate Description Contextualizer(p.firstName).is(notEmpty) • Consider the object under validation • In this example, it is a field accessor • The function prototype is the entry point Select Ident(“p”) firstName validator[Person] { p ⇒ ... }
  • 38. Generate Description • How to get at the prototype? • The macro signature includes the rule block: def apply[T : c.WeakTypeTag] (c: Context) (v: c.Expr[T ⇒ Unit]): c.Expr[Validator[T]] • To extract the prototype: val Function(prototype :: Nil, body) = v.tree // prototype: ValDef
  • 39. Generate Description • Putting it all together: def describeRule(rule: ValidationRule) = { val para = prototype.name val Select(Ident(`para`), description) = rule.ouv description.toString }
  • 40. Walkthrough Search for rule Process rule Generate description Rewrite rule
  • 41. Rewrite Rule • We’re constructing a Validator[Person] • A rule is itself a Validator[T]. For example: Contextualizer(p.firstName).is(notEmpty) • We need to: – Lift the rule to validate the enclosing type – Apply the description to the result
  • 42. Quasiquotes • Provide an easy way to construct ASTs: Apply( Select( Ident(newTermName"x"), newTermName("$plus") ), List( Ident(newTermName("y")) ) ) q"x + y"
  • 43. Quasiquotes • Quasiquotes also let you splice trees: def greeting(whom: c.Expr[String]) = q"Hello "$whom"!" • And can be used in pattern matching: val q"$x + $y" = tree
  • 44. Rewrite Rule Contextualizer(p.firstName).is(notEmpty) new Validator[Person] { def apply(p: Person) = { val validation = Contextualizer(p.firstName).is(notEmpty) validation(p.firstName) withDescription "firstName" } }
  • 45. Rewrite Rule • Putting it all together: def rewriteRule(rule: ValidationRule) = { val desc = describeRule(rule) val tree = Literal(Constant(desc)) q""" new com.wix.accord.Validator[${weakTypeOf[T]}] { def apply($prototype) = { val validation = ${rule.validation} validation(${rule.ouv}) withDescription $tree } } """ }
  • 47. Epilogue • The finishing touch: and combinator def apply[T : c.WeakTypeTag] (c: Context) (v: c.Expr[T ⇒ Unit]): c.Expr[Validator[T]] = { val Function(prototype :: Nil, body) = v.tree // ... all the stuff we just discussed val rules = findRules(body) map rewriteRule val result = q"new com.wix.accord.combinators.And(..$rules)" c.Expr[Validator[T]](result) }
  • 48. [email protected] @tomerg http://il.linkedin.com/in/tomergabel Check out Accord at: http://github.com/wix/accord Thank you for listening WE’RE DONE HERE!

Editor's Notes

  • #3: Image source: http://en.wikipedia.org/wiki/File:Martin_Luther_King_-_March_on_Washington.jpg
  • #5: Image source: https://www.flickr.com/photos/leo-gruebler/6347903993
  • #17: Image source: https://www.flickr.com/photos/wwarby/11271811524/in/photostream/
  • #22: Number image source: http://pixabay.com/en/count-numbers-digits-display-147393/
  • #23: Number image source: http://pixabay.com/en/count-numbers-digits-display-147393/
  • #27: Number image source: http://pixabay.com/en/count-numbers-digits-display-147393/
  • #37: Number image source: http://pixabay.com/en/count-numbers-digits-display-147393/
  • #41: Number image source: http://pixabay.com/en/count-numbers-digits-display-147393/
  • #47: Image source: https://www.flickr.com/photos/bevgoodwin/8608320577