the-tomster
Joined 13 years ago
Joined 13 years ago
If you're doing something like per-request or per-frame arenas you can clear the arena without having to reallocate the whole mapping. And depending how fancy you want to get you can mark the pages unused when you clear the arena so that the OS can reclaim them if needed.
Two options: you either say "eh 20MB per request ought to be big enough" and resize it later if you need to. Or you take time to figure out reasonable limits in terms of whatever domain you're dealing with, and return descriptive errors when those limits are exceeded. Maybe you're saying your service supports up to N HTTP headers and M query parameters in the URL and so on. For almost anything there's a limit you can place that's reasonable. Having no limits at all just means the limit is when you run out of memory / disk / whatever.
If you like RAII and C++ just use that though, Zig is an alternative not an upgrade, imo.
Indeed if you don't want to manage everything yourself I don't think there's a need to use Zig. The whole pitch is making everything explicit and not hiding control flow. And I do think that limits its usefulness to smaller-scale codebases.
Writing quality software doesn't require much from the programming language until your codebase gets very large and you're collaborating with a ton of people. If I'm expecting a codebase to grow to a large scale I'm not reaching for Zig for that. I don't trust _myself_ to keep that much Zig code tidy and correct let alone a big mob of developers and agents :)
I don't love malloc / free, managing frees one-to-one with allocations is a nightmare. An HTTP server is actually a great example of a good fit for arenas... you can have an arena created per connection, and then free the arena when the connection closes. Now all of your allocations during that connection are guaranteed to be freed instead of having to keep track of them individually. Need something to live across connections? Use the general purpose allocator for those particular things.
For one shot programs, why bother freeing anything at all? The gpa or malloc or whatever else is fine there.
Personally I mostly lean on fixed-size buffers, but if I'm writing Zig it's just little toy programs where blowing up when the buffer runs out of room is fine. But for big non-toy programs it might be good to use fixed-size buffers anyway and define your limits in terms of things actually relevant to your domain.
RAII and smart pointers are fine too, but C++ has you covered if you want those. Zig is specifically avoiding that kind of invisible code that destructors bring you.
I try to look at a clean reinstall as a good chance to make sure my backups and restore process are working too. Maybe take a chance to experiment with a different distribution or organize things differently, or new bootloader.
I've found Haxe to be pretty pleasant in this situation. The only areas I really needed a library were around graphics and input, and Heaps looked more interesting to me than the JS alternatives I looked at.
The language itself feels like a pleasant mush of all the Java-y OO languages, but without the entire kitchen sink included. You've got all the polymorphism and generic typing stuff you'd expect from a java clone, plus algebraic data types, plus the ability to drop to dynamic duck-typing if you have to. And the type inference has worked pretty well for me. Oh, it also has a macro system I've never needed to use.
The tooling situation is good but not great. The compiler's messages have generally been clear. I am using vim + universal ctags for development, and it is fine but not as deluxe as a working LSP. I didn't have any luck getting Haxe's LSP working with vim, but I assume a VS Code based setup is more of a happy path and would have better luck.
Output-wise, the JS it generates seems fine. For my particular use case I care more about the readability and debuggability of the generated JS rather than the size. It has not been a problem to understand where an issue is coming from while looking at the generated JS.
Performance wise, the only issues I've had were caused by my own foolishness in making thousands of draw calls instead of batching things. Other than bugs I haven't seen any performance problems.
When it comes to libraries, you have to contend with both the relatively small size of the community, as well as the difficulty of writing a library that actually supports all of Haxe's compile targets. Haxe errs on the side of pragmatism instead of identical behavior on all of its supported platforms. So often you'll find nasty platform-specific logic in the heart of libraries, and if your target isn't supported then you have to dive in and fix it yourself. It is not a good language for grabbing a few things off of npm or cargo and slapping them together.
MahjongSoul was recently translated to English (https://mahjongsoul.game.yo-star.com/). The heavy anime-girl theming can be a bit unfortunate but it's an excellent implementation of the game and allows you to play matches against bots to learn the game.
Tenhou is the more classic and staid online implementation, and there are browser extensions for Chrome and Firefox to translate it to english. (http://tenhou.net/)
As a side project I implemented a small text editor in this style. I had a working text editor with the ability to load a file, insert and delete text, scroll around a large file, and save changes. It fit within about 100 lines of concise (but I wouldn't say obfuscated) C.
In the end I decided to reformat it and use my usual style before implementing more features. But it was a good experiment and I now understand the appeal of the ultra-condensed style you see in J, K, some Forth, and some Perl code.
Go has specifically rejected the complexity that these features introduce, both in the implementation of the language and the writing of programs in it. If you want those features, just use a language that has them. Some other people might not care about those features, and prefer the simplicity of Go, and that's fine too.
Why have macros and history reimplemented badly by every application when one application could do it well?