Hello,
This is my first post to this Rust community and I am happy to introduce myself and discuss what I love about this language, but first a little about myself.
I’m Alice, Fluffy to most, and she/her are my pronouns. I’m from the UK. I got a little boy who love like crazy. I’m Autistic, suffer from cPTSD and I also 🩷 Rust!!
Rust I feel appeals to Autistic people because of it’s focus on accuracy and correctness. It’s a common feeling people have about the language. But as the type of person I am I love it.
I began learning it in 2023, before this I was using C++. Rust showed me the importance of error’s as values and helped improve the quality of my code.
Currently I’m writing a game-engine as a hobby. The game-engine is a work in progress (WIP) and I have only just begun it’s development. Since the game-engine will natively support various platforms. To ensure consistency I’m writing all the platform specific code manually and building my own custom standard library for my engine, loosely based on the actual Rust standard library.
Right now I have the code in place to create/remove directories and to create, delete, write, read and set file pointer location. Convert UTF8 to UTF16 and output to the console in Unicode (Windows C API uses UTF16) and heap functions to get the process heap and create and delete memory dynamically.
Next will be the ‘config.json’ for which Serde will be used. Then the logger, and so on.
So it is a WIP but it’s fun and given my conditions allows me to do what I love, writing Rust code.
Thanks for reading!!
Alice 🏳️⚧️
Have you considered TOML instead? For files that need to be edited and read by humans it tends to be better than JSON due to the easier ability to split it over lines and add comments in between.
I’ll never understand how the rust community loves TOML (like me) but also loves Rust syntax (totally not like me)
I feel like they are opposite: rust syntax is full of symbols, toml is super minimal and square parentheses are just less “noisy” than curly ones…
Personally, I just think the amount (and use of) symbols needs to match the semantic complexity.
With spoken language, a few dots and commas generally suffice.
With programming languages, I do want to see scopes and whatnot, so I like having braces in place, for example. Something like Python largely turns to word soup in my brain.
With a configuration language, the complexity is almost even simpler than a spoken language, so I really don’t need much in terms of symbols.
JSON has a mismatch for use in configuration. The keys in a object don’t need to be quoted. The commas after each¹ line in an object really aren’t necessary when pretty-printed. And well, JSON not having comments also kind of disqualifies it.
Having said that, not every symbol has to be my brain’s favorite thing. I don’t particularly care for having each line terminated with a semi-colon. But I do believe that Rust is able to generated such excellent error messages, because the semicolons make it very clear where the statement ends, so I don’t mind putting it down.
¹) Don’t add a comma after the last line, though, or you’ll go to JSON jail.
just to be clear, i talked about ‘‘symbols’’ and not syntax because i understand that the expressiveness is a feature not an opinion in rust
but having {} as code blocks instead of keywords is a choice, right?
also the old thing that on non us keyboard { is harder than [ or ( and that it was an old choice dictated by the keyboards used when making unix or c i guess
i don’t mind syntax per se :)
Really? I feel the opposite. I’d much rather have indentation enforced by the language than merely convention.
That said, I prefer braces, mostly because it makes things like inline functions more reasonable (the lambda syntax sucks IMO), and my editor does a great job matching on braces.
The stupidest thing IMO is that JSON came from JavaScript, but it loses the flexibility of JavaScript. The quotes thing is acceptable IMO since it allows for flexibility in keys (e.g. you can have a URL as a key), but these aren’t:
I love that semicolons mean something in Rust. Since pretty much everything is an expression, you only need a semicolon to turn it into a statement. That’s really nice!
I don’t think it has anything to do with error messages though, plenty of languages do that well without it.
Well, I don’t have a problem with incorrect indentation. As in, the people I work with indent their code correctly, so I don’t need enforcement. If you do need enforcement, you can also throw an autoformatter onto a braced language and it’ll be able figure it out.
But yeah, to me it’s rather that the additional visual cue of indentation + braces helps me a lot. I check the scope of things quite often. If I need to guestimate whether one line has a different indentation than another, that just takes longer and I’ll misread it more often.
But well, in that vein, I also like braces, because I like to use explicit scopes. If I construct a more complex variable which needs intermediate variables, then I’ll isolate the construction process into a separate scope, so that folks reading the code know for certain that these variables will not be used further down. It’s kind of like the isolation of a function, except you don’t explicitly pass things in.
For serializing data, absolutely. But no one in their right mind would use a URL for the name of a configuration field. 🙃
And I can kind of understand them disallowing comments, ever since I saw an XML file which had data encoded into comments. Not any XML file, but one of the most important XML formats in a larger company. Which, I guess, is why they were scared of adding more nodes, in case any applications wouldn’t be able to handle that.
But yeah, that is again assuming JSON to be used for serializing data, not for configuration. The two use-case are just kind of at odds.
Well, I don’t think it’s impossible to solve it without semicolons, but I do think that it makes it harder. And if it’s harder, it will be solved later, which can result in a culture of people not caring for readable errors. And that is then really hard to undo.
My point was hypothetical. The goal is consistent formatting. Python enforces that at a language level, which eliminates a lot of issues from C style languages, like Apple’s infamous
goto fail
, which was a block scope issue:if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0) goto fail; goto fail;
In Python, such ambiguity is impossible.
As do I, largely because I can do things like
if (condition) { fn(); } else { fn2(); }
in one line without using a ternary. I especially like Rust’s blocks as expressions (let x = if condition { y } else { z };
), but for other reasons. I hate ternaries, so maybe that’s why.But I find Python highly readable, which is why I was surprised.
That’s a separate issue though. In Python, you don’t have block scope, but that’s not a syntax limitation, but a language choice.
Which is why you use a data format for data and a config format for configs. JSON is fine for data, and not fine for configs.
JSON doesn’t have comments because it’s a data format. But since it’s also used for configs (which it shouldn’t), it should support comments and trailing commas at minimum.
Just use a config format for config, like TOML.
@ex_06 @taladar Personnally it’s not that I like the syntax, it’s that I love the semantic.
Are you talking about rust or toml? Because if rust, just out of curiosity, would you still like it with keywords instead of symbols?
Rust has very few symbols, especially compared to pre-1.0 when they had ~ (box?) and @ (GC?).
Symbols in modern Rust are pretty reasonable IMO, but maybe that’s just stockholm syndrome.
@sugar_in_your_tea @ex_06
-
&&
and||
instead ofand
andor
-
::
instead of the simpler.
Just those two changes would help significatly reduce the awkwarness. Even turbofish would be slightly less noizy.
Idk,
&&
and||
are pretty universally common, so I highly doubt they trip anyone up.::
is a little odd, but at least it’s limited to imports. Having it be.
makes it a little ambiguous when you seex.y
as to whetherx
is a module or an instance. But it’s absolutely fine in other languages, so that’s not a hill I’m willing to die on.The turbofish is disgusting though. I prefer D’s template syntax:
Type!A
orType!(A, B)
, though this conflicts with macros. If we have macros all use the same symbol (e.g.println#(...)
instead ofprintln!(...)
), then we could use the!
instead of the turbofish. But that ship has sailed and it’s not clear if my bike shed is a better color.TOML is a terrible format. It is anything but obvious, especially when you have more than one level of nesting.
It is pretty annoying that there isn’t an obvious format that Serde supports to use though:
I would probably go with either RON or one of the forks of serde_json that adds support for comments. I think there’s serde_jsonc and serde_jsonc2 maybe.
JSON doesn’t have comments according to the spec. So he is right. Same with trailing commas.
Right but JSONC does support them. We just want support for JSONC as well as JSON.
The thing is, for many use-cases, you care about the configuration language being widely understood/supported. And TOML hit kind of a local maximum, where it’s capable enough for most configuration needs, while being basically INI++. Presumably, you could even fork an INI parser for building a TOML parser, which makes it easy to adopt in many ecosystems.
If you’re doing a lot of nesting in your config, you should rethink your config. Config should be pretty flat.
If you’re putting data in TOML, you’re doing it wrong. If your config needs to include data, IMO it should just reference the data in a separate file that uses a proper data format (e.g. JSON).
TOML rocks precisely because it nudges you into making simpler configs. Nesting is inherently hard to read (see endless debates over indentation standards), and TOML sidesteps the whole problem elegantly, forcing you to think about whether you actually need it. In most cases you don’t, and when you do, it’s possible and not unreasonable.
Why? I don’t see any reason for that.
This is just “you’re holding it wrong”.
Really. Here’s the first Gitlab CI example I could find:
lintDebug: interruptible: true stage: build script: - ./gradlew -Pci --console=plain :app:lintDebug -PbuildDir=lint artifacts: paths: - app/lint/reports/lint-results-debug.html expose_as: "lint-report" when: always
Let’s see the TOML:
[lintDebug] interruptible = true stage = "build" script = [ "./gradlew -Pci --console=plain :app:lintDebug -PbuildDir=lint" ] [lintDebug.artifacts] paths = [ "app/lint/reports/lint-results-debug.html" ] expose_as = "lint-report" when = "always"
Gross. The tool I used to convert even added extra indentation because otherwise it is unclear.
IMO JSON5 is the best:
{ lintDebug: { interruptible: true, stage: 'build', script: [ './gradlew -Pci --console=plain :app:lintDebug -PbuildDir=lint', ], artifacts: { paths: [ 'app/lint/reports/lint-results-debug.html', ], expose_as: 'lint-report', when: 'always', }, }, }
This is much clearer than TOML and less ambiguous than YAML. It could do without the outer
{}
, but overall it’s still better.The only gross thing I see is your indentation. I find the TOML to be more readable honestly.
In a config format, you want to group top level fields together, and it enforces that. Your example could be like this instead:
lintDebug: stage: build script: - ./gradlew -Pci --console=plain :app:lintDebug -PbuildDir=lint artifacts: paths: - app/lint/reports/lint-results-debug.html expose_as: "lint-report" when: always interruptible: true
It’s easy to tack stuff on like that, and it’s also easy to miss when quickly scanning, especially if you’re using 2-space indenting.
The TOML would be the same in either case, because it forces related fields to be grouped separately from child groups.
The main thing I don’t like about TOML is yellow table groups:
[[thing]] [[thing]]
I rarely see it in the wild though.
It’s trying to do two things at once, and ends up doing neither very well. The extra curly braces are there because it’s trying to be a data format, and it’s bad as a data format because it’s not universal. We’ve standardized on JSON as a community for data, and that’s unlikely to change, so we shouldn’t try to “fix” it just for configs. IMO, either use JSON or a config-specific format.
I agree that YAML is plain awful. It shouldn’t exist.
XML is awful for anything outside of markup, and even then I think we can do better. I’m partial to Lua tables:
{x=10, y=45, "one", "two", "three"}
A typical HTML drop down menu {pulled from MDN):
<select name="pets" id="pet-select"> <option value="">--Please choose an option--</option> <option value="hamster">Hamster</option> <option value="parrot">Parrot</option> </select>
Could be like this in a Lua table:
{ node="select", name="pets", id="pet-select", {value="", "--Please choose an option--"}, {value="hamster", "Hamster"}, {value="parrot", "Pattot"}, }
Or maybe something a little different with the node type outside:
select{ name="pets", id="pet-select", option{value="", "--Please choose an option--"}, option{value="hamster", "Hamster"}, option{value="parrot", "Parrot"}, }
I think QT Quick uses something like that, but it’s been years since I played with it.
JSON5 is seriously what I feel JSON should’ve been. Comments, trailing commas, hex numbers, etc.