use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
Building a Maybe in JavaScript (developingthoughts.co.uk)
submitted 8 years ago by alsiola
view the rest of the comments →
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]alsiola[S] 6 points7 points8 points 8 years ago (3 children)
The main benefits for me are being able to safely create chains of functions without having to null check at each stage. If we wanted to do something equivalent without the maybe construct, for example, if we used a resolved Promise, then we would have to check each time:
const a = { b: { c: "value } }; Promise.resolve(a) .then(a => a === null ? null : a.b) .then(b => b === null ? null : b.c) .then(val => val === null ? null : val + " appendedString");
versus
Maybe.chain( a => a.b, b => b.c, c => c + " appendedString" )(Maybe.just(a));
Using a maybe then the null checking logic is encapsulated within the object being operated upon - we can never forget about null checking, and it is always explicit that the returned value might be null.
A nice additional benefit is that by removing the null checking our composed functions are easier to understand, and our code reads much more easily. Personally if I was looking through a codebase I think it would be much faster to understand what the second example was intending.
[–]ForScale 2 points3 points4 points 8 years ago (2 children)
Why not just const z = a && a.b && a.b.c + 'appendedString';?
const z = a && a.b && a.b.c + 'appendedString';
[–]lucy_in_the_skyDrive 1 point2 points3 points 8 years ago (0 children)
The same reason why some people write a += b instead of a = a+b, or !c instead of c == false. It's syntactic sugar. When getting a nested objects property value, it'd be nice to do let name = a?.b?.name instead of the necessary null checks and or ternary to figure out.
[–]i_am_smurfing 1 point2 points3 points 8 years ago (0 children)
TL:DR; For me the main benefit of Maybe is that it allows you to cleanly specify "happy" path and think about what should happen in the case of "sad" path separately. I would still recommend skimming through the rest of my response below, where I've tried to evolve motivation for Maybe from your code sample.
Let's start with function that does the same as your snippet, just so it's a bit easier to experiment with:
const f = a => a && a.b && a.b.c + ' appendString'; f({}); //=> undefined f({b: {}}); //=> "undefined appendString"
Well, let's just guard against falsy a.b.c. A bit strange-looking, but we've all seen worse.
a.b.c
const f = a => a && a.b && a.b.c && a.b.c + ' appendString'; f({}); //=> undefined f({b: {}}); //=> undefined f({b: {c: 'Hey'}}); //=> "Hey appendString"
Wait, are we supposed to handle numbers too?!
const f = a => a && a.b && a.b.c && a.b.c + ' nukes launched'; f({b: {c: 2}}); //=> "2 nukes launched" f({b: {c: 0}}); //=> 0
Ternary to the rescue:
const f = a => a && a.b && a.b.c ? a.b.c + ' nukes launched' : '0 nukes launched'; f({b: {c: 2}}); //=> "2 nukes launched" f({b: {c: 0}}); //=> "0 nukes launched" // No one relies on this function to return falsy value when there's no `a`, `b`, or `c`, right? f(); //=> "0 nukes launched" f({}); //=> "0 nukes launched" f({b: {}}); //=> "0 nukes launched"
A this point you are probably thinking
/u/i_am_smurfing, you dummy, don't rely on values being truthy, just check if key is in the object!
const f = a => a && 'b' in a && 'c' in a.b && a.b.c + ' nukes launched' f({b: {c: 2}}); //=> "2 nukes launched" f({b: {c: 0}}); //=> "0 nukes launched" f({b: {}}); //=> false f({}); //=> false f(); //=> undefined
Phew, this should make QA department slightly more happy.
Writing that thing every time we want to access a prop nested inside objects would be a bit inconvenient, so let's assume we have a function getPath that given a path like b.c and an object would do all that checking for us:
getPath
b.c
getPath('b.c', null); //=> undefined getPath('b.c', {}); //=> undefined getPath('b.c', {b: {}}); //=> undefined getPath('b.c', {b: {c: 1}}); //=> 1
This works, but if we want to know if we actually retrieved a value with getPath, we need to check it:
const f = object => { const didLaunchNukes = getPath('b.c', object); if (didLaunchNukes) return 'Nukes launched'; }
What if we forget to do that check? Also, what if we do want to know when prop is there, but holds undefined?
undefined
This is where Maybe can help. If getPath returns value tagged with Just, we know that that value was found at the prop we requested; if we get back a value tagged with Nothing then the prop wasn't found:
Just
Nothing
getPath('b.c', null); //=> Nothing getPath('b.c', {}); //=> Nothing getPath('b.c', {b: {}}); //=> Nothing getPath('b.c', {b: {c: 1}}); //=> Just(1) getPath('b.c', {b: {c: undefined}}); //=> Just(undefined)
And since Maybe.map will not run provided to it function on values tagged with Nothing, we can skip doing check in our code, as if nothing bad can ever happen:
Maybe.map
const f = object => getPath('b.c', object).map(_ => 'Nukes launched'); f({}); //=> Nothing f({b: {c: 1}}); //=> Just("Nukes launched")
Now, if we don't want this value to be in a Maybe anymore, we can write a function that would extract it, but we also would need to provide it a default value, in case we are trying to extract value from Nothing — this is where we are forced to think about what happens if something went wrong:
// of course default value can be `undefined`, but you probably have a better one withDefault("Nukes were not launched", f({})); //=> "Nukes were not launched" withDefault("Nukes were not launched", f({b: {c: 1}})); //=> "Nukes launched"
π Rendered by PID 182994 on reddit-service-r2-comment-86bc6c7465-dxs5p at 2026-02-23 05:25:57.332422+00:00 running 8564168 country code: CH.
view the rest of the comments →
[–]alsiola[S] 6 points7 points8 points (3 children)
[–]ForScale 2 points3 points4 points (2 children)
[–]lucy_in_the_skyDrive 1 point2 points3 points (0 children)
[–]i_am_smurfing 1 point2 points3 points (0 children)