proposal-do-expressions
proposal-do-expressions copied to clipboard
Beautify and better examples
The JSX example was poor due to its misuse of do. do, in this example, was being used where a ternary is often used, so to ensure the reason to use do was more effectively communicated I designed a more complicated example where a ternary would be unpreferable. Semicolons were being used off and on, therefore, I removed them as to avoid confusion. Increased readability in the conditional section and removed unnecessary curly braces.
Any word on this being able to be merged?
Ping?
These really are great examples. Thanks, @ChrisBrownie55. I hope these are merged.
@jonathantneal Thanks, it's been a hot minute since I introduced this so I'm thinking it won't get merged though lol
I would suggest adding null coalescing example:
declare const cache: Map<T, R>;
function heavyTransform(obj: T) {
return cache.get(obj) ?? do {
const computedValue = ...;
cache.set(obj, computedValue);
computedValue
}
}
Or similar... I always dream of this when writing this kind of look ups...
One of those examples aren't that strong, the if else could easily be a ternary:
const x = (
foo()
? a
: bar()
? b
: c
)();
I'd suggest the following:
- use more
const(really important part of FP and value-returning blocks in general is immutability) - give an example where someone would use a
letand seperate assignments - give an example that requires more that just a value in the if statement body (@Akxe's example almost fits this)
For the second, a try/catch would be a great example, as a ternary wouldn't fit at all.
let result;
try {
const random = Math.random();
const powed = random ** random;
result = calc_something(powed, random);
} catch {
// aww, `calc_something` threw, fallback
result = calc_something_else(0.5, 4);
}
for (3), something like this might be better:
const x = do {
if ( foo() ) {
a();
} else if ( bar() ) {
const random = Math.random();
const temp = get_nth(random ** random);
temp;
} else {
c();
}
};
as a ternary would be far too verbose, and it would require a iife to match the second if.
^ these are 2 poor examples, please do better than I did ;)
Nested ternaries are often considered poor style, and common styleguides/eslint configs forbid them.
Obligatory note that those aren't nested; they are chained.
@rkirsling they're definitely nested; if you put parens to match default precedence, one of the ternaries will be contained within the truthy or falsy branch of the other ternary.
It's a critical distinction because we don't call if {} else if {} else {} "nested ifs", even though else if is likewise not its own thing under the hood.
Recommending against nesting is pretty uncontroversial, but a ? b : c ? d : e is a baby too often thrown out with that bathwater.
If there's one hill I'll die on in programming language design, it's definitely this. :smile:
Personally, I see things exactly the same way that @ljharb sees it, I consider ? : ? : to be "nested," even though they don't have the parenthesis like ? : (? :) does, and am personally okay with writing if () { } else { if () {} else {} }, so I am likely to be a minority here regarding sytlistic preferences.
Now, even though I'm one of the (apparently few) people who are perfectly fine with reading and using ternaries, I still see value in block scopes that can return values, but attempting to create one thing in a language to obsolete another one solely due to syntax seems like a very weak argument. That is why I strongly suggest showing where "do blocks" cannot easily be replaced with another syntatical construct (if/else vs ?:).
I think this PR is dead. However, for the sake of readability, multiple ternary chains can become less readable in some cases but that doesn't mean you can't use them if they suit your need. If this was all about the React example, I added more else-if-statements because, from my experience, instead of chaining ternaries together (especially when the values or conditions are multiple lines long), it's often easier to extract the logic out of the return-statement.