An expressive static type system is one of the most joyful and powerful tools for prototyping, designing, and maintaining programs. In this performance-theatrical presentation, I will provide a taste of how to use types, in conjunction with tests, to drive iterative development of a particular program, the famous FizzBuzz problem. We will solve generalizations of this problem, changing and adding requirements, to illustrate the pleasures and benefits of "type thinking".
The Scala language will be used as the vehicle for this demonstration, but the techniques apply immediately to any industrial-strength statically typed language, such as Haskell, OCaml, F#, Rust, and most recently, Swift.
Type-Directed TDD in Rust: a case study using FizzBuzzFranklin Chen
An expressive static type system is one of the most joyful and powerful tools for prototyping, designing, and maintaining programs. In this performance-theatrical presentation, I will provide a taste of how to use types, in conjunction with tests, to drive iterative development of a particular program, the famous FizzBuzz problem. We will solve generalizations of this problem, changing and adding requirements, to illustrate the pleasures and benefits of "type thinking".
The Rust language will be used as the vehicle for this demonstration, but the techniques apply immediately to any industrial-strength statically typed language, such as Scala, Haskell, OCaml, F#, and most recently, Swift.
Regular expressions are very commonly used to process and validate text data. Unfortunately, they suffer from various limitations. I will discuss the limitations and illustrate how using grammars instead can be an improvement. I will make the examples oncrete using parsing libraries in a couple of representative languages, although the ideas are language-independent.
I will emphasize ease of use, since one reason for the overuse of regular expressions is that they are so easy to pull out of one's toolbox.
Type-Directed TDD in Rust: a case study using FizzBuzzFranklin Chen
An expressive static type system is one of the most joyful and powerful tools for prototyping, designing, and maintaining programs. In this performance-theatrical presentation, I will provide a taste of how to use types, in conjunction with tests, to drive iterative development of a particular program, the famous FizzBuzz problem. We will solve generalizations of this problem, changing and adding requirements, to illustrate the pleasures and benefits of "type thinking".
The Rust language will be used as the vehicle for this demonstration, but the techniques apply immediately to any industrial-strength statically typed language, such as Scala, Haskell, OCaml, F#, and most recently, Swift.
Regular expressions are very commonly used to process and validate text data. Unfortunately, they suffer from various limitations. I will discuss the limitations and illustrate how using grammars instead can be an improvement. I will make the examples oncrete using parsing libraries in a couple of representative languages, although the ideas are language-independent.
I will emphasize ease of use, since one reason for the overuse of regular expressions is that they are so easy to pull out of one's toolbox.
Effective and Efficient Entity Search in RDF dataRoi Blanco
Triple stores have long provided RDF storage as well as data access using expressive, formal query languages such as SPARQL. The new end users of the Semantic Web, however, are mostly unaware of SPARQL and overwhelmingly prefer imprecise, informal keyword queries for searching over data. At the same time, the amount of data on the Semantic Web is approaching the limits of the architectures that provide support for the full expressivity of SPARQL. These factors combined have led to an increased interest in semantic search, i.e. access to RDF data using Information Retrieval methods. In this work, we propose a method for effective and efficient entity search over RDF data. We describe an adaptation of the BM25F ranking function for RDF data, and demonstrate that it outperforms other state-of-the-art methods in ranking RDF resources. We also propose a set of new index structures for efficient retrieval and ranking of results. We implement these results using the open-source MG4J framework.
Included in this report, you will find a complete summary of the work completed on the ImmigrationWorksInHalifax initiative from January 1, 2009 to December 31, 2009. Goals include:
- Raise awareness and change perceptions on the benefits of hiring immigrants
- Provide key decision makers with the information they need to source, select, develop and welcome skilled immigrants to their workforce.
- Increase the business network of new immigrants so that they will be able to find employment related to their work experience and qualification.
Baques explains the need for carbon polluters to sequest carbon and any such non-profit initiative may not be sustainable over long run. hence we have conceptualized this idea of developing a profitable model which can be imitated throughout the world to reduce the impact of Co2.
TDD - Test Driven Development - Java JUnit FizzBuzzAlan Richardson
A short example Test Driven Development session where I code FizzBuzz.
FizzBuzz is often used as a programming interview question and as a Kata for practicing your coding.
The GitHub code repository with the Java code for this exercise is available at:
https://github.com/eviltester/fizzbuzz
Read the blog post for the video:
http://blog.eviltester.com/2018/03/tdd-test-driven-development-java-junit.html
When learning the game of Chess, people usually start by learning the basic moves individual pieces can perform. Later, to master the game, one must develop the skill to combine those small, basic moves into larger strategies. If we think about Test Driven Development in similar terms, what would those “basic TDD moves” be?
Effective and Efficient Entity Search in RDF dataRoi Blanco
Triple stores have long provided RDF storage as well as data access using expressive, formal query languages such as SPARQL. The new end users of the Semantic Web, however, are mostly unaware of SPARQL and overwhelmingly prefer imprecise, informal keyword queries for searching over data. At the same time, the amount of data on the Semantic Web is approaching the limits of the architectures that provide support for the full expressivity of SPARQL. These factors combined have led to an increased interest in semantic search, i.e. access to RDF data using Information Retrieval methods. In this work, we propose a method for effective and efficient entity search over RDF data. We describe an adaptation of the BM25F ranking function for RDF data, and demonstrate that it outperforms other state-of-the-art methods in ranking RDF resources. We also propose a set of new index structures for efficient retrieval and ranking of results. We implement these results using the open-source MG4J framework.
Included in this report, you will find a complete summary of the work completed on the ImmigrationWorksInHalifax initiative from January 1, 2009 to December 31, 2009. Goals include:
- Raise awareness and change perceptions on the benefits of hiring immigrants
- Provide key decision makers with the information they need to source, select, develop and welcome skilled immigrants to their workforce.
- Increase the business network of new immigrants so that they will be able to find employment related to their work experience and qualification.
Baques explains the need for carbon polluters to sequest carbon and any such non-profit initiative may not be sustainable over long run. hence we have conceptualized this idea of developing a profitable model which can be imitated throughout the world to reduce the impact of Co2.
TDD - Test Driven Development - Java JUnit FizzBuzzAlan Richardson
A short example Test Driven Development session where I code FizzBuzz.
FizzBuzz is often used as a programming interview question and as a Kata for practicing your coding.
The GitHub code repository with the Java code for this exercise is available at:
https://github.com/eviltester/fizzbuzz
Read the blog post for the video:
http://blog.eviltester.com/2018/03/tdd-test-driven-development-java-junit.html
When learning the game of Chess, people usually start by learning the basic moves individual pieces can perform. Later, to master the game, one must develop the skill to combine those small, basic moves into larger strategies. If we think about Test Driven Development in similar terms, what would those “basic TDD moves” be?
Presented at JavaZone (9th September 2015)
Video available at https://vimeo.com/138863968
The three-act play, the given–when–then BDD triptych, the three steps of the Feynman problem-solving algorithm... a surprising number of things appear to come in threes. This talk walks through — and has some fun with — a number of triples that affect and are found in software development.
As a long time C# developer, I started with Python as a second language for ML purposes. Starting in Python is easy, doing engineering grade python turned out to be a lot harder, so these are 10 things I learned along the way to writing production code in Python.
Fuzz-testing: A hacker's approach to making your code more secure | Pascal Ze...Codemotion
Increased complexity makes it very hard and time-consuming to keep your software bug-free and secure. We introduce fuzz-testing as a method for automatically and continuously discovering vulnerabilities hidden in your code. The talk will explain how fuzzing works and how to integrate fuzz-testing into your Software Development Life Cycle to increase your code’s security.
Many Rubyists branch out and take a look at other languages. What are similarities between those languages and ruby? What are differences? How does Ruby influence these languages?
Unit Testing in Javascript
The way to quality product isn't easy or simple but it is reachable. One of the key things to do is unit testing. What, when and how to do it --> read in the presentation.
See more details here: http://www.slideshare.net/AnnaKhabibullina/jsfwdays-2014unittesingjavascriptv4-33966202
Read about this and other techtalks @ DA-14 in our blog: http://da-14.com/our-blog/
Introducing Swift - and the Sunset of Our Culture?dankogai
Apple recently released a language called Swift. As a language it appears to be the best of both worlds -- a script language that emits native codes. But I've got a feeling it means more than just a language. The talk roughly consists of 4 parts as follows:
* Introducing Swift
* Script Languages vs "Compiler" Languages
* Free Software vs. Open Source
* The Sunset of Our Culture
Missing objects: ?. and ?? in JavaScript (BrazilJS 2018)Igalia
By Daniel Ehrenberg.
Slides at https://docs.google.com/presentation/d/1UOk7RlrCdFLs95OPQ-emm__oHD3n43zGyLsn0aGZWyI/edit#slide=id.p
JavaScript code frequently has to deal with missing values, but current mechanisms are repetitive or error-prone. Some are proposing that we change the JavaScript programming language, in a way inspired by other languages like Swift: the optional chaining and nullish coalescing operators.
We got a big upgrade to JavaScript with ES6, but TC39, the standards committee which defines the programming language, is still making improvements with this and other proposals. In this talk, I'll explain what kinds of things TC39 thinks about, how it goes about improving the programming language, and how you can participate to shape the future of JavaScript.
(c) BrazilJS 2018
24 e 25 de Agosto, Brazil
Similar to Exploring type-directed, test-driven development: a case study using FizzBuzz (20)
Hidden Gems of Europe - DISCOVERING THE CONTINENT'S BEST-KEPT SECRETSKamil Uğraş TÜRKOĞLU
Europe, continent rich in history, culture, and natural beauty, is often synonymous with famous cities like Paris, Rome, and London. These iconic destinations attract millions of tourists every year, captivating them with their renowned landmarks, vibrant culture, and bustling urban life. However, beyond these well-trodden paths lie countless hidden gems waiting to be discovered. These lesser-known destinations offer unique experiences, authentic encounters, and breathtaking landscapes that often surpass the allure of their famous counterparts.
In "Hidden Gems of Europe," we embark on a journey to uncover these secret spots, exploring the heart and soul of Europe through its quaint villages, charming towns, and secluded natural wonders. This book aims to inspire travelers to look beyond the obvious and venture into the lesser-explored corners of the continent, where true adventure and discovery await.
How To Talk To a Live Person at American Airlinesflyn goo
This page by FlynGoo can become your ultimate guide to connecting with a live person at American Airlines. Have you ever felt lost in the automated maze of customer service menus? FlynGoo is here to rescue you from endless phone trees and automated responses. With just a click or a call to a specific number, we ensure you get the human touch you deserve. No more frustration, no more waiting on hold - we simplify the process, making your travel experience smoother and more enjoyable.
LUXURY TRAVEL THE ULTIMATE TOKYO EXPERIENCE FROM SINGAPORE.pdfDiper Tour
Get off on the most luxurious Tokyo itinerary from Singapore. Experience Tokyo’s sophisticated modernism and rich tradition with first-class travel, sumptuous lodging, fine food, and special tours. Savor the finest that this energetic city has to offer for an experience that will never be forgotten.
BTW UK Visa Application Process, Uk Visa complete guide, Uk Visa fees, requirements and application process. Know all about uk visa and best way to apply for the uk visa. Get to know about the requirements that allows you for the faster visa appliaction. BTW UK Visa Application Process, Uk Visa complete guide, Uk Visa fees, requirements and application process. Know all about uk visa and best way to apply for the uk visa. Get to know about the requirements that allows you for the faster visa appliaction. BTW UK Visa Application Process, Uk Visa complete guide, Uk Visa fees, requirements and application process. Know all about uk visa and best way to apply for the uk visa. Get to know about the requirements that allows you for the faster visa appliaction. BTW UK Visa Application Process, Uk Visa complete guide, Uk Visa fees, requirements and application process. Know all about uk visa and best way to apply for the uk visa. Get to know about the requirements that allows you for the faster visa appliaction. BTW UK Visa Application Process, Uk Visa complete guide, Uk Visa fees, requirements and application process. Know all about uk visa and best way to apply for the uk visa. Get to know about the requirements that allows you for the faster visa appliaction. BTW UK Visa Application Process, Uk Visa complete guide, Uk Visa fees, requirements and application process. Know all about uk visa and best way to apply for the uk visa. Get to know about the requirements that allows you for the faster visa appliaction. BTW UK Visa Application Process, Uk Visa complete guide, Uk Visa fees, requirements and application process. Know all about uk visa and best way to apply for the uk visa. Get to know about the requirements that allows you for the faster visa appliaction. BTW UK Visa Application Process, Uk Visa complete guide, Uk Visa fees, requirements and application process. Know all about uk visa and best way to apply for the uk visa. Get to know about the requirements that allows you for the faster visa appliaction. Get information in this PDF and simplyfy your visa process.
Its running cost is among the diverse vital aspects you must consider before buying an electric scooter. Calculate the cost of getting e-scooter charge for your regular usage to calculate its economic efficiency, similar to people who investigate the mileage of petrol or diesel-driven scooters.
The Power of a Glamping Go-To-Market Accelerator Plan.pptxRezStream
Unlock the secrets to success with our comprehensive 8-Step Glamping Accelerator Go-To-Market Plan! Watch our FREE webinar, where you'll receive expert guidance and invaluable insights on every aspect of launching and growing your glamping business.
During the coldest months, Italy transforms into a winter wonderland, providing visitors with a very unique experience. From the Settimana Bianca ski event to the lively Carnevale celebrations, Italy's winter festivities provide something for everyone. Enjoy hot cocoa, eat hearty comfort foods, and buy during winter deals. Explore the country's rich cultural past by participating in Settimana Bianca, and Carnevale, sipping hot chocolate, shopping during winter deals, and indulging in winter comfort foods. Visit our website https://timeforsicily.com/ for more information.
4 DAYS MASAI MARA WILDEBEEST MIGRATION SAFARI TOUR PACKAGE KENYABush Troop Safari
Join our 4-day Masai Mara Wildebeest Migration Safari in Kenya. Witness the incredible wildebeest migration, enjoy exciting game drives, and stay in comfortable lodges. Get up close and personal with one of nature's most amazing exhibits! Book Your Safari Today at - https://bushtroop-safaris.com/
Antarctica- Icy wilderness of extremes and wondertahreemzahra82
In this presentation, we delve into the captivating realm of Antarctica, Earth's southernmost continent. This icy wilderness stands as a testament to extremes, with record-breaking cold temperatures and vast expanses of pristine ice. Antarctica's landscape is dominated by towering glaciers, colossal icebergs, and expansive ice shelves. Yet, amidst this frozen expanse, a rich tapestry of unique wildlife thrives, including penguins, seals, and seabirds, all finely attuned to survive in this harsh environment. Beyond its natural wonders, Antarctica also serves as a vital hub for scientific exploration, providing invaluable insights into climate change and the Earth's history
Our Ooty honeymoon package from Chennai is a perfect escape for newlywed couples to celebrate their love and start their new life together. Our package offers a range of itineraries to cater to the diverse preferences of couples. From adventure activities to relaxing spa sessions, these packages are designed to provide the perfect balance between adventure and relaxation.
Exploring type-directed, test-driven development: a case study using FizzBuzz
1. Exploring type-directed, test-driven development
A case study using FizzBuzz
Franklin Chen
http://franklinchen.com/
June 7, 2014
Pittsburgh TechFest 2014
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 1 / 76
2. Outline
1 Introduction
2 Original FizzBuzz problem
3 FizzBuzz 2: user configuration
4 FizzBuzz 3: FizzBuzzPop and beyond
5 Parallel FizzBuzz
6 Conclusion
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 2 / 76
3. Outline
1 Introduction
2 Original FizzBuzz problem
3 FizzBuzz 2: user configuration
4 FizzBuzz 3: FizzBuzzPop and beyond
5 Parallel FizzBuzz
6 Conclusion
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 3 / 76
4. Goals of this presentation
Give a taste of a practical software development process that is:
test-driven
type-directed
Show everything for real (using Scala):
project build process
testing frameworks
all the code
Use FizzBuzz because:
problem: easy to understand
modifications: easy to understand
fun!
Encourage you to explore a modern typed language
This Monday, Apple ditched Objective C for its new language Swift!
Complete Swift code will shown at the end; looks a lot like Scala.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 4 / 76
5. Test-driven development (TDD)
Think.
Write a test that fails.
Write code until test succeeds.
Repeat, and refactor as needed.
Is TDD dead?
Short answer: No.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 5 / 76
6. Type systems
What is a type system?
A syntactic method to prove that bad things can’t happen.
“Debating” types “versus” tests?
Let’s use both types and tests!
But: use a good type system, not a bad one.
Some decent practical typed languages
OCaml: 20 years old
Haskell: 20 years old
Scala: 10 years old
Swift: 5 days old
Rust (still in progress)
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 6 / 76
7. Outline
1 Introduction
2 Original FizzBuzz problem
3 FizzBuzz 2: user configuration
4 FizzBuzz 3: FizzBuzzPop and beyond
5 Parallel FizzBuzz
6 Conclusion
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 8 / 76
8. Original FizzBuzz problem
FizzBuzz defined
Write a program that prints the numbers from 1 to 100.
But for multiples of three, print “Fizz” instead of the number.
And for the multiples of five, print “Buzz”.
For numbers which are multiples of both three and five, print “FizzBuzz”.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 9 / 76
9. Starter code: main driver
Scala: a modern object-oriented and functional language.
object Main extends App {
// Will not compile yet!
runToSeq(1, 100).foreach(println)
}
Type-directed design: separate out effects (such as printing to
terminal) from the real work.
Type-directed feedback: compilation fails when something is not
implemented yet.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 10 / 76
10. The joys of continuous compilation and testing
SBT: build tool supporting Scala, Java. . .
Winning features
Source file changes trigger smart recompilation!
Source file changes trigger rerun of the tests that depend on changed
code!
$ sbt
> ~testQuick
[info] Compiling 1 Scala source to ...
[error] ...Main.scala:16: not found: value runToSeq
[error] runToSeq(1, 100) foreach println
[error] ^
[error] one error found
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 11 / 76
11. Write type-directed stub
object Main extends App {
runToSeq(1, 100).foreach(println)
def runToSeq(start: Int, end: Int): Seq[String] = {
???
}
}
Write wanted type signature
??? is convenient for stubbing.
In Scala standard library
Just performs: throw new NotImplementedError
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 12 / 76
12. Write acceptance test (simplified)
Specs2: a fine testing framework for Scala, Java. . .
class MainSpec extends Specification { def is = s2"""
${Main.runToSeq(1, 16) ==== ‘strings for 1 to 16‘}
"""
val ‘strings for 1 to 16‘ = Seq(
"1", "2", "Fizz", "4", "Buzz", "Fizz",
"7", "8", "Fizz", "Buzz", "11", "Fizz",
"13", "14", "FizzBuzz", "16"
)
}
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 13 / 76
13. Test passes type check, but fails
Incremental compilation/testing kicks in:
Waiting for source changes... (press enter to interrupt)
[info] MainSpec
[info] x Main.runToSeq(1, 16) ==== ‘strings for 1 to 16
[error] an implementation is missing (Main.scala:19)
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 15 / 76
14. Outside-in: for a FizzBuzz unit
Types are shapes to assemble logically.
def runToSeq(start: Int, end: Int): Seq[String] = {
start.to(end).map(FizzBuzz.evaluate)
}
start.to(end): Seq[Int], where Seq[_] is a type constructor
that, given a type A, returns a type of Seq[A].
For any value of type Seq[A], map: (A => B) => Seq[B].
Therefore: need to implement function
FizzBuzz.evaluate: Int => String.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 16 / 76
15. Implement new FizzBuzz module
A failing acceptance test drives discovery of
A unit, FizzBuzz
A function with a particular type, Int => String
object FizzBuzz {
type Evaluator = Int => String
val evaluate: Evaluator = { i =>
???
}
}
Types are better than comments as documentation!
Comments are not checkable, unlike types and tests.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 18 / 76
16. First part of unit test: example-based
Manually write some examples.
class FizzBuzzSpec extends Specification { def is = s2"""
${FizzBuzz.evaluate(15) ==== "FizzBuzz"}
${FizzBuzz.evaluate(20) ==== "Buzz"}
${FizzBuzz.evaluate(6) ==== "Fizz"}
${FizzBuzz.evaluate(17) ==== "17"}
"""
}
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 19 / 76
17. The joy of property-based tests
ScalaCheck: a framework for writing property-based tests.
class FizzBuzzSpec extends Specification
with ScalaCheck { def is = s2"""
${‘Multiple of both 3 and 5 => "FizzBuzz"‘} """
def ‘Multiple of both 3 and 5 => "FizzBuzz"‘ =
prop { i: Int => (i % 3 == 0 && i % 5 == 0) ==>
{ FizzBuzz.evaluate(i) ==== "FizzBuzz" }
}
}
Winning features
Auto-generates random tests for each property (100 by default).
Type-driven: here, generates random Int values.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 20 / 76
18. Property-based tests (continued)
The other three properties of interest:
def ‘Multiple of only 3 => "Fizz"‘ =
prop { i: Int => (i % 3 == 0 && i % 5 != 0) ==>
{ FizzBuzz.evaluate(i) ==== "Fizz" }
}
def ‘Multiple of only 5 => "Buzz"‘ =
prop { i: Int => (i % 3 != 0 && i % 5 == 0) ==>
{ FizzBuzz.evaluate(i) ==== "Buzz" }
}
def ‘Not a multiple of either 3 or 5 => number‘ =
prop { i: Int => (i % 3 != 0 && i % 5 != 0) ==>
{ FizzBuzz.evaluate(i) ==== i.toString }
}
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 22 / 76
19. A buggy and ugly solution
// Buggy and ugly!
val evaluate: Evaluator = { i =>
if (i % 3 == 0)
"Fizz"
else if (i % 5 == 0)
"Buzz"
else if (i % 3 == 0 && i % 5 == 0)
"FizzBuzz"
else
i.toString
}
[info] FizzBuzzSpec
[info] x FizzBuzz.evaluate(15) ==== "FizzBuzz"
[error] ’Fizz’ is not equal to ’FizzBuzz’
(FizzBuzzSpec.scala:14)
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 23 / 76
20. Booleans are evil!
Maze of twisty little conditionals, all different
Too easy to write incorrect sequences of nested, combined
conditionals.
Overuse of Booleans is a type smell.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 24 / 76
21. Pattern matching organizes information
val evaluate: Evaluator = { i =>
(i % 3 == 0, i % 5 == 0) match {
case (true, false) => "Fizz"
case (false, true) => "Buzz"
case (true, true) => "FizzBuzz"
case (false, false) => i.toString
}
}
Winning features
Visual beauty and clarity.
No duplicated conditionals.
No ordering dependency.
Type checker verifies full coverage of cases.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 26 / 76
22. Example of non-exhaustive pattern matching
val evaluate: Evaluator = { i =>
(i % 3 == 0, i % 5 == 0) match {
case (true, false) => "Fizz"
case (false, true) => "Buzz"
case (true, true) => "FizzBuzz"
// case (false, false) => ???
}
}
[warn] ...FizzBuzz.scala:46: match may not be exhaustive.
[warn] It would fail on the following input: (false, false)
[warn] (i % 3 == 0, i % 5 == 0) match {
[warn] ^
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 27 / 76
23. Acceptance test passes
[info] MainSpec
[info] + Main.runToSeq(1, 16) ==== ‘strings for 1 to 16
Done?
No. Client wants more features.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 29 / 76
24. Outline
1 Introduction
2 Original FizzBuzz problem
3 FizzBuzz 2: user configuration
4 FizzBuzz 3: FizzBuzzPop and beyond
5 Parallel FizzBuzz
6 Conclusion
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 30 / 76
25. Adding new features
Client wants to:
Choose two arbitrary divisors in place of 3 and 5
such as 4 and 7
Choose other arbitrary words in place of "Fizz" and "Buzz"
such as "Moo" and "Quack"
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 31 / 76
26. Type-driven refactoring
Types mean: refactoring is much more fun!
Add new tests.
Change types and code: to make new tests type check.
Refactor original code and tests: use new APIs.
Keep passing the old tests.
Delay writing code for new features.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 32 / 76
27. More features means more types
Change FizzBuzz.evaluate to Defaults.fizzBuzzer:
def runToSeq(start: Int, end: Int): Seq[String] = {
start.to(end).map(Defaults.fizzBuzzer)
}
Add new types to FizzBuzz module:
type Evaluator = Int => String
case class Config(pair1: (Int, String),
pair2: (Int, String))
type Compiler = Config => Evaluator
val compile: Compiler = {
case Config((d1, w1), (d2, w2)) =>
{ i =>
???
}
}
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 33 / 76
28. Extract original default configuration
object Defaults {
val fizzBuzzerConfig: Config =
Config(3 -> "Fizz", 5 -> "Buzz")
val fizzBuzzer: Evaluator =
FizzBuzz.compile(fizzBuzzerConfig)
// Useful to keep old implementation
val oldFizzBuzzer: Evaluator = { i =>
(i % 3 == 0, i % 5 == 0) match {
case (true, false) => "Fizz"
case (false, true) => "Buzz"
case (true, true) => "FizzBuzz"
case (false, false) => i.toString
}
}
}
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 34 / 76
29. More types means more tests
Write new property-based test over arbitrary user configurations:
val arbitraryConfig: Arbitrary[Config] = Arbitrary {
for {
(d1, d2, w1, w2) <-
arbitrary[(Int, Int, String, String)]
} yield Config(d1 -> w1, d2 -> w2)
}
def ‘Arbitrary pair of divisors: divisible by first‘ =
arbitraryConfig { config: Config =>
val evaluate = FizzBuzz.compile(config)
val Config((d1, w1), (d2, _)) = config
prop { i: Int => (i % d1 == 0 && i % d2 != 0) ==>
{ evaluate(i) ==== w1 }
}
}
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 35 / 76
30. Problem: coarse Config type
[info] ! Arbitrary divisor/word pair fizzBuzzers
[error] ArithmeticException: :
A counter-example is ’Config((0,),(0,))’:
java.lang.ArithmeticException: / by zero
(after 0 try) (FizzBuzzSpec.scala:58)
0 as a divisor crashes!
We discovered client’s underspecification.
Client says: meant to allow only divisors within 2 and 100.
We need to:
Add runtime validation when constructing Config.
Refine Config random generator.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 36 / 76
31. Add (runtime) validation
Runtime precondition contract: Scala’s require (throws exception on
failure):
val DIVISOR_MIN = 2; val DIVISOR_MAX = 100
def validatePair(pair: (Int, String)) = pair match {
case (d, _) =>
require(d >= DIVISOR_MIN,
s"divisor $d must be >= $DIVISOR_MIN")
require(d <= DIVISOR_MAX,
s"divisor $d must be <= $DIVISOR_MAX")
}
case class Config(pair1: (Int, String),
pair2: (Int, String)) {
validatePair(pair1); validatePair(pair2)
}
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 37 / 76
32. A note on exceptions and types
Exceptions are evil because they escape the type system.
In real life, I prefer to use a principled type-based validation system,
such as Scalaz.
Note: Swift does not have exceptions, so expect some type-based
libraries to emerge!
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 38 / 76
34. New test runs further, stills fails
Refactor old code to FizzBuzz.compile, to pass old tests and new test.
val compile: Compiler = {
case Config((d1, w1), (d2, w2)) =>
// Precompute, hence "compiler".
val w = w1 + w2
// Return an Evaluator.
{ i =>
(i % d1 == 0, i % d2 == 0) match {
case (true, false) => w1
case (false, true) => w2
case (true, true) => w
case (false, false) => i.toString
}
}
}
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 41 / 76
35. Outline
1 Introduction
2 Original FizzBuzz problem
3 FizzBuzz 2: user configuration
4 FizzBuzz 3: FizzBuzzPop and beyond
5 Parallel FizzBuzz
6 Conclusion
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 42 / 76
36. Generalizing to more than two divisors
Client wants FizzBuzzPop!
Given three divisors (such as 3, 5, 7).
Given three words (such as "Fizz", "Buzz", "Pop").
Example: 21 should output "FizzPop".
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 43 / 76
37. More features means more tests
Write new tests for new Defaults.fizzBuzzPopper:
def is = s2"""
${Defaults.fizzBuzzPopper(2) ==== "2"}
${Defaults.fizzBuzzPopper(21) ==== "FizzPop"}
${Defaults.fizzBuzzPopper(9) ==== "Fizz"}
${Defaults.fizzBuzzPopper(7) ==== "Pop"}
${Defaults.fizzBuzzPopper(35) ==== "BuzzPop"}
"""
Change configuration: to Seq of pairs, instead of just two:
val fizzBuzzPopperConfig: Config =
Config(Seq(
3 -> "Fizz", 5 -> "Buzz", 7 -> "Pop"
))
val fizzBuzzPopper: Evaluator =
FizzBuzz.compile(fizzBuzzPopperConfig)
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 45 / 76
38. More tests means more (or changed) types
[error] ...Defaults.scala:29: not enough arguments for
method apply:
(pair1: (Int, String), pair2: (Int, String))
com.franklinchen.FizzBuzz.Config in object Config
[error] Unspecified value parameter pair2.
[error] Config(Seq(
[error] ^
Change type Config to allow a sequence of pairs:
case class Config(pairs: Seq[(Int, String)]) {
pairs.foreach(validatePair)
}
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 46 / 76
39. Fix remaining type errors
Refactoring reveals need to implement case of more than two divisors.
val compile: Compiler = {
case Config(Seq((d1, w1), (d2, w2))) =>
val w = w1 + w2
{ i =>
(i % d1 == 0, i % d2 == 0) match {
case (true, false) => w1
case (false, true) => w2
case (true, true) => w
case (false, false) => i.toString
}
}
case _ => // TODO handle more than 2
{ i => ??? }
}
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 47 / 76
40. More computation means more types
Compile each divisor to a “rule” that awaits input.
type Rule = Int => String
val buildRule: ((Int, String)) => Rule = {
case (n, word) => { i =>
if (i % n == 0) word else ""
}
}
FizzBuzz demo time!
Two volunteers: each to play role of Rule.
One “manager” to combine two sub-results.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 49 / 76
41. Assemble the types
type Evaluator = Int => String
type Compiler = Config => Evaluator
type Rule = Int => String
val compile: Compiler = { case Config(pairs) =>
val rules: Seq[Rule] = pairs.map(buildRule) // compile
// Return an Evaluator.
{ i =>
val words: Seq[String] = rules.map { rule => rule(i) }
val combined: String = words.reduce { (x, y) => x + y }
if (combined == "") i.toString else combined
}
}
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 51 / 76
42. A note on reduce
For any value of type Seq[A], reduce: ((A, A) => B) => B.
Example: for Seq[String], reduction with string concatenation + returns
the concatenation of all the strings in the sequence.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 52 / 76
43. Test failure: coarse types again
nfo] x Arbitrary pair of divisors: divisible by first
rror] A counter-example is ’Config(List((8,), (32,)))’
(after 0 try)
rror] A counter-example is ’32405464’
(after 0 try - shrinked (’1150076488’ -> ’32405464’))
rror] ’32405464’ is not equal to ’’
(FizzBuzzSpec.scala:71)
Demo time!
Configuration: Seq(3 -> "", 5 -> "Buzz")
Input: 9 (note: divisible by 3)
Output: should be "" (because of the part divisible by 3)
Output was: "9"
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 53 / 76
44. Assemble the types
type Evaluator = Int => String
type Compiler = Config => Evaluator
type Rule = Int => String
val compile: Compiler = { case Config(pairs) =>
val rules: Seq[Rule] = pairs.map(buildRule) // compile
// Return an Evaluator.
{ i =>
val words: Seq[String] = rules.map { rule => rule(i) }
val combined: String = words.reduce { (x, y) => x + y }
if (combined == "") i.toString else combined
}
}
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 54 / 76
45. Property-based testing rescued us again!
Be honest: would you have caught this bug manually?
I didn’t.
I never wrote FizzBuzzPop examples testing empty strings.
Property-based testing reveals unexpected corner cases.
(Empty “fizz” and “buzz” word strings).
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 55 / 76
46. An empty string is not equivalent to no string
Presence of something “empty” is not equivalent to no thing.
Sending someone an empty email versus not sending any email.
Many programming languages get this wrong.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 56 / 76
47. Option[A] type
Option[A] is one of two possibilities:
None
Some(a) wraps a value a of type A.
For example, Some("") is not the same as None.
val fizzFor3 = Some("") // multiple of 3
val buzzFor3 = None // not multiple of 5
val fizzbuzzFor3 = Some("") // fizzed ""
val fizzFor2 = None // not multiple of 3
val buzzFor2 = None // not multiple of 5
val fizzbuzzFor2 = None // not multiple of any
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 57 / 76
48. Cleaning up the types
// was: type Rule = Int => String
type Rule = Int => Option[String]
Useful type errors:
und : String
quired: Option[String]
word
^
und : String("")
quired: Option[String]
""
^
und : Seq[Option[String]]
quired: Seq[String]
val words: Seq[String] = rules map { rule => rule(i) }
^
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 58 / 76
49. Fix the type errors: our rule builder
type Rule = Int => Option[String]
val buildRule: ((Int, String)) => Rule = {
case (n, word) => { i =>
(i % n == 0).option(word)
}
}
Demo time!
(Instructions: for result Some(s), hold up the string, else don’t hold
up anything)
Configuration: Seq(3 -> "", 5 -> "Buzz")
Input: 9
Output: now correctly is ""
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 59 / 76
50. Fix the type errors: our compiler
val compile: Compiler = { case Config(pairs) =>
val rules: Seq[Rule] = pairs map buildRule
{ i =>
val wordOptions: Seq[Option[String]] =
rules.map { rule => rule(i) }
val combinedOption: Option[String] =
wordOptions.reduce(addOption)
combinedOption.getOrElse(i.toString)
}
}
We need to write: addOption
Scala standard library provides: getOrElse
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 60 / 76
51. “Addition” for Option[String]
def addOption(a1: Option[String], a2: Option[String]):
Option[String] = (a1, a2) match {
case (Some(s1), None) => Some(s1)
case (None, Some(s2)) => Some(s2)
case (Some(s1), Some(s2)) => Some(s1 + s2)
case (None, None) => None
}
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 61 / 76
52. Getting A back out of Option[A]
Do not lose information!
getOrElse inspects the
and either
returns the value v inside a Some(v),
or else returns the specific default value.
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 62 / 76
53. The same thing, in Swift
func addOption(a1: String?, a2: String?) -> String? = {
switch (a1, a2) {
case (let .Some(s1), .None): return .Some(s1)
case (.None, let .Some(s2)): return .Some(s2)
case (let .Some(s1), let .Some(s2)): return .Some(s1+s2)
case (.None, .None): return .None
}
}
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 64 / 76
54. Transform information; don’t destroy it
Did you notice? Our new code no longer uses if.
Bug cause: destroying information, using if
Building a rule: if (i % n == 0) word else ""
Obtaining a final string answer:
if (combined == "") i.toString else combined
Transforming information
To Option[String]: (i % n == 0).option(word)
To String: combinedOption.getOrElse(i.toString)
Type-directed design tip
We could have saved trouble up front, by using precise types.
Avoid if, when possible.
Avoid String (but required at I/O boundaries of program).
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 65 / 76
55. Bonus: the final code in Swift
typealias Evaluator = Int -> String
typealias Config = [(Int, String)]
typealias Compiler = Config -> Evaluator
typealias Rule = Int -> String?
let buildRule: ((Int, String)) -> Rule = { n, word in
{ i in return (i % n == 0) ? word : nil } }
}
let compile: Compiler = { pairs in
let rules: [Rule] = pairs.map(buildRule)
return { i in
let wordOptions = rules.map { rule in rule(i) }
let combinedOption = wordOptions.reduce(nil, addOption)
if let combined = combinedOption { return combined }
else { return String(i) }
}
}Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 66 / 76
56. Outline
1 Introduction
2 Original FizzBuzz problem
3 FizzBuzz 2: user configuration
4 FizzBuzz 3: FizzBuzzPop and beyond
5 Parallel FizzBuzz
6 Conclusion
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 67 / 76
57. Parallelism
Use of map: parallelizable; there are high-performance parallel
collections for Scala.
Use of reduce: parallelizable because of the monoid property:
Option[String] is a Monoid
There is an identity element (None).
There is a binary associative operator (addOption).
Fantastically important in practice!
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 68 / 76
58. Final demo!
Demo time!
Configuration:
Seq(3 -> "Fizz", 5 -> "Buzz", 7 -> "Pop", 2 -> "Boom")
Tree of volunteers to simulate concurrency:
Four at leaves.
Two “middle managers” each handling two leaves.
One top-level manager handling two middle managers.
Input: 42
Output: "FizzPopBoom"
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 69 / 76
59. Final parallelized code
val parallelCompile: Compiler = { case Config(pairs) =>
val rules = pairs.
toArray.
toPar.
map(buildRule)
{ i: Int => rules.
map { rule => rule(i) }.
reduce(addOption).
getOrElse(i.toString)
}
}
Coding style tip
This level of conciseness is not always best: maybe too “clever”?
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 70 / 76
60. Parallelism summary
We discovered a theoretical speedup for generalized FizzBuzz:
Sequential: O(n)
Parallel: O(log n) (given log n processors, and omitting some
technical subtleties)
Also, driver outer loop can be sped up:
Sequential loop on 1 to m: O(m)
Parallel loop: O(1) (given m processors)
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 72 / 76
62. Outline
1 Introduction
2 Original FizzBuzz problem
3 FizzBuzz 2: user configuration
4 FizzBuzz 3: FizzBuzzPop and beyond
5 Parallel FizzBuzz
6 Conclusion
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 74 / 76
63. Conclusion
Tests are great.
Types are great.
Tests and types work hand in hand, driving design and program
evolution.
Modern typed languages such as Scala promote fun, correct
programming!
It’s a great time to be learning and using a modern typed language:
Apple ditched Objective C for Swift.
Code, slides, article
Go to https://github.com/franklinchen/
talk-on-type-directed-tdd-using-fizzbuzz
The article has more detail omitted in the presentation.
The hyperlinks in all provided PDFs are clickable.
The Swift code:
https://github.com/franklinchen/fizzbuzz-swift
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 75 / 76
64. Some free online courses on modern typed functional
programming
Using Scala: Functional Programming Principles in Scala on
Coursera, taught by Martin Odersky (inventor of Scala)
Using Haskell: Introduction to Functional Programming on EdX,
taught by Erik Meijer (Haskell hero)
Franklin Chen http://franklinchen.com/ Exploring type-directed TDD w/FizzBuzz Pittsburgh TechFest 2014 76 / 76