Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

Grokking TechTalk #16: Maybe functor in javascript

750 vues

Publié le

Speaker: Lam Huynh - Senior FrontEnd Developer @ 8Bit Rockstars Co. Ltd

Bio: A Javascript user who is interested in language theory

Description: Introduction to Maybe Functor in Javascript, a concept borrowed from various functional programming languages to help you write cleaner code while still being null-safe.

Publié dans : Technologie
  • Awesome lonely girl looking for fun on webcam with the you now - www.xslideshare.usa.cc
       Répondre 
    Voulez-vous vraiment ?  Oui  Non
    Votre message apparaîtra ici

Grokking TechTalk #16: Maybe functor in javascript

  1. 1. Maybe Functor in Javascript Another approach to null handling 1
  2. 2. 2
  3. 3. Origin of Null Pointer Exception ● Sir Tony Hoare was designing type systems for the language ALGOL W and he put “Null Pointer Exception” as part of the language, because “because it was so easy to implement” ● In 2009, he called it “The Billion Dollar Mistake” 3
  4. 4. What we want: getCountry('vn').getCity('HCMC').population; What we have to do var country = getCountry('vn'); if (country !== null) { var city = country.getCity('HCMC'); if (city !== null) { var population = city.population; } } How do we fight NULL? 4 Drawbacks: ● Looks complicated ● Error-prone, especially when there are many nesting ifs ● Tedious to write ● Declares a lot of useless variables
  5. 5. ● A Functor is a container of a value Introduction to Functor 5 A value A container of value ● A simple Functor can be implemented through an ES6 class class Functor { constructor(value) { this.value = value; } }
  6. 6. One important thing about Functor 6 By definition, a functor needs to implement a map function
  7. 7. Remember Array Map? 7 Let’s look at Array’s map function. var addOne = (x) => x + 1; var square = (x) => x * x; var result = [1, 2, 3] .map(addOne) // [2, 3, 4] .map(square); // [4, 9, 16]
  8. 8. Implement map for Functor 8 class Functor { constructor(value) { this.value = value; } map(fn) { var newValue = fn(this.value); return new Functor(newValue); } }
  9. 9. Let’s see it in action (1) 9 var addOne = (x) => x + 1; var functorOf6 = new Functor(5).map(addOne); // Functor(6)
  10. 10. It can also work with any value, for example, an object: var toUpperCase = (str) => str.toUpperCase(); var exciting = (someName) => someName + ’!!!!!!!’; var value = { name: 'grokking' }; var containerOfValue = new Functor(value) .map(thing => thing.name) // Functor(‘grokking’) .map(toUpperCase) // Functor(‘GROKKING’) .map(exciting); // Functor(‘GROKKING!!!!!!!’) Let’s see it in action (2) 10
  11. 11. Notice that our actual value is still inside the Functor. var functorOf36 = new Functor(5) .map(addOne) // Functor(6) .map(square); // Functor(36) var result = functorOf36 + 100; // Functor(36) + 100 ??????? How to get the value inside Functor 11 Let’s add another method to Functor to extract the value. class Functor { get() { return this.value; } }
  12. 12. var valueInside = new Functor(5) .map(addOne) // Functor(6) .map(square); // Functor(36) .get(); // 36 var toUpperCase = (str) => str.toUpperCase(); var exciting = (someName) => someName + '!!!!!!'; var valueInside = new Functor({ name: 'grokking' }) .map(people => people.name) // Functor(‘grokking’) .map(toUpperCase) // Functor(‘GROKKING’) .map(exciting); // Functor(‘GROKKING!!!!!!!’) .get(); // 'GROKKING!!!!!!!' Now we can get the value inside Functor 12
  13. 13. class Functor { constructor(value) { this.value = value; } map(fn) { var newValue = fn(this.value); return new Maybe(newValue); } get() { return this.value; } } Full implementation of Functor 13
  14. 14. var addOne = (x) => null; // we return Null var square = (x) => x * x; var valueInside = new Functor(1) .map(addOne) // Functor(null) .map(square); // Functor(null * null) ???? .get(); // ???? But we are still affected by NULL 14 The solution is to turn our functor into a Maybe
  15. 15. ● Maybe is a kind of Functor that is Null- friendly. Real magic happens in the map function ● Maybe that contains a real value (not null) is usually called a Just / Some ● Maybe that contains null value is usually called a Nothing / None Introduction to Maybe 15 Maybe(value) = Just(value) Maybe(null) = Nothing
  16. 16. class Maybe { constructor(value) { this.value = value; } map(fn) { if (this.value !== null) { // Magic happens here var newValue = fn(this.value); return new Maybe(newValue); } return new Maybe(null); } getOrElse(fallBackValue) { return (this.value === null) ? this.value : fallBackValue; } } Let’s implement Maybe 16
  17. 17. It’s pretty much the same as Functor’s example. The only difference is that we use getOrElse instead of get var addOne = (x) => x + 1; var square = (x) => x * x; var result = new Maybe(3) .map(addOne) // Maybe(4) .map(square) // Maybe(16) .getOrElse(0); // 16 Maybe in action 17
  18. 18. When Maybe contains NULL, it will not map anymore var result = new Maybe(3) .map(x => null) // Maybe(null) .map(x => x * x) // Maybe(null) .getOrElse(0); // 0 var result = new Maybe(3) .map(x => x + 1) // Maybe(4) .map(x => null) // Maybe(null) .getOrElse(0); // 0 When Null happens 18
  19. 19. Some real world examples var family = { grandma: { mother: { you: 'YOUR NAME HERE' } } }; var you = new Maybe(family.grandma) .map(grandma => grandma.mother) .map(mother => mother.you) .getOrElse('DEFAULT NAME'); // returns “YOUR NAME HERE” var family = { grandma: null }; var you = new Maybe(family.grandma) .map(grandma => grandma.mother) .map(mother => mother.you) .getOrElse('DEFAULT NAME'); // returns “DEFAULT NAME” 19 We can use it to safely access nested objects
  20. 20. Compare with what we used to do 20 var you = family.grandma.mother.you || 'DEFAULT NAME'; var you = 'DEFAULT NAME'; if (family.grandma && family.grandma.mother && family.grandma.mother.you) { you = family.grandma.mother.you; } var you = new Maybe(family.grandma) .map(grandma => grandma.mother) .map(mother => mother.you) .getOrElse('DEFAULT NAME'); Short, but unsafe Safe, but long and nested Safe and flattened
  21. 21. var population = new Maybe(getCountry('vn')) .map(country => country.getCity('HCMC')) .map(city => city.population) .getOrElse(0); Some real world examples var country = getCountry('vn'); if (country !== null) { var city = country.getCity('HCMC'); if (city !== null) { var population = city.population; } } 21 We can rewrite our example earlier Into shorter and flattened code
  22. 22. ● Is just a container of value ● Is a fundamental concept in Functional Programming. From there you can explore Applicative and Monad ● Is a kind of functor that checks null on each map ● Helps flatten your code ● Is used widely in many other languages: - Haskell, Elm: Maybe Recap 22 Maybe Functor
  23. 23. References ● https://github.com/fantasyland/fantasy-land Fantasy Land Specification ● https://cwmyers.github.io/monet.js/ Powerful abstractions for Javascript ● http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html Functor, Applicatives, Monads in pictures ● https://en.wikipedia.org/wiki/Functor (looks scary with all the math) ● http://www.mokacoding.com/blog/functor-applicative-monads-in-pictures/ (Maybe in Swift) ● http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html Java 8 Optional 23

×