Post by BartCPost by David BrownPost by BartCThe standard way of swapping terms x and y in Python requires writing
each term twice. That needs extra care. And yes it can be a little less
efficient.
This is /programming/ - it is not ditch-digging. Yes, you need to take
care with what you write and how you write it - the same applies to all
programming, in all programming languages.
I can see I'm never going to convince you of anything! So C, is perfect
as it is; Python is perfect as it is. Nothing needs to be done. If
anyone needs to go a little out of their way, then it's just
'programming'. If something is error-prone, you just need to take more
care, or do more unit-tests.
You do a fine job at taking a small point, extrapolating it wildly, then
leaping to ridiculous conclusions. Sit down and relax - take a deep
breath, count to ten, put on some whale song music, or whatever helps
you calm down.
C has its flaws. If you had actually /read/ anything I have posted, you
would know I think that. But it works fine as it is - most C
programmers do not seem to have problems understanding pointers and
arrays, getting braces right, or any of the other things you find nearly
impossible. Most C programmers understand that writing C takes care and
effort. Most C programmers understand that their work is easier if they
get reasonable tools and learn how to use them properly.
You may also see that I sometimes discuss things I would prefer were
different in C, or that I think would make useful additions to the
language. But I make these either in the context of clear wishful
thinking that I know will never happen, or as ideas that are at least
somewhat realistic because they can be found as extensions in existing
compilers, or are in C++.
Ultimately, I am a practical programmer. I make a living writing
embedded code in C (plus some C++, plus Python PC programming, etc.).
My main interest in C groups is to get the best out of the language and
the tools, and be sure that my code is correct. To a very large extent,
I don't really care if my compiler rejects a piece of bad code because
the syntax of C described in the standards disallows it, or if it merely
triggers a warning in my compiler. In either case, I have avoided a
mistake.
So I find repeated discussions about how "C lets you write this bad
code" as tedious and pointless. C lets you write /good/ code, and C
tools help you write /good/ code and avoid /bad/ code. What more do you
want? Do you want to turn back time and change C forty years ago? Do
you need someone to hold your hand and explain to you /again/ how arrays
work every time you use one? If you can't cope with writing C
/correctly/, then pick a different language or a different career.
(As for Python - it is a very different language from C. It has its
strengths and weaknesses, and is useful for different tasks than C
programming. It is also off-topic here, since we are discussing C - so
while I will refer to Python for contrast or comparison with C, I am not
going into detail about what I like or dislike about it.)
Post by BartC(Although that doesn't explain why there is a new version of Python
every five minutes.)
Post by David BrownWhat's next after "swap" ? Do you want to add an operator that
calculates "4*a + b" just because that fits an x86 addressing mode, and
people could then use it to do efficient multiplication by 5 even on
Tiny C? Personally, I'd rather continue to write "x * 5" and let a good
compiler generate the efficient code on processors that have such
instructions.
You're being silly now.
You are the one who wants to add new features (operators or built-in
functions) to take advantage of processor instructions that exist on
some cpus - just so that limited compilers can generate better code.
And I suspect the number of times I would have use of a "swap" operator
in my programming is not that much more than the number of times I have
to multiply by 5.
Post by BartCDoesn't C already have ++a and a+=b and P->m and
++a a=a+1
a+=b a=a+b
P->m (*P).m
a?b:c if (a) temp=b; else temp=c; ... temp ...
a && b !!a & !!b
a && b if (a) if (b) ...
switch(x) if (x==...)...
There are a number of constructs with both add expressibility and also
tell the compiler exactly what it is that is being done rather than the
compiler having to deduce it.
C is not designed to be an absolute minimal language - merely a
relatively small and stable language.
Post by BartCswap
min and max
n-way select (a?b:c is 2-way select)
n-times loops
a to b loops
non-int/non-const switch (here, where C has an if/else-if chain
comparing the same expr against a number of values; see below)
bit extraction
2-way/n-way select as lvalues
chained compares (Python-style a==b==c etc)
I know that you have a thing about gcc and its wonderful optimiser,
if (x[i+1]=a) {...}
else if (x[i+1]=f(i)) {...}
else if (x[i+1]....
So you write 'x[i+1]' N times and gcc magically generates code that only
evaluates it once (even being clever enough to know that, if i is global
and f() is external, f() won't change i for the third compare).
But hang on ... wouldn't it be better if you only wrote 'x[i+1]' *once*?
And that way the value is frozen so calls like f() can't effect
subsequent comparisons.
I guess you know better...
Yes, I know better:
int x_i = x[i+1];
if (x_i == a) {
...
} else if (x_i == f(i)) {
...
} else if (x_i == ...
Those of us who understand C99, local variables and block scope, and who
use compilers with at least basic optimisation, are not afraid to make
new local variables as needed in order to get the code we want.
Post by BartCPost by David BrownAnd the fact that it is /not/ common on newer processors and in
particular, it is not common on RISC designs, suggests that as an
operation it is not useful enough to be worth the cost of including it
in the processor. (Swap instructions were cheap to implement in single
cpu, single bus master, in-order processors. They are /very/ expensive
to implement in modern multi-core out-of-order processors with
load-store architectures.)
That's true; XCHG on x64 is too slow to be useful. But it doesn't change
the fact that it was /desirable/.
The key desirable feature of having a low-level "exchange" operation is
to make it atomic. C11 gives you atomic_exchange() for that purpose.
Other than that, it is not /that/ hard to manually write out a "swap"
operation when you need it - or write your own macro or function if you
need it a lot. And it is not /that/ hard for a compiler to see such
patterns and generate optimal code for the target.
I don't disagree that it might sometimes be convenient to have a "swap"
operation built into the language. I just think it is not nearly useful
enough to be worth the effort of adding it to the language.
Post by BartCPost by David BrownPost by BartCThat reminds me of a feature I had on an old language which was along
stack a, b
unstack a, b
stack/unstack map to push and pop instructions. There are no type checks
so this could do type-punning (stack a float, unstack to an int).
If you want to program in Forth, that's fine - but it's a very different
language from C.
This wasn't Forth, but an early version of my C-like language. But
what's wrong with it? It ticks all the boxes. It can do 'a,b=b,a' and a
lot more (via a macro such as ASSIGN2(a,b, b,c) if required). It doesn't
need to use the hardware stack.
I didn't say there was anything wrong with it - merely that it is a
different language, and from that rather small snippet and description
it looks more like Forth than C.