HN user

drjeats

14 karma
Posts0
Comments20
View on HN
No posts found.

Ghostty is trying to be a speed demon terminal, so I'd expect it to use ReleaseFast.

The current build system docs don't prioritize one build mode over another:

https://ziglang.org/learn/build-system/

Standard optimization options allow the person running zig build to select between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. By default none of the release options are considered the preferable choice by the build script, and the user must make a decision in order to create a release build.

But for more opinionated recommendations, ReleaseSafe is clearly favored:

https://zig.news/kristoff/how-to-release-your-zig-applicatio...

ReleaseSafe should be considered the main mode to be used for releases: it applies optimizations but still maintains certain safety checks (eg overflow and array out of bound) that are absolutely worth the overhead when releasing software that deals with tricky sources of input (eg, the internet).

https://zighelp.org/chapter-3/

Users are recommended to develop their software with runtime safety enabled, despite its small speed disadvantage.

If you could somehow collect real-world data, the overwhelming majority of Zig programs aren't released and have likely only made debug builds :P

Then why do my data structures detect if I go out of bounds?

Because you have iterator debugging and/or assertions turned on and are only using non-primitive data structures (e.g. std::vector, std::array).

Zig does the thing that Rust and Go do where it makes the primary primitive for pointers to chunks of memory (slices) bounds checked. You can opt out with optimization settings, but I think most programs will build in "safe release" mode unless they're very confident in their test coverage.

It's strictly better than C++, because in practice codebases are passing lots of `(data, len)` params around no matter how strongly you emphasize in your style guide to use `std::span`. The path of least resistance in Zig, including the memory allocator interface, bundles in language-level bounds checking.

Zig's Lovely Syntax 12 months ago

Personally, I'd rather prefix with `\\` than have to postfix with `\n`. The `\\` is automatically prepended when I enter a newline in my editor after I start a multiline string, much like editors have done for C-style multiline comments for years.

Snippet from my shader compiler tests (the `\` vs `/` in the paths in params and output is intentional, when compiled it will generate escape errors so I'm prodded to make everything `/`):

    test "shader_root_gen" {
        const expected =
            \\// Generated file!
            \\
            \\pub const @"spriteszzz" = opaque {
            \\    pub const @"quadsprite" = @import("src\spriteszzz/quadsprite.glsl");
            \\};
            \\
            \\pub const @"sprites" = opaque {
            \\    pub const @"universalsprite" = @import("src\sprites/universalsprite.glsl");
            \\};
            \\
            \\pub const @"simpleshader" = @import("src/simpleshader.glsl");
            \\
        ;

        const cmdline =
            \\--prefix src -o testfile.zig src\spriteszzz/quadsprite.glsl src\sprites/universalsprite.glsl src/simpleshader.glsl
        ;

        var args_iter = std.mem.tokenizeScalar(u8, cmdline, ' ');
        const params = try Params.parseFromCmdLineArgs(&args_iter);

        var buffer: [expected.len * 2]u8 = undefined;
        var stream = std.io.fixedBufferStream(buffer[0..]);
        try generateSource(stream.writer().any(), params.input_files.items, params.prefix);
        const actual = stream.getWritten();

        try std.testing.expectEqualSlices(u8, expected, actual);
    }

In the most common cases, Zig does exactly what D does here as well. Constant expressions are folded at compile time like any reasonable systems language. It's akin to writing C++ where you slap constexpr on everything. Zig agrees with D that constexpr is silly :)

The one thing is Zig doesn't have D's notion of function purity, so I suspect there are cases where D could either infer that an expression is const where Zig can't, or at the very least D's compiler could do it faster.

Not to dismiss D's contributions to systems programming languages, of course. Clearly a ton of inspiration of being pulled from y'all's work.

Lambda Fellows 6 years ago

People with secure tech careers in hard-to-break-into-industries get those careers by being able to work for little-to-no-pay due to their privileged upbringing.

This isn't sour grapes, I am one of those people. This program is exactly the sort of thing I would have taken advantage of because I could.

Hooking your students up with companies is a good thing, but companies should expect to compensate people for labor, even for a trial period when it's on the scale of an entire month.

This isn't in Lambda School's direct power to solve, but the real issue here is companies are entirely unwilling to properly mentor new cohorts of engineers. You're expected to graduate from college/trade school a rockstar and start your new job landing PRs in time for the daily deploy. It's bad for the profession.

Lambda Fellows 6 years ago

If your company has the bandwidth to create, manage, and mentor not-real-client-work, surely you have the resources to pay interns.

This page did not automatically flip to dark mode on any of the browsers I use--which all are on dark mode--on my macbook, which is also using dark mode.

Nice article :)

Might be worth touching on error callbacks/logging as an error handling strategy.

Sometimes an error is not recoverable in the sense that the calling code can't really do anything about it, but the library should attempt to make progress anyway instead of halting the entire program.

By allowing users to specify an error callback, this means they can log errors, capture stack traces, assert, or whatever.

This isn't that helpful for smaller libraries with smaller-scoped processes, but if it's something like a renderer or interactive audio lib, those often just need to be given a bunch of frame time to do work with the complex input you've prepped and fed to it, and trying to propagate error codes up out of that simulation step would both contort the inner code and not be as helpful as an error callback.

With an error callback you can assert, set breakpoints, or do whatever. But more importantly, by default you can have it just log so when you inevitably in a bug it doesn't prevent everyone else from getting work done while it keeps asserting until you fix your shit.

This will be a less common need than the other standard error reporting mechanisms, but is important to get right if your library has these complex internal preconditions that you want to make visible to the client when violated.

I like doing that too, but the Zig syntax doesn't prevent that kind of arrangement, just makes it a bit wider.

    return if (value >= radix) error.InvalidChar else
           if (comeCondition)  error.OtherError  else
           ...
                               value;
or maybe this, but it seems uglier to me:
    return if      (value >= radix) error.InvalidChar
           else if (comeCondition)  error.OtherError
           ...
           else                     value;
Specifying JSON 10 years ago

Isn't edn a data/object format, rather than a markup format? It's like a better JSON.

:)

I have a little local deploy script that runs this if it fails a smoke test:

say -v Bad "Deployment failed, server gave a bad response"

Is the Blender Game Engine workflow mostly like shown in this video?

https://www.youtube.com/watch?v=K5HEyoDb-tw&index=64&list=PL...

I don't understand the appeal of learning programming without the beginning programmer being in charge of control flow.

Attaching scripts to things is useful for people with skills in using 3D tools, but now you have to introduce them to the concept of writing functions to be executed repeatedly in a loop without them being able to see the loop.

Student: How does it know to keep running my script?

Teacher: It runs every frame in a loop.

S: What's a loop?

T: teaches loops

S: Where's the loop that runs my script?

T: Deep inside the bowels of Blender.

S: Oh.

Yes, the platform support and hot reloading are real nice. That's why so many teams have invested in Unity.

The collision engine is what I was referring to when I said it's not that huge of a thing to do your own Box2D integration, so I disagree that there's a huge value add there. Just drop in the same solution they dropped in.

And the sound tools, until very recently, were incredibly rudimentary. You'd have been just as well off tossing in OpenALSoft or rolling your own FMOD integration (at least then you could use the FMOD Studio tool). I'm grateful for the new Audio Mixer window.

Unity doesn't provide any sequencing for you (maybe you were thinking of Unreal's Matinee?). Also, most people who need input mapping don't use the builtin input mapper. Editor scripts are also painful to write.

You're not really wrong. The platform support and asset importing and hot reloading, for example, are great. However, some of the things like resource management and PhysX or Box2D integration aren't that big of a deal. I want to be realistic about the actual value that Unity adds.

Can it do uninstalls well yet?

I tried to make a package for a simple binary last year (I believe it was premake4 or something). It was annoying to use, and other software I installed with it didn't have an uninstall option.

Package managers make me happy (love Homebrew on OSX), but I don't see a point if I can't also uninstall. I rarely install things from sources that need vetting.

It's similar, but not quite the same. The built-in components work like this (although I'm not deeply knowledgeable of Unity internals or anything, just have been working with it for a few years).

But any game-specific logic written by a developer, while technically using the same component system, is usually written from an individual scene object's perspective rather than from a "system processing components associated with various game objects in bulk" perspective.

You can still write code that looks like a system, but the framework really encourages you to attach those scripts to scene objects, so you end up basing a lot of logic around the structure of the game object hierarchy.

(The alternative to putting a script on a game object is to have one Master script of a scene that delegates updates to several subsystems, but you lose the benefit of things such as disabling a gameobject while the scene is running to temporarily disable a system.)

For instance, you'll see a lot of addons (example Fabric: http://www.tazman-audio.co.uk/?page_id=73#! ) that use prefabs to create hierarchical data even when it's not necessarily appropriate. But it's the path of least resistance.

When you go to implement gameplay logic, you're usually not writing systems as rasmusrn describes, you're writing behavior scripts on the roots of game objects hierarchies (not unlike Actors as you'd see in Unreal and other game engines).

Trying to make a bunch of click-together MonoBehaviours usually makes a mess.

These slides give a good overview of generally good ways to not shoot yourself in the foot in Unity, and it mentions this actor-ish approach: http://slides.com/cratesmith/how-to-use-unity#/

The hope (or at least my hope after working with Unity for a while) with the design rasmusrn is using is that composing per-entity data is more flexible than composing per-entity behavior.

Mastering Emacs 11 years ago

In magit-status-mode I'm able to stage files based on the region.

I can also expand them and highlight multiple chunks to stage just those chunks.

The are only two major things I don't know how to do with the current stable version of Magit (1.4). One is starting an interactive rebase. It can take you through the commits and let you edit the buffer, but I haven't figured out if it's possible to start an interactive rebase without using the "!" command line.

The other thing is checking out files in order to revert them, I'm sure there's a way but using "!" and pasting the file names in still seems fastest.

I've also been wondering if it's possible to write a command to manage the `--skip-worktree` status of files, showing which are currently skipped in magit-status-mode. That would be a useful thing for me to have.