bash <enter>
<paste> <enter>
exit <enter>
Tada!19 karma · joined April 1, 2024
bash <enter>
<paste> <enter>
exit <enter>
Tada!It also makes match expressions an expression rather than a statement, so it can replace awkward terenaries. And it has no transitive dependencies!
Counterpoint: 95% of config-readers are or could be checked in with all the config they ever read.
I have yet to come across a programming language where it is easier to read + parse + type/structure validate a json/whatever file than it is to import a thing. Imports are also /much/ less fragile to e.g. the current working directory. And you get autocomplete! As for checks, you can use unit tests. And types, if you've got them.
I try to frame these guys as "data values" rather than configuration though. People tend to have less funny ideas about making their data 'clean'.
The only time where JSON.parse is actually easier is when you can't use a normal import. This boils down to when users write the data and have practical barriers to checking in to your source code. IME such cases are rare, and most are bad UX.
> Side effects in constructors
Putting such things in configuration files will not save you from people DRYing out the config files indirectly with effectful config processing logic. I recently spent the better part of a month ripping out one such chimera because changing the data model was intractable.
The data model is closer to XML than JSON, though, so unfortunately it's not a drop-in replacement for yaml.
Small sample:
package {
name my-pkg
version "1.2.3"
dependencies {
// Nodes can have standalone values as well as // key/value pairs.
lodash "^3.2.1" optional=#true alias=underscore
}
}Go and Zig are both aggressively small and portable languages, and e.g. prefer explicit `defer` where Rust would handle cleanup implicitly. Unlike Zig, Go and Rust are both widely used and mature ~tier-1 languages with a deep bench of native libraries. However, there's a deep gulf between their philosophies. Go values a shallow learning curve and making code easy to write, whereas Rust values expressivness and making it hard to write bad code. This is not to say that you can't write Good Software in Go or make money with Rust code. However, the languages tend to attract distinct groups of programmers, and there's a reason flamewars crop up between their proponents with unusual regularity.
Zig is notable for targeting C's niches of having lots of structural flexibility in memory management, being good at calling C code, and building C programs. C is the native language of most truly powerful interfaces (operating systems, graphics, cryptography, databases, other programming languages, device drivers, low-level networking, etc.), and programs primarily concerned with interfacing with such things tend to be better off written in C. Working with C code is in the happy path for Zig, while other mainstream programming languages demand significant specialized expertise or wrapper libraries (1). Wrapper libraries aren't always available, are almost always less useful than the original, and only save you /some/ build headaches. This makes Zig a candidate in many situations where C - and /maybe/ C++ - are the only real competition.
In short:
If your interest is learning new ways to think about writing programs, Rust will give you a more distinct perspective than Zig. Like Go, there will be lots of libraries and guides to help you out.
If your interest is in learning to write a kind of program you couldn't in Go and think "closer to the metal", Zig is likely better suited to task.
(1): This isn't nearly as true for C++, but there's still enough impeadence mismatch between idiomatic C and C++ to invite interfacing bugs and wrapper libraries.
// zod 3 syntax
import { z } from 'zod'
const RGB = z.schema({
red: z.number(),
green: z.number(),
blue: z.number(),
})
type RGB = z.infer<typeof RGB>
// same thing as:
// type RGB = { red: number; green: number; blue: number };
For the initial migration, there are tools that can automatically convert types into the equivalent schema. A quick search turned up https://transform.tools/typesgcript-to-zodghl, but I've seen others too.For what it's worth, I have come to prefer this deriving types from parsers approach to the other way around.
https://amazon-ion.github.io/ion-docs/
The "object and array need to be entirely and deep parsed" and "object and array cannot be streamed when writing" are somewhat incompatible from a (theoretical) parsing perspective, though; you need to know how far to skip ahead in order to do so.
I agree that it is silly to design an efficiency-oriented format that does neither, though. Ion chooses to be shallow parsed efficiently, although it also makes affordances for streams of top-level values explicitly in the spec.
You just: - Mange/setup nixos - Add container architecture definition to nixos config
The containers, being systemd units, would have all the normal systemd log management like the rest of your system, instead of having to dig through docker-compose logs with a different mechanism than "normal" systemd service logs.
You'd also get all the normal benefits of a nixos system: the config file can be placed on a new system to completely reproduce the system state (modulo databases et all), rollbacks are trivial, etc.
[1]: https://github.com/jesseduffield/lazygit
[2]: https://magit.vc/
It's schemaless, so the binary format can't be as effecient as protobufs, but IMO the minor overhead is worth not paying the costs protobuf has to.
The text format (which is interoperable) is a strict superset of JSON that resolves many of the issues ziggy tackles (tagged unions, comments, verbosity, multiline strings), although not quite as prettily for configs.
It also specs proper decimal values, mitigating the issues presented in the OP.