Open benadamstyles opened 7 years ago
Unfortunately the syntax isn't too great:
maybe(valueX)
.flatMap(x => maybe(valueY).map(y => ({x, y})))
.foreach({x, y} => {
// use x and y
})
you can make it a tiny bit shorter by wrapping the values with maybe first e.g.
const maybeX = maybe(valueX)
const maybeY = maybe(valueY)
maybeX
.flatMap(x => maybeY.map(y => ({x, y})))
.foreach({x, y} => {
// use x and y
})
Something that Scala has which is quite nice for this is a for comprehension
which would look like:
for {
x <- maybeX
y <- maybeY
// do something with x, y / return result
} yield
... but I think your if statement is fine :)
Ah ok, yep. I was close. One thing I'm struggling with actually is when to use .map
and when to use .flatMap
. I know there's the simple rule of "flatMap
if you're returning a Maybe
", but I'm not always sure whether I want to return a Maybe
or a "possibly null value". Perhaps I never want to return a "possibly null value" – should I always be wrapping one of those in maybe()
?
I wonder if there could be an extra method called something like and
or join
which would work something like:
maybe(valueX)
.and(valueY)
.and(valueZ)
.foreach(([x, y, z]) => {
// use x, y and z
})
Just thought, couldn't you do this to make it even shorter? Given that you already know maybeX
is a Maybe
?
const maybeX = maybe(valueX)
const maybeY = maybe(valueY)
maybeX
.flatMap(x => maybeY)
.foreach(y => {
const x = maybeX.just() // we know maybeX is a Just because it passed the flatMap test
// use x and y
})
You use map
when you transform the value inside the maybe to another value. flatMap
is when you need to return a Maybe
instead and is most useful unwrapping more than one Maybe
or when using the just
and nothing
.
The best way to visualise and understand flatMap
is to know that it's shorthand for flatten
and would be the same as doing map
and then flatten
. For example:
maybeX.map(x => maybeY) // Maybe(Maybe(y))
whereas
maybeX.flatMap(x => maybeY) // Maybe(y)
so Maybe(Maybe(y))
becomes Maybe(y)
by using flatMap
.
It would be possible to make another type of Maybe
that takes an array and only lets you map
/ forEach
when they're all non empty values.
For example:
maybe([1, 2, 3])
.filter(a => a.every(e => maybe(e).isJust()))
.foreach(console.log)
Also in response to your last comment: you could do it like that. But I wouldn't.. as you're creating a dependency that might break if someone updates it. It's also perhaps less clear.
The preferred method would be to have default values for your Maybe
's by using orJust()
.
This is so useful, thanks. I think I've finally "grokked" flatMap
now... Thanks for all your help!
For example:
maybe([1, 2, 3]) .filter(a => a.every(e => maybe(e).isJust())) .foreach(console.log)
@alexanderjarvis I'm finding myself doing this a lot. Would you consider a PR that adds a new method, something like .all()
(or whatever you think) which does this? The code would be something along the lines of:
all() {
if (Array.isArray(this.value) && this.value.every(x => maybe(x).isJust())) {
return this
} else {
return nothing
}
}
And you would use it like:
maybe([1, 2, 3])
.all()
.map(transform)
.orJust([])
What would the
maybe
version of the following be?Would it be this?
This doesn't seem very functional. Maybe I'm missing something super obvious. Thanks!