Oh, but fully agreed, nested ternaries is right out. In fact, usually in those other cases too, it's just annoying that there's not a good alternative.
Oh, but fully agreed, nested ternaries is right out. In fact, usually in those other cases too, it's just annoying that there's not a good alternative.
function deriv(exp, variable) {
if (is_number(exp)) {
return 0;
}
if (is_variable(exp)) {
if (is_same_variable(exp, variable)) {
return 1;
} else {
return 0;
}
}
if (is_sum(exp)) {
return make_sum(deriv(addend(exp), variable),
deriv(augend(exp), variable));
}
if (is_product(exp)) {
return make_product(deriv(multiplier(exp),
variable),
multiplicand(exp)))
}
return error(exp, "unknown expression type -- deriv");
}I'll add a couple of things onto this: early returns are very helpful for me in avoiding nesting if statements (although that's less applicable in this specific example).
function op(cond) {
if (cond) {
//do something
}
}
function op (cond) {
if (!cond) { return; }
//do something
}
And it's good to remember that you can basically stick functions anywhere including inline, so it's not necessarily a requirement to take a function like this and move it to a top level as a private function. If you're only using it in one place you can just define it and call it anonymously.And don't be afraid to still use ternary operators non-nested. There's a sibling comment complaining about the nested if statement. If that really bothers you, you can still do:
if (is_variable(exp)) {
return is_same_variable(exp, variable) ? 1 : 0;
} if (is_same_variable(exp, variable)) {
return 1;
} else {
return 0;
}
should be return +is_same_variable(exp, variable)"Languages do not differ in what they make possible, but in what they make easy."
It's not the biggest thing in the world, and I don't want to distract from the rest of the book, but this is a situation where writing a one or two line helper function:
const _ = (cond, a, b) => cond ? a : b;
would have made the code much more readable without much downside that I can see -- at least to my subjective opinion. Maybe I'm missing something.Edit: comment below correctly points out that if it's important for you to avoid immediate evaluation, you'll need to wrap your conditionals in functions.
_(cond, () => a, () => b)
And _ becomes: const _ = (cond, a, b) => cond? a(): b();
And it does matter in this case when looking at the last condition which signals an error (does not return an error value if I understand it correctly). In which case your _ would raise an error even when not appropriate.I'm not sure it matters here, the error you're pointing out looks to be getting returned (unless I'm misunderstanding what the book intends the `error` function to do), and creating an Error in Javascript is fine, it doesn't break your program until it's actually thrown.
Edit: just looked at your comment again, and you're saying it does actually throw the error rather than returning it :) So double-corrected on my part :)
But your point stands regardless. There will be scenarios where what you're talking about matters -- JSX also follows this pattern of immediate evaluation and yeah, I see errors from that plenty of times. So it's good to mention.