I've been learning zig for my game development project, read more about it here. Those are my initial (mostly positive) impressions of the language, coming from a mostly JS/TS recent experience.
Errors are values - It's quite a popular opinion at this point that exceptions aren't the best. They create a hidden control flow, and in JavaScript they can't even be declared; which makes your applications much more unstable.
Zig uses error enums and nice syntactical sugar for easy and fun error handling. For example :
fn failingFunction() error{MyError}!void { return error.MyError; } pub fn main() !void { try failingFunction(); }
In the code above we declare an error MyError (This can also be done separately) and return it.
The try means "if this returns an error, return it here" as in:
failingFunction() catch |err| return err;
I believe this approach is a great combination and saves us from the endless if (err != nil) in Go land.
Other highlights:
The !void syntax - ! is used to create a union between the return type and the error types. Zig supports not adding any errors prior to the !, which is supposed to create a union of all the errors that you actually return from the function.
In practice, I find this syntax unhelpful. At least with my IDE experience I don't get any intellisense in this case, and it makes the function less clear. Just tell me what you are gonna return!
I only see it being useful on the main() function.
You know how in TS you might have a type like number | undefined? You might use an if or some logic to narrow down the type to what you need, and TS automatically displays the new type correctly.
While it's easy, there are problems with this approach:
In Zig, you do this with "Payload Capturing". You can "capture" aka create a new immutable variable with the resulting type. For example:
const maybe_num: ?usize = 10; // `?` Means it can be `null` if (maybe_num) |num| { // Use num }
It's very clear what's happening! Moreover, the variable is immutable, but if you really need to change it, you can capture a pointer to the value instead.
It's also worth mentioning that this mechanism can be used throughout the language, including: for, switch, catch, etc.
Admittedly I didn't yet grasp the full possibilities of comptime. But in short, you can run regular code during compilation. You may create whole functions that are only used during this time, and can return compilation errors if necessary.
It suits Zig quite well, because it's a very malleable language. Even types are values, meaning you can create, change, and get information about types (Especially in comptime).
A basic example of this from the Zig Guide:
const a = 5; // When a number type isn't specified, it defaults to comptime_int const b: if (a < 10) f32 else i32 = 5; // b: f32 after compilation
I'm using VSCode with the official Zig plugin (which uses zls). The intellisense and errors I see in the editor leave much to be desired.
"detectable illegal behavior" aka illegal things that will result in a compilation error aren't typically displayed in the editor. For example:
const nums = [3]u8{ 2, 1, 3 }; _ = nums[4]; // Index out of bounds error
I'm on the 0.14 (dev) master branch version, if it's supposed to work let me know in the comments!
The above is the detailed content of Zig First Impressions from a JS Dev. For more information, please follow other related articles on the PHP Chinese website!