Liste des Groupes | Revenir à cl c |
On 01/11/2024 20:47, Bart wrote:Then we disagree on what 'multi-way' select might mean. I think it means branching, even if notionally, on one-of-N possible code paths.On 01/11/2024 18:47, David Brown wrote:Yes, it is.On 01/11/2024 19:05, Bart wrote:>On 01/11/2024 17:35, David Brown wrote:>>>>
What you have written here is all correct, but a more common method would be to avoid having three printf's :
>
void shout_a_number(int n) {
printf( (const char* []) { "ONE", "TWO", "THREE" } [n] );
}
>
That's more likely to match what people would want.
I was also trying to show that all elements are evaluated, so each has to have some side-effect to illustrate that.
Fair enough.
>>>
A true N-way-select construct (C only really has ?:) would evaluate only one, and would deal with an out-of-range condition.
That's a matter of opinion and design choice, rather than being requirements for a "true" select construct.
I don't think it's just opinion.
I don't disagree that such an "select one of these and evaluate only that" construct can be a useful thing, or a perfectly good alternative to to an "evaluate all of these then select one of them" construct. But you are completely wrong to think that one of these two is somehow the "true" or only correct way to have a selection.Those logical operators that may or may not short-circuit.
In some languages, the construct for "A or B" will evaluate both, then "or" them. In other languages, it will evaluate "A" then only evaluate "B" if necessary. In others, expressions "A" and "B" cannot have side-effects, so the evaluation or not makes no difference. All of these are perfectly valid design choices for a language.
I don't count evaluating the conditionals: here it is the branches that count (since it is one of those that is 'selected' via those conditionals), and here you admit that only one is executed.>It evaluates all the conditionals down the chain until it hits a "true" result, then evaluates the body of the "if" that matches, then skips the rest.
In general, an if-else-if chain (which was the point of the OP), would evaluate only one branch.
(Of course generated code can evaluate all sorts of things in different orders, as long as observable behaviour - side-effects - are correct.)It's pretty much the complete opposite of straightforward, as you go on to demonstrate.
So would a switch-case construct if sensibly implemented (in C's version, anything goes).C's switch is perfectly simply and clearly defined. It is not "anything goes". The argument to the switch is evaluated once, then control jumps to the label of the switch case, then evaluation continues from that point. It is totally straight-forward.
>
You might not like the "fall-through" concept or the way C's switch does not quite fit with structured programming. If so, I'd agree entirely.Good.
The requirement for lots of "break;" statements in most C switch uses is a source of countless errors in C coding and IMHO a clear mistake in the language design. But that does not hinder C's switch statements from being very useful, very easy to understand (when used sensibly), and with no doubts about how they work (again, when used sensibly).It wasn't. YOU wrote FUD when you called them straightforward. I would bet you that the majority of C programmers don't know just how weird switch is.
The same applies to C's c?a:b operator: only one of a or b is evaluated, not both.You are conflating several ideas, then you wrote something that you /know/ is pure FUD about C's switch statements.
So writing "The same applies" makes no sense.'The same applies' was in reference to this previous remark of mine:
You are, of course, correct that in "c ? a : b", "c" is evaluated first and then one and only one of "a" and "b".And here you confirm that it does in fact apply: only one branch is executed.
Yes, short-circut operators would need the same features. That's why it's easier to build this stuff into a core language than to try and design a language where 90% of the features are there to implement what should be core features.>Yes, you'd need something like that to implement such "short-circuit" operators using functions in C. In other languages, things may be different.
(This also why implementing if, switch, ?: via functions, which lots are keen to do in the reddit PL forum, requires closures, lazy evaluation or other advanced features.)
>
These things tend to come about because that is the natural order that comes through. It's something I observed rather than decided.But it becomes mandatory if the whole thing returns a value, to satisfy the type system, because otherwise it will try and match with 'void'.Your language, your choice.
>
I'd question the whole idea of having a construct that can evaluate to something of different types in the first place, whether or not it returns a value, but that's your choice.If the result of a multi-way execution doesn't yield a value to be used, then the types don't matter.
SOMETHING needs to happen when none of the branches are executed; what value would be returned then? The behaviour needs to be defined. You don't want to rely on compiler analysis for this stuff.In my hypothetical language described above, it never happens that none of the branches are executed.
Do you feel you need to write code like this?
const char * flag_to_text_A(bool b) {
if (b == true) {
return "It's true!";
} else if (b == false) {
return "It's false!";
} else {
return "Schrödinger's cat has escaped!";
}
}
When you have your "else" or "default" clause that is added for something that can't ever happen, how do you test it?I write code like this:
It seems you are just arguing in the defence of C rather than objectively, and being contradictory in the process.>Given that the tertiary operator chooses between two things, it seems fairly obvious that you need two alternatives to choose from - having a choice operator without at least two choices would be rather useless.
In C on the other hand, the ':' of '?:' is always needed, even when it is not expected to yield a value. Hence you often see this things like this:
>
p == NULL ? puts("error"): 0;
I can't say I have ever seen the tertiary operator used like this. There are a few C programmers that like to code with everything as expressions, using commas instead of semicolons, but they are IMHO mostly just being smart-arses. It's a lot more common to write :Well, it happens, and I've seen it (and I've had to ensure my C compiler deals with it when it comes up, which it has). Maybe some instances of it are hidden behind macros.
if (!p) puts("error");
This is new to me. So this is another possibility for the OP?Meanwhile I allow this (if I was keen on a compact form):In C you could write :
>
(p = nil | print "error")
>
No else is needed.
>
p == NULL || puts("error");
which is exactly the same structure.
I think all of these, including your construct in your language, are smart-arse choices compared to a simple "if" statement, but personal styles and preferences vary.C's if statement is rather limited. As it is only if-else, then if-else-if sequences must be emulated using nested if-else-(if else (if else....
Les messages affichés proviennent d'usenet.