4 ms·
huh? Every new language has type safe print functions. Having to specify the type with printf formatters is archaic and awful.
by forrestthewoods 4y ago
huh? Every new language has type safe print functions. Having to specify the type with printf formatters is archaic and awful.
- kccqzy 4y agoMost new languages with type-safe print functions are either dynamically typed (which makes this whole discussion moot) or leverage some significant advance in PL theory in order to make the print function type-safe. By advance, I mean not known before the 1990s.
- forrestthewoods 4y agoSorry, I explicitly meant statically typed languages. Rust, Nim, Zig, Odin, Jai, etc. > For many languages, print is special and the implementation is provided as part of the language implementation. Sure. Printing variables to strings is definitely worth language-level features imho. It's a bad thing if a language (C++) requires users to come up with extremely complex libraries (fmt/std::format) because the language lacks the features to make such a common operation simple and reliable. C style printf is a dumpster fire. C++ iostreams are unuseably slow. Modern languages definitely solve this particular problem much better!
- atq2119 4y agoRust's print! implementation is pretty darn complicated, wouldn't you say?
- xigoi 4y agoHowever, Nim's is very simple: https://github.com/nim-lang/Nim/blob/version-1-6/lib/system/io.nim#L598 https://github.com/nim-lang/Nim/blob/version-1-6/lib/system/...
- elcritch 4y agoThe magic that makes Nim’s print / repr functions really neat is the `fieldPairs` iterator that works on any type. It’s a comptime function to iterate fields of a type, very handy and very simple to use. It can work on any type unlike Rust’s Debug macro which only works on types you own and can annotate. https://nim-lang.org/docs/iterators.html#fieldPairs.i%2CS%2CT https://nim-lang.org/docs/iterators.html#fieldPairs.i%2CS%2C...
- forrestthewoods 4y agoI don't know what Rust's print! implementation looks like. I also don't care. I am not a Programming Language programmer. I am a user of programming languages. Using C-style printf sucks balls. It's extremely error prone and it doesn't support complex types. Using Rust's print system is delightful. I can't make a type error and arbitrarily complex types can be printed with roughly zero effort via {:?} and #[derive(Debug)].
- lmm 4y ago> Sorry, I explicitly meant statically typed languages. Rust, Nim, Zig, Odin, Jai, etc. Requiring a macro is no better than what C does. Most of those languages have a less awful macro system than C's, but that's not an actual language advancement. The state of printing is still awful in the languages you mention.
- dilap 4y agoYou don't like Zig's solution? I think it's excellent. Normal zig code, executed at compile-time. No magic, no macros, fully compile-time error-checked formatting. https://github.com/ziglang/zig/blob/master/lib/std/fmt.zig#L78 https://github.com/ziglang/zig/blob/master/lib/std/fmt.zig#L...
- lmm 4y agoI don't, no. Proper stage polymorphism is great, but running arbitrary code at compile time without a coherent model of how you're doing that (which ad-hoc const/constexpr/etc. isn't) is like substituting for generics by having dynamic types. If I'm just going to run arbitrary code at compile time I might as well do that with a make rule.
- dilap 4y agoSure, it is basically a dynamic language at compile time, but I feel like the downsides of that are significantly mitigated by the fact that it's running at, you know, compile time -- you'll still get compile-time errors for any mistakes! (Some people even try to write entire programs in dynamic languages, as crazy as that is.) Regarding "might as well have a makefile rule," it's not really fair -- in practical terms having a seemless way to evaluate functions in your code at compile time is way different than doing codegen. Like, in practice, how would you write a type-safe format function using codegen? You could do it, but it would be very, very gnarly. Very different. Even Go -- which famously for a while tried to advocate codegen as an alternative to generics (w/ stuff like stringer to codegen print functions for human names for constants) -- resorts to dynamic types & runtime errors for formatting. So let's see: formatting approaches we've seen so far: – dynamic w/ runtime errors (e.g. Go, C#, C, ...) – static via baked into compiler support – static via special-case restricted compile-time evaluated language (e.g. rust macros) - static via full-lang compile-time eval (e.g. zig) I think you said all those are awful, so, I'm curious -- what's the better approach you have in mind?