Created
October 30, 2014 10:24
-
-
Save 4e6/9bc0e44725bec62926fa to your computer and use it in GitHub Desktop.
Null Driven Development. Use AnyRef with for comprehensions.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Pojo { | |
def doStuff(): Unit = println("rocket launched!") | |
} | |
object Example { | |
import NullDrivenDevelopment._ | |
def none: Pojo = null | |
def pojo: Pojo = new Pojo | |
// NPE | |
def testNPE(pojo: Pojo = none) = pojo.toString | |
// null | |
def testMap(pojo: Pojo = none) = for { | |
p ← pojo | |
} yield p.toString | |
// null | |
def testFlatMap(pojo: Pojo = none) = for { | |
p ← new Pojo | |
q ← pojo | |
} yield q.toString | |
// null | |
def testFilter() = for { | |
p ← pojo | |
q ← pojo | |
if p.toString == q.toString | |
} yield p | |
// Vector(m,i,s,c,...) | |
def testNotNull() = for { | |
p ← pojo | |
q ← pojo | |
ps = p.toString | |
qs = q.toString | |
(x, y) ← ps zip qs | |
if x == y | |
} yield x | |
// Effect | |
def testEffect() = for { | |
p ← new Pojo | |
} p.doStuff() | |
// Nothing | |
def testNothing() = for { | |
p ← new Pojo | |
n ← none | |
} n.doStuff() | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Naive effect system used in `NullMO#foreach` | |
sealed trait Effect | |
case object Nothing extends Effect | |
case object Effect extends Effect { | |
def apply[A](a: ⇒ A): Effect = a match { | |
case Nothing ⇒ Nothing | |
case _ ⇒ this | |
} | |
} | |
object NullDrivenDevelopment { | |
// Don't dare to call it a Monad, so it's just MO | |
implicit class NullMO[A <: AnyRef](a: A) { | |
def map[B <: AnyRef](f: A ⇒ B): B = | |
if (a ne null) f(a) | |
else null.asInstanceOf[B] | |
def flatMap[B <: AnyRef](f: A ⇒ B): B = | |
map(f) | |
def filter(p: A ⇒ Boolean): A = | |
if ((a ne null) && p(a)) a | |
else null.asInstanceOf[A] | |
def withFilter(p: A ⇒ Boolean): A = | |
filter(p) | |
def foreach[B](f: A ⇒ B): Effect = | |
if (a ne null) Effect(f(a)) | |
else Nothing | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment