drjeats
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
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.
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);
}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.
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.
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.
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;https://msdn.microsoft.com/en-us/library/dn961160.aspx#Ancho...
$"Name = {name}, hours = {hours:hh}"
var s = $"hello, {name}"
System.IFormattable s = $"Hello, {name}"
System.FormattableString s = $"Hello, {name}"
$"{person.Name, 20} is {person.Age:D3} year {(p.Age == 1 ? "" : "s")} old."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"
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.
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.
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.
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.
Kids are still learning jazz and other music history in schools that have good music programs.
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.
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.