So:
auto result = boolean_flag ?
compute_property() :
compute_another_property();
if (boolean_flag) {
do_this();
} else {
do_that();
}So:
auto result = boolean_flag ?
compute_property() :
compute_another_property();
if (boolean_flag) {
do_this();
} else {
do_that();
}Seriously though, there's nothing in ternary operator that says it should only be used for side-effect free code. Especially in C++ (or Java), which doesn't even differentiate between stateless and stateful code on the language level.
IMO ternary is a perfect solution for the case where you want to assign or return a different value based on a boolean condition. Whether or not the code in branches is side-effect free is irrelevant.
Personally, where I try to avoid using ternary operator, is places where I don't care about returned value. So "yes" for:
auto foo = [condition] ? possibly_stateful_then() : possibly_stateful_else();
no for: [condition] ? then_statement() : else_statement();As i asked below: Why though?
Also,
> in languages we're discussing
Don't bury that lede. If you're restricting what you're saying to a specific language say that bold and as the very first thing, so people don't end up wasting their time parsing your post in a different context. Rude.
I like to think of it as using the dedicated tool for a job it was designed for. In my mind, it's a good rule of thumb because it enhances readability (compare "the principle of least surprise").
> Don't bury that lede. If you're restricting what you're saying to a specific language say that bold and as the very first thing, so people don't end up wasting their time parsing your post in a different context. Rude.
Why? Come on, at this point in the thread we'll still discussing C++ derivatives. I thought it was obvious.
Also: if a lanuguage has an if/else as an expression and has a ternary operator, then IMO there's a problem with that language being cluttered with duplicate syntax for the same thing.
My primary language, Object Pascal, even goes to the length of naming functions (return values) and procedures (don't return values) differently. It really helps to focus the mind on the purpose of each: one almost always expects procedures to do something and, most likely, modify something that may introduce side effects. Functions are almost always side-effect-free in "decent" Object Pascal code.
Using ternaries only when it is free of side-effect can both helo avoid a class of unnecessary errors, and add meaningful semantic information that some code is, or should be, side-effect free.
It would be great if the compiler(s) in various languages supported enforcing it, but sometimes you take whatever you get.
Personally i dislike the latter form because it requires me to spend extra time reading what is boilerplate that is functionally identical to a ternary.
Edit: Not impressed by the down-voting of an earnest question of someone trying to learn more about how other people see things, HN.
If-else is the only option if you want to have multiple statements in a {} block, instead of only one function call.
So it seems more consistent to use ternary for expressions and if-else for statement control flow.
I'm sorry, but i really don't follow your logic, can you try to explain it more clearly?
The classic languages with ternary (C, C++, Java, PHP, JavaScript) all have the deficiency of distinction between statements and expressions. When everything in your language is an expression, the need for ternary disappears.
Python has a ternary operator, which does return a value. It just so happens this operator uses the tokens `if` and `else`. But it's the same thing what you'd write in C or Javascript as `C ? T : F`, would be written `T if C else F` in Python. Different order of arguments and tokens, but it's still the ternary operator and not an if/else block.
You can't get a result from block statements in Python. Just because the ternary operator uses the same tokens as the if/else block, doesn't mean it's the same thing.
let x = if true { 5 } else { 6 };Languages with very different syntax like Python are of course going to have different style preferences. Eg. Python doesn't have a ?: operator at all, just an inline if-else expression, so the entire discussion of "should you use ?: for control flow" is meaningless for Python.
boolean_flag
? do_this()
: do_that();
It seems so terse as to be impossible to misinterpret.The only possibly feasible way i see for it doing something unexpected would be if it were the last statement in a function in a language that implicitly returns the value returned by the last statement in a function; but users of such languages usually are aware that can happen.
How do they suggest that?
As far as i am aware ternaries put no restriction whatsoever on what kind of code you can put in its branches.
I don't buy the comparison with getX either, since ternaries have no name, they're just some punctuation, and even if implemented as if/else word pairs are completely vague.
It might be a convention in some circles. I don't think it's a well-established one, though.
For me, ternaries strongly suggest "expressions being run for its return value", but without any indication whether or not it's side effect-free. In practice, most of the time such expressions end up being side effect-free (getters, finders, etc.), but every now and then you do want to have a stateful expression (e.g. getting something from a map, and storing a default value there if the key is missing in the map). I believe such stateful expressions are fine to use with ternaries as well.
You just called someone out for this:
"If you're restricting what you're saying to a specific language say that bold and as the very first thing (...)"
Are you talking about a specific language now? Because some languages do put restrictions on that. Python makes a clear distinction between statements and expressions, so you don't even get the option to use a ternary in place of an if/else block.
That said, (in general) I disagree that ternaries suggest side-effect free. However, they do suggest that you care about the return value of the ternary expression. Some languages enforce this suggestion, others don't. But even for languages that don't, a ternary that silently discards its return value feels like a "cute hack" to me.
So as an example of doing both, consider following Java pseudocode (simples example that comes to my mind now):
Foo value = someCondition()
? map1.computeIfAbsent("key", defaultValueProvider)
: map2.computeIfAbsent("key", defaultValueProvider);
This both gets a value and changes state of the map; which map is queried/altered is determined by the condition. I personally don't mind such code, and prefer it to if/else version. Foo value = ( someCondition() ? map1 : map2 ).computeIfAbsent("key", defaultValueProvider);
Or some kind of moral equivalent?For clarity, let's rewrite it as:
Foo value = someCondition()
? map1.computeIfAbsent("key", defaultValueProvider)
: list1.get(42);