Liste des Groupes | Revenir à cl c |
On 03/11/2024 17:00, David Brown wrote:And if it does /not/ involve actions "in-line", or if the semantics of the selection say that all parts are evaluated before the selection, then it would /not/ involve branching. I did not say that multi-way selections cannot involve branching - I said that the phrase "multi-way selection" is too vague to say that branches are necessary.On 02/11/2024 21:44, Bart wrote:I would disagree on that definition, yes. A "multi-way selection" would mean, to me, a selection of one of N possible things - nothing more than that. It is far too general a phrase to say that it must involve branching of some sort ("notional" or otherwise).Not really. If the possible options involving actions written in-line, and you only want one of those executed, then you need to branch around the others!
I understand that this is key to what /you/ mean by "multi-way selection". And if I thought that was what that phrase meant, then I'd agree with you on many of your other points.And it is too general to say if you are selecting one of many things to do, or doing many things and selecting one.Sorry, but this is the key part. You are not evaluating N things and selecting one; you are evaluating ONLY one of N things.
For X, it builds a list by evaluating all the elements, and returns the value of the last. For Y, it evaluates only ONE element (using internal switch, so branching), which again is the last.I am very keen on keeping the concepts distinct in cases where it matters. So they should be given distinct names or terms - or at least, clear descriptive phrases should be used to distinguish them.
You don't seem keen on keeping these concepts distinct?
In C, no. But when we have spread to other languages, including hypothetical languages, there's nothing to stop that. Not only could it be supported by the run-time type system, but it would be possible to have compile-time types that are more flexible and only need to be "solidified" during code generation. That might allow the language to track things like "uninitialised" or "no value" during compilation without having them part of a real type (such as std::optional<> or a C struct with a "valid" field). All sorts of things are possible in a programming language when you don't always think in terms of direct translation from source to assembly.How on earth is that going to satisfy the type system? You're saying it's OK to have this:>>
The whole construct may or may not return a value. If it does, then one of the N paths must be a default path.
>
No, that is simply incorrect. For one thing, you can say that it is perfectly fine for the selection construct to return a value sometimes and not at other times.
int x = if (randomfloat()<0.5) 42;
Or even this, which was discussed recently, and which is apparently valid C:Presumably you meant to add the closing } here ? Yes, that is valid C, but it is undefined behaviour to use the value of F() if a value was not returned.
int F(void) {
if (randomfloat()<0.5) return 42;
In the first example, you could claim that no assignment takes place with a false condition (so x contains garbage). In the second example, what value does F return when the condition is false?It doesn't return a value. That is why it is UB to try to use that non-existent value.
You can't hide behind your vast hyper-optimising compiler; the language needs to say something about it.I am not suggesting any kind of "hyper-optimising" compiler. I am suggesting that it is perfectly possible for a language to be defined in a way that is different from your limited ideas (noting that your style of language is not hugely different from C, at least in this aspect).
My language will not allow it. Most people would say that that's a good thing. You seem to want to take the perverse view that such code should be allowed to return garbage values or have undefined behaviour.Is your idea of "most people" based on a survey of more than one person?
After all, this is C! But please tell me, what would be the downside of not allowing it?Are you asking what are the downsides of always requiring a returned value of a specific type? Do you mean in addition to the things I have already written?
It's fine if it never returns at all for someI think the word "neighbour" is counter-intuitive to spell. Therefore we should throw out the English language, because it is all terrible, and it only still exists because some people insist on using it rather than my own personal language of gobbledegook.cases. It's fine to give selection choices for all possible inputs. It's fine to say that the input must be a value for which there is a choice.With justification. 0010 means 8 in C? Jesus.
>
What I see here is that you don't like C's constructs (that may be for good reasons, it may be from your many misunderstandings about C, or it may be from your knee-jerk dislike of everything C related).
It's hardly knee-jerk either since I first looked at it in 1982, when my own language barely existed. My opinion has not improved.It's been knee-jerk all the time I have known you in this group.
Once a thread here has wandered this far off-topic, it is perhaps not unreasonable to draw comparisons with your one-man language. But it is not as useful as comparisons to real languages that other people might be familiar with, or can at least read a little about.You have some different selection constructs in your own language, which you /do/ like. (It would be very strange for you to have constructs that you don't like in your own personal one-man language.)It's a one-man language but most of its constructs and features are universal. And therefore can be used for comparison.
Have you been following this thread at all? Clearly a "multi-way select" must have an input to choose the selection. But it does /not/ have to be a choice of a path for execution or evaluation.FGS, /how/ different? To select WHICH path or which element requires some input. That's the controlling expression.One feature of my concept of 'multi-way select' is that there is one or more controlling expressions which determine which path is followed.>
>
Okay, that's fine for /your/ language's multi-way select construct. But other people and other languages may do things differently.
Or maybe with your ideal language, you can select an element of an array without bothering to provide an index!No. I am well aware that the flexibility of C's switch, and the fall-through mechanism, make it more effort to parse and handle algorithmically than if it were more structured. That has no bearing on whether or not the meaning is clearly defined, or whether the majority of real-world uses of "switch" are fairly easy to follow.
There are plenty of C programmers - including me - who would have preferred to have "switch" be a more structured construct which could not be intertwined with other constructs in this way. That does not mean "switch" is not clearly defined - nor does it hinder almost every real-world use of "switch" from being reasonably clear and structured. It does, however, /allow/ people to use "switch" in more complex and less clear ways.Try and write a program which takes any arbitrary switch construct (that usually means written by someone else, because obviously all yours will be sensible), and cleanly isolates all the branches including the default branch.
Hint: the lack of 'break' in a non-empty span between two case labels will blur the line. So will a conditional break (example below unless it's been culled).Okay.
You are confusing "this makes it possible to write messy code" with a belief that messy code is inevitable or required. And you are forgetting that it is always possible to write messy or incomprehensible code in any language, with any construct.I can't write that randomfloat example in my language.
I can't leave out a 'break' in a switch statement (it's not meaningful). It is impossible to do the crazy things you can do with switch in C.Okay - although I can't see why you'd have a "break" statement here in the first place.
Yes, with most languages you can write nonsense programs, but that doesn't give the language a licence to forget basic rules and common sense, and just allow any old rubbish even if clearly wrong:It is undefined behaviour in C. Programmers are expected to write sensible code.
int F() {
F(1, 2.3, "four", F,F,F,F(),F(F()));
F(42);
}
This is apparently valid C. It is impossible to write this in my language.
We /do/ know that most people would feed sensible code to compilers.Oh, right. I'm not allowed to use counter-examples to lend weight to my comments. In that case, perhaps you shouldn't be allowed to use your sensible examples either. After all we don't know what someone will feed to a compiler.You can't use such a statement as a solid basis for a multi-way construct that returns a value, since it is, in general, impossible to sensibly enumerate the N branches.>
>
It is simple and obvious to enumerate the branches in almost all real-world cases of switch statements. (And /please/ don't faff around with cherry-picked examples you have found somewhere as if they were representative of anything.)
But, suppose C was upgraded so that switch could return a value. For that, you'd need the value at the end of each branch. OK, here's a simple one:What exactly is your point here? Am I supposed to be impressed that you can add something to C and then write meaningless code with that extension?
y = switch (x) {
case 12:
if (c) case 14: break;
100;
case 13:
200;
break;
}
Any ideas? I will guess that x=12/c=false or c=13 will yield 200. What avout x=12/c=true, or x=14, or x = anything else?
You /can/ isolate things into distinct blocks, with occasional fall-throughs, when you look at code people actually write. No one writes code like your example above, so no one needs to be able to interpret it.So if I understand correctly, you are saying that chains of if/else, an imaginary version of "switch", and the C tertiary operator all evaluate the same things in the same way, while with C's switch you have no idea what happens?Yes. With C's switch, you can't /in-general/ isolate things into distinct blocks. You might have a stab if you stick to a subset of C and follow various guidelines, in an effort to make 'switch' look normal.
See the example above.
I haven't even given any examples.That is true, if you cherry-pick what you choose to ignore in each case until it fits your pre-conceived ideas.You're the one who's cherry-picking examples of C!
Here is my attempt at converting the above switch into my syntax (using a tool derived from my C compiler):I know you have done a fair bit of programming. That does not change what I said. (And I am not claiming that I have programmed in a wider range of fields than you.)
switch x
when 12 then
if c then
fi
100
fallthrough
when 13 then
200
end switch
It doesn't attempt to deal with fallthrough, and misses out that 14-case, and that conditional break. It's not easy; I might have better luck with assembly!
No, what you call "natural" is entirely subjective. You have looked at a microscopic fraction of code written in a tiny proportion of programming languages within a very narrow set of programming fields.I've worked with systems programming and have done A LOT in the 15 years until the mid 90s. That included pretty much everything involved in writing graphical applications given only a text-based disk OS that provided file-handling.
Plus of course devising and implementing everthing needed to run my own systems language. (After mid 90s, Windows took over half the work.)When you use your own language, that inevitably /restricts/ your experience with other programmers and other code. It is not a positive thing in this context.
That's not criticism - few people have looked at anything more.Very few people use their own languages, especially over such a long period, also use them to write commercial applications, or create languages for others to use.
No, I think there is quite a bit wrong with the way C's "switch" statement works.What I /do/ criticise is that your assumption that this almost negligible experience gives you the right to decide what is "natural" or "true", or how programming languages or tools "should" work.So, in your opinion, 'switch' should work how it works in C? That is the most intuitive and natural way implementing it?
I think you'd be surprised. Designing a general-purpose programming language is not a small or easy task, and making a compiler is certainly a big job. But you'd search far and wide to find an experienced programmer who doesn't have opinions or ideas about languages and how they might like to change them.You need to learn that other people have different ideas, needs, opinions or preferences.Most people haven't got a clue about devising PLs.
Those branches don't yield different types in C. In C, branches don't "yield" anything. Any results from calling these functions are, in effect, cast to void.Of course they don't! Here, F, G and H return int, float and void* respectively:>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.
>
Of course they do.
if (c1) F();
else if (c2) G();
else H();
C will not complain that those branches yield different types. But you say it should do? Why?
You're just being contradictory for the sake of it aren't you?!No, but I think you are having great difficulty understanding what I write. Maybe that's my fault as much as yours.
"None" is the Python equivalent of "no value".Python /always/ returns some value. If one isn't provided, it returns None. Which means checking that a function returns an explicit value goes out the window. Delete the 10 and 20 (or the entire body), and it still 'works'.This is just common sense; I don't know why you're questioning it. (I'd quite like to see a language of your design!)>
def foo(n) :
if n == 1 : return 10
if n == 2 : return 20
if n == 3 : return
>
That's Python, quite happily having a multiple choice selection that sometimes does not return a value.
It is undefined behaviour, as you would expect. (In my hypothetical language that had better handling for "no value", falling off the end of the function would return "no value" - in C++, that's std::nullopt, which is what you get with "return {};" here.)Yes, that is a dynamically typed language, not a statically type language.So what happens when n is 4? Does it return garbage (so that's bad).
>
std::optional<int> foo(int n) {
if (n == 1) return 10;
if (n == 2) return 20;
if (n == 3) return {};
}
>
That's C++, a statically typed language, with a multiple choice selection that sometimes does not return a value - the return type supports values of type "int" and non-values.
Does it arrange to return some special value of 'optional' that means no value?No. C++ rules for function returns are similar to C's, but a little stricter - you are not allowed to fall off the end of a non-void function (excluding main(), constructors, destructors and coroutines). If you break the rules, there is no defined behaviour.
In that case, the type still does matter, but the language is providing that default path for you.I'm guessing that "end" here is part of the syntax of your function definitions in your language. That's not executable code, but part of the syntax.
Why not? They still have to write 'end', or do you propose that can be left out if control never reaches the end of the function?!X Y A B are arbitrary expressions. The need for 'else' is determined during type analysis. Whether it will ever execute the default path would be up to extra analysis, that I don't do, and would anyway be done later.>
>
But if it is not possible for neither of X or Y to be true, then how would you test the "else" clause? Surely you are not proposing that programmers be required to write lines of code that will never be executed and cannot be tested?
(In earlier versions of my dynamic language, the compiler would insert an 'else' branch if one was needed, returning 'void'.Perhaps I want to put it there for symmetry.
I decided that requiring an explicit 'else' branch was better and more failsafe.)
This was the first part of your example:You can't design a language like this where valid syntax depends on compiler and what it might or might not discover when analysing the code.>
>
Why not? It is entirely reasonable to say that a compiler for a language has to be able to do certain types of analysis.
const char * flag_to_text_A(bool b) {
if (b == true) {
return "It's true!";
} else if (b == false) {
return "It's false!";
/I/ would question why you'd want to make the second branch conditional in the first place. Write an 'else' there, and the issue doesn't arise.
Because I can't see the point of deliberately writing code that usually takes two paths, when either:I am not expecting anything from compiler writers here. I am asking /you/ why you want to force /programmers/ to write extra code that they know is useless.
(1) you know that one will never be taken, or
(2) you're not sure, but don't make any provision in case it is
Fix that first rather relying on compiler writers to take care of your badly written code.
And also, you keep belittling my abilities and my language, when C allows:If I were the designer of the C language and the maintainer of the C standards, you might have a point. C is not /my/ language.
int F(void) {}
How about getting your house in order first.
Ah, a point that we can agree on 100% :-)Anyone who is convinced that their own personal preferences are more "natural" or inherently superior to all other alternatives, and can't justify their claims other than saying that everything else is "a mess", is just navel-gazing.I wrote more here but the post is already too long.
Let's just that 'messy' is a fair assessment of C's conditional features, since you can write this:No, let's not just say that.
Les messages affichés proviennent d'usenet.