Syntax has nothing to do with the speed of the language: python could be "natural" and "human-like" while being much faster and also "unnatural" and "inhuman" while being slower.
Language abstractions that are not "zero-cost" inevitably lead to worse performance. Python has many such abstractions designed to improve developer experience. I think that's all the person you're responding to meant.
It’s not mainly the syntax though although it has a marginal effect. It’s partially the lack of typing information (which is syntax) but mostly that it runs interpreted. Pypy is significantly faster because it applies JIT to generate machine code directly to represent the Python code and it’s significantly faster in most cases. Another huge cost is in multi-threaded scenarios where Python has the GIL (even in single threaded there’s a cost) which is an architectural and not syntactic decision.
For example, Python has a drastically simpler syntax in some ways than C++ (ignoring the borrow annotations). In many ways it can look like Python code. Yet its performance is the same as c++ because it’s AOT compiled and has an explicit type system to support that.
TLDR: most of python’s slowness is not syntactic but architectural design decisions about how to run the code which is why alternate Python implementations (IronPython, PyPy) typically run faster.
Take a look at the way Python handles integers for an excellent example. Early Python integers had a limited range, similar to other languages. They also had a special type of integer with unlimited range, but it required special syntax to use it. At some point they decided to simplify the syntax and make every integer unlimited, but that slows down operations - something as simple as 1 + 1 is a lot slower than it needs to be.
It does, actually, as the syntax is a result of the language's design and a simpler and more human-like syntax requires a higher level of abstraction that reduces efficiency.
The design of a language, including its syntax, has a great bearing on its speed and efficiency.
Compare C with Assembly, for example, and you will see that higher level languages take complex actions and simplify them into a more terse syntax.
You will also observe that languages such as Python are not nearly as suitable for lower level tasks like writing operating systems where C is much more suitable due to speed.
Languages like Python and Ruby include a higher level of built-in logic to make writing in them more natural and easy at the cost of efficiency.
Syntax is utterly irrelevant. It's the most irrelevant thing you could be focusing on.
JAX and Triton compile your python code to incredibly fast GPU kernels. If you want to run pure python, then there are JIT based runtimes like Jython or PyPy that run your code faster.
What it boils down to is the fact that CPython is an incredibly slow runtime and CPython dominates due to interoperability with C extensions.
I don't know why, but I've seen a lot of people act as if the C language is some kind of voodoo thing as if C being fast is due to mere superstition. "Everyone knows C is the fastest, therefore C is the fastest" What you're doing is the equivalent of reading tea leaves or horoscopes or being an audiophile.
Then let's look at C++, which in some areas has a higher abstraction level than C, but in some areas can still be faster than C. (Due to usage of templates, which then inline the library code, which then can be optimized on actual types, rather than using library functions which use void pointers, which will require a function call and have a not as optimized compiled form.
The main thing about python being slower is that in most contexts it is used as an interpreted/interpiled language running on its own VM in cpython.
What you wrote about C versus C++ is largely untrue. C++ is not faster than C, even when “using library functions which use void pointers”. There is nothing about a void pointer that prevents inlining in either C or C++. There is also no “optimized on actual types” for C++ and not C, since everything is compiled into a low level intermediate language in the compiler (typically three-address code). All of the C++ types are absent at that point. The low level intermediate representation is then what receives optimization.
For example, GCC will outright inline both bsearch() and the provided comparator in cases where it can see the definition of the comparator, such that there are no function calls done to either bsearch() or the comparator. C compilers will do this for a number of standard library functions and even will do it for non-library functions in the same file since they will inline small functions if allowed to do inlining. When the functions are not in the same file, you need LTO to get the inlining, but the same applies to C++.
That said, I have never seen assembly output from a C++ compiler for C++ using C++ specific language features that was more succinct than equivalent C. I am sure it happens, but the C++ language is just full of bloat. C++ templates usually result in more code than less, since the compiler must work much harder to optimize the result and opportunities are often lost. It is also incredibly easy for overhead to be hiding in the abstractions, especially if you have a thread safe class used in a single threaded context as part of a larger multithreaded program. The compiler will not optimize the thread safety overhead away. You might not believe that C++ language features add bloat, so I will leave you with this tidbit:
Tim Sweeney’s team had C++ code that not only did not use exceptions, but explicitly opted out of them with noexcept. They got a 15% performance boost from turning off exceptions in the compiler, for no apparent reason. C, not having exceptions, does not have this phantom overhead.
Noexcept doesn't mean "this function doesn't use exceptions", it means "this function doesn't throw exceptions". The difference being that a child function can throw, but std::terminate will be called once a noexcept function is unwound. There's no standard way to specify the former, only compiler flags.
C++ can be used to write code that generates assembly equivalent to pretty much any C. A lot of standards committee work goes into ensuring that's possible. The trade-off is that it's the closest thing humans have ever produced to a lovecraftian programming language.
If every function is marked noexcept, does it make a difference? Either way, the point of C++ exceptions was to make the fast path even faster by moving error handling out of it. Since they had no idea what was wrong, the code evidently was running in the fast path since it was not terminating by throwing exceptions, yet it ran slower merely because of the C++ exception support.
In any case, my point is that C++ features often carry overhead that simply does not exist in C. Being able to get C++ code to run as fast as C code (possibly by not using any C++ features) does not change that.
Yes, but you can not achieve faster code in C++ than you can also achieve in C and the use of templates or dynamic dispatch certainly can come with a cost. I would also argue than you can write similar abstractions also in C with very similar trade-offs. The difference is mostly that C has less syntactic sugar but everything is more obvious.
I'd love to see any examples you have of compile time metaprogramming libraries like Eigen or CTRE written instead in C. You can do a little of that with _Generic, but I'd generally prefer the nightmare that is templates to most of the hardcore macro magic I've encountered (e.g. Boost.PP), let alone constexpr.
Yes, a C compiler will do something special for some library functions. However for my library, I can use higher level abstractions to implement my algorithms etc. and benefit from the optimisations well.
And yes, one can write somewhat generic C code, which can be in lines as well, but that's not as high level abstracted code (i.e. not type safe, but around void pointers)
The other guy’s remarks were based on the behavior of ancient compilers. I was describing current ones. In any case, my remarks mostly apply to LLVM too. GCC and LLVM are the only compilers that matter these days.
Intel replaced ICC with a LLVM fork and Microsoft’s compiler is used by only a subset of Windows’ developers. There are few other compilers in widespread use for C and C++. I believe ARM has a compiler, but Linaro has made it such that practically nobody uses it. Pathscale threw in the towel several years ago too. There is the Compcert C compiler, but it is used in only niche applications. I could probably name a few others if I tried, but they are progressively more niche as I continue.