3 ms·
I so much agree with this. When I started using Zig, memories from writing Pascal started coming back, and I realized I was fine writing Pascal with manual memo
by ngrilly 1y ago
I so much agree with this. When I started using Zig, memories from writing Pascal started coming back, and I realized I was fine writing Pascal with manual memory management, unlike C and C++ where segfaults were a more frequent problem.
- pjmlp 1y agoI was lucky to have gone through a few BASICs (including compiled ones), Z80 and 68000 Assembly, and Turbo Pascal (3.0 - 6.0), before getting to learn C with Turbo C 2.0, although I had already a few books on C, which made be aware that C wasn't the be all end all, that a few decades later many that learned C after C89 kind of propagated as urban myth. Not only I was aware that there were other ways to do systems programming, I was educated that there were safer ways to achieve the same goals. My trasition to C++ came thanks to Borland having the TP/C++ symbiosis, which later became Delphi/C++.
- ngrilly 1y agoIf I remember well, the biggest difference between Pascal and C was that Pascal, unlike C, offered spatial memory safety (thanks to strings and arrays being represented as "fat" pointers including the length), but none of them offered temporal memory safety (heap-use-after-free and stack-use-after-return)?
- pjmlp 1y agoMuch more than that, first lets take into account no one really used plain ISO Pascal on PC, it was always dialects from UCSD Pascal, or eventually Object Pascal, created by Apple and adopted by Borland, TMT and others. Strings were indeed fat pointers, and for the usual critic of being limited to 255 characters, you could eventually use fat pointers to unbounded arrays, with functions to get the lower and upper bounds. Since Pascal supports pass by reference (var parameters), there was no need to mess up with pointers for in/out, or out parameters, thus one less scenario where pointers could go wrong. Memory allocation has special functions New() and Dispose() that are type aware, thus no need to do sizeof() that might go wrong. And there was Mark()/Release() for arena style programming as well. Numeric ranges, with bounds checking, was another one. Enumerations without implicit conversations. Bounds checking, checked arithemetic (this one depended on the build mode), IO checking, and a few other checked modes, naturally they could be disabled if needed. Mapped arrays, so you could get the memory address directly, while having bounds checking. Unbounded arrays provided a way to do slices, even if a bit verbose. Pointers were typed, no decays from arrays, although you could do exactly the same clever tricks as C, by callign specific functions like Adr, Succ, Pred,... Record variants required a specific tag, so while they weren't tracked, it was easier to spot if "unions" were being used properly. Units provided a much better encapsulation as header files + implementation, with selected type visibility. Yes, use after free, doing the wrong thing in mapped memory, or inline Assembly were the main ways how something could go wrong, but much less than with plain C. Which is why I tend to do my remarks with Zig, you will notice quite a few similarities with 1980's safety from the likes of Pascal and Modula-2, the later even better than those Pascal dialects, although Turbo Pascal eventually grew most of the Modula-2 features, plus plenty of C++ inspired ones as well. Hence why with the prices Ada compilers were being sold, and the "cheaper" Pascal dialects and Modula-2, it was yet another reason why it did not took off back then. Ironically GNU Pascal is no longer relevant, while GCC now supports Ada and Modula-2 as official frontends.
- ngrilly 1y agoFantastic summary. I forgot Pascal var parameters, which have probably inspired ref parameters in C# and inout in Swift. Makes me wonder if a language like Zig would benefit from something similar, reducing the need for pointers even more. I also have some vague memory that Turbo Pascal, unlike my Watcom C++ compiler, had a default segfault handler printing stack traces, which was a nice quality-of-life improvement. Interesting that you mentioned header files, as that was indeed the thing that I missed the less when I moved from C++ to Java.