4 ms·
Any C programmer working at large scale will need to rely on third-party libraries. That library code is an abstraction. When I write C++ the language magic i
by nwatson 10y ago
Any C programmer working at large scale will need to rely on third-party libraries. That library code is an abstraction.
When I write C++ the language magic is "just another library". If I'm uncomfortable I just step through those magic layers in a debugger and I'm then happy, just like a C library user would step through compiled-from-source third party stuff.
"But a C coder can read the third-party code!" But a C program already hides the magic of function calls and stack frames ... C++ is just a few more layers of abstractions just like that one!
- wolfgke 10y ago> When I write C++ the language magic is "just another library". The difference is: For a library you can (in principle) write your own implementation and replace the given one by it. Or even remove the library completely if it seems a good idea. For language features this is not possible (without writing a new compiler that implements something different than C/C++). Thus the language features of C++ clearly cannot be compared to a library - they change the language (if left away), while a library is no different language, but a text written in the language.
- lmm 10y ago> But a C program already hides the magic of function calls and stack frames ... C++ is just a few more layers of abstractions just like that one! In principle yes, but there are good and bad abstractions (bitshifts that print probably being in the latter category), and facilities that break important symmetries of their surrounding code (exceptions).
- gpderetta 10y agoExactly, I mean, which language designer would reuse the the very common stream input/output operators for such an uncommon bit manipulation operation! Slightly less tongue-in-cheek, what sort of symmetries are broken by exceptions?
- lmm 10y ago> Slightly less tongue-in-cheek, what sort of symmetries are broken by exceptions? They make it much harder to maintain single entry/exit in functions where you want that - and, crucially, harder to notice when a function isn't single entry/exit. They also violate referential transparency, which means e.g. caching the result of a repeated function call is no longer necessarily safe.
- mrec 10y ago> caching the result of a repeated function call is no longer necessarily safe Not seeing this one. Unpredictable exception-throwing only happens if the work being done by your function isn't pure, i.e. it depends on something other than the function parameters. And if that's the case then caching its result is a bad idea anyway. What am I missing here?
- lmm 10y agoIf you make an exception-aware cache that part will behave correctly. The problem is that you can't just move the call around, store the value and use it later, because you're changing where the evaluation happens, so that can lead to an exception happening earlier or later and changing which functions get evaluated. "Everyone knows" you shouldn't use exceptions as control flow, but it's very easy to not realise you were doing it by accident (I once came across a method that always exceptioned and never did what it looked like it was meant to) until you refactor and break something.
- acomar 10y ago> Unpredictable exception-throwing only happens if the work being done by your function isn't pure, i.e. it depends on something other than the function parameters. This isn't true. The canonical example is trying to grab the first element of an empty list. You either check and catch the error or eat the exceptional behavior, but some pure functions are just partial and aren't defined for all inputs. (Whether or not they throw a catch-able exception depends on language/implementation and is really not relevant to my point.)