Skip to content

Commit

Permalink
Update README with links to examples of other null safe implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanstull committed Sep 21, 2024
1 parent e596852 commit 6ca083e
Showing 1 changed file with 28 additions and 11 deletions.
39 changes: 28 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ The purpose of this library is to provide a quick, easy, readable/writable, and

### Quick comparison of null-safe implementations:

| Implementation | Null-safe | Readable & Writable | Efficient |
|---------------------- |----------- |------------------- |----------- |
| 🎉 **ScalaNullSafe** 🎉 | ✔️ | ✔️ | ✔️ |
| Normal access || ✔️ | ✔️ |
| Explicit null-checks | ✔️ || ✔️ |
| Option flatMap | ✔️ | ⚠️ ||
| For loop flatMap | ✔️ | ⚠️ ||
| Null-safe navigator | ✔️ | ⚠️ | ⚠️ |
| Try-catch NPE | ✔️ | ✔️ | ⚠️ |
| thoughtworks NullSafe DSL| ✔️ | ✔️ | ⚠️ |
| Monocle Optional (lenses)| ✔️ | 💀 | 💀 |
| Implementation | Null-safe | Readable & Writable | Efficient |
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------- |------------------- |----------- |
| 🎉 [**ScalaNullSafe**](https://github.com/ryanstull/ScalaNullSafe/blob/e596852bd54fd3848bc9fa91bdee33f4024afde1/benchmarks/src/test/scala/com/ryanstull/nullsafe/Benchmarks.scala#L132) 🎉 | ✔️ | ✔️ | ✔️ |
| [Normal access](https://github.com/ryanstull/ScalaNullSafe/blob/e596852bd54fd3848bc9fa91bdee33f4024afde1/benchmarks/src/test/scala/com/ryanstull/nullsafe/Benchmarks.scala#L27) || ✔️ | ✔️ |
| [Explicit null-checks](https://github.com/ryanstull/ScalaNullSafe/blob/e596852bd54fd3848bc9fa91bdee33f4024afde1/benchmarks/src/test/scala/com/ryanstull/nullsafe/Benchmarks.scala#L30-L45) | ✔️ || ✔️ |
| [Option flatMap](https://github.com/ryanstull/ScalaNullSafe/blob/e596852bd54fd3848bc9fa91bdee33f4024afde1/benchmarks/src/test/scala/com/ryanstull/nullsafe/Benchmarks.scala#L74-L79) | ✔️ | ⚠️ ||
| [For loop flatMap](https://github.com/ryanstull/ScalaNullSafe/blob/e596852bd54fd3848bc9fa91bdee33f4024afde1/benchmarks/src/test/scala/com/ryanstull/nullsafe/Benchmarks.scala#L82-L90) | ✔️ | ⚠️ ||
| [Null-safe navigator](https://github.com/ryanstull/ScalaNullSafe/blob/e596852bd54fd3848bc9fa91bdee33f4024afde1/benchmarks/src/test/scala/com/ryanstull/nullsafe/Benchmarks.scala#L120-L123) | ✔️ | ⚠️ | ⚠️ |
| [Try-catch NPE](https://github.com/ryanstull/ScalaNullSafe/blob/e596852bd54fd3848bc9fa91bdee33f4024afde1/benchmarks/src/test/scala/com/ryanstull/nullsafe/Benchmarks.scala#L104-L109) | ✔️ | ✔️ | ⚠️ |
| [thoughtworks NullSafe DSL](https://github.com/ryanstull/ScalaNullSafe/blob/e596852bd54fd3848bc9fa91bdee33f4024afde1/benchmarks/src/test/scala/com/ryanstull/nullsafe/Benchmarks.scala#L169-L172) | ✔️ | ✔️ | ⚠️ |
| [Monocle Optional (lenses)](https://github.com/ryanstull/ScalaNullSafe/blob/e596852bd54fd3848bc9fa91bdee33f4024afde1/benchmarks/src/test/scala/com/ryanstull/nullsafe/Benchmarks.scala#L139-L162) | ✔️ | 💀 | 💀 |

Key: ✔️ = Good, ⚠️ = Sub-optimal, ⛔ = Bad, 💀 = Horrible

Expand Down Expand Up @@ -224,9 +224,26 @@ To be fully explicit, the `??` macro would transform the above example to:
}
```

### `??` compared to `?`

Compared to the `?` macro, in the case of a single arg, the `??` macro checks that the _entire_ expression is not null; whereas
the `?` macro would just check that the preceding elements (e.g. `a` and `b` in `a.b.c`) aren't null before returning the default value.

For example consider the following example:

```scala
case class A(b: B)
case class B(c: C)
case class C(s: String)

val a = A(B(C(null)))

assert(?(a.b.c.s, "Default") == null)
assert(??(a.b.c.s)("Default") == "Default")
```

For `?`, the default value only gets used if there would've been a `NullPointerException`. So the return value of `?` could still be `null` even if you supply a default.

### Safe translation

All of the above work for method invocation as well as property access, and the two can be freely intermixed. For example:
Expand Down

0 comments on commit 6ca083e

Please sign in to comment.