diff options
Diffstat (limited to 'zig.html.markdown')
| -rw-r--r-- | zig.html.markdown | 125 | 
1 files changed, 63 insertions, 62 deletions
| diff --git a/zig.html.markdown b/zig.html.markdown index 0efe5f64..65fd1e6b 100644 --- a/zig.html.markdown +++ b/zig.html.markdown @@ -5,24 +5,19 @@ contributors:      - ["Philippe Pittoli", "https://karchnu.fr/"]  --- -  [Zig][ziglang] aims to be a replacement for the C programming language.  **WARNING**: this document expects you to understand a few basic concepts in computer science, such as pointers, stack and heap memory, etc.  **WARNING**: Zig isn't considered as ready for production. Bugs are expected. -DO NOT TRY ZIG AS YOUR FIRST PROGRAMMING EXPERIENCE. -The compiler, even the language and its libraries aren't ready, yet. -You've been warned.  Prior knowledge of C is recommended. -  ## Quick overview: Zig compared to C  - Syntax is mostly the same, with some improvements (less ambiguity).  - Zig introduces namespaces. -- Try and catch mechanism, which is both convenient, efficient and optional. +- `try` and `catch` mechanism, which is both convenient, efficient and optional.  - Most of the C undefined behaviors (UBs) are fixed.  - Compared to C, raw pointers are safer to use and less likely to be needed.    * The type system distinguishes between a pointer to a single value, or multiple values, etc. @@ -38,7 +33,6 @@ Prior knowledge of C is recommended.  ## Zig language -  ```zig  //! Top-level documentation. @@ -47,8 +41,8 @@ Prior knowledge of C is recommended.  // Simple comment.  ``` -  ### Hello world. +  ```zig  // Import standard library, reachable through the "std" constant.  const std = @import("std"); @@ -67,9 +61,10 @@ pub fn main() void {  ```  ### Booleans, integers and float. +  ```zig  // Booleans. -// Keywords are prefered to operators for boolean operations. +// Keywords are preferred to operators for boolean operations.  print("{}\n{}\n{}\n", .{      true and false,      true or false, @@ -109,6 +104,7 @@ i <<| 8   == 255   // u8: won't go higher than 255  ```  ### Arrays. +  ```zig  // An array is a well-defined structure with a length attribute (len). @@ -138,7 +134,7 @@ var some_integers: [10]i32 = undefined;  some_integers[0] = 30; // first element of the array is now 30 -var x = some_integers[0]; // "x" now equals to 30, its type is infered. +var x = some_integers[0]; // "x" now equals to 30, its type is inferred.  var y = some_integers[1]; // Second element of the array isn't defined.                            // "y" got a stack garbage value (no runtime error). @@ -156,8 +152,8 @@ try some_integers[i]; // Runtime error 'index out of bounds'.  ```  ### Multidimensional arrays. -```zig +```zig  const mat4x4 = [4][4]f32{      [_]f32{ 1.0, 0.0, 0.0, 0.0 },      [_]f32{ 0.0, 1.0, 0.0, 1.0 }, @@ -177,8 +173,8 @@ for (mat4x4) |row, row_index| {  ```  ### Strings. -```zig +```zig  // Simple string constant.  const greetings = "hello";  // ... which is equivalent to: @@ -195,8 +191,8 @@ print("string: {s}\n", .{greetings});  ```  ### Slices. -```zig +```zig  // A slice is a pointer and a size, an array without compile-time known size.  // Slices have runtime out-of-band verifications. @@ -206,8 +202,8 @@ const slice = array[0..array.len];  // "slice" represents the whole array.  ```  ### Pointers. -```zig +```zig  // Pointer on a value can be created with "&".  const x: i32 = 1;  const pointer: *i32 = &x;  // "pointer" is a pointer on the i32 var "x". @@ -223,6 +219,7 @@ const foo = pointer.?; // Get the pointed value, otherwise crash.  ```  ### Optional values (?<type>). +  ```zig  // An optional is a value than can be of any type or null. @@ -239,6 +236,7 @@ if (x) |value| {  ```  ### Errors. +  ```zig  // Zig provides an unified way to express errors. @@ -384,8 +382,8 @@ const result = for (items) |value| {  ```  ### Labels. -```zig +```zig  // Labels are a way to name an instruction, a location in the code.  // Labels can be used to "continue" or "break" in a nested loop.  outer: for ([_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 }) |_| { @@ -434,8 +432,8 @@ const result = for (items) |value| { // First: loop.  ```  ### Switch. -```zig +```zig  // As a switch in C, but slightly more advanced.  // Syntax:  //   switch (value) { @@ -454,15 +452,15 @@ var x = switch(value) {  // A slightly more advanced switch, accepting a range of values:  const foo: i32 = 0;  const bar = switch (foo) { -  0                        => "zero", -  1...std.math.maxInt(i32) => "positive", -  else                     => "negative", +    0                        => "zero", +    1...std.math.maxInt(i32) => "positive", +    else                     => "negative",  };  ```  ### Structures. -```zig +```zig  // Structure containing a single value.  const Full = struct {      number: u16, @@ -564,6 +562,7 @@ print("p.y: {}\n", .{p.y}); // 30  ```  ### Tuples. +  ```zig  // A tuple is a list of elements, possibly of different types. @@ -572,33 +571,33 @@ const foo = .{ "hello", true, 42 };  ```  ### Enumerations. -```zig +```zig  const Type = enum { ok, not_ok };  const CardinalDirections = enum { North, South, East, West };  const direction: CardinalDirections = .North;  const x = switch (direction) { -  // shorthand for CardinalDirections.North -  .North => true, -  else => false +    // shorthand for CardinalDirections.North +    .North => true, +    else => false  };  // Switch statements need exhaustiveness.  // WARNING: won't compile. East and West are missing.  const x = switch (direction) { -  .North => true, -  .South => true, +    .North => true, +    .South => true,  };  // Switch statements need exhaustiveness.  // Won't compile: East and West are missing.  const x = switch (direction) { -  .North => true, -  .South => true, -  .East,          // Its value is the same as the following pattern: false. -  .West => false, +    .North => true, +    .South => true, +    .East,          // Its value is the same as the following pattern: false. +    .West => false,  }; @@ -606,12 +605,12 @@ const x = switch (direction) {  ```  ### Unions. -```zig +```zig  const Bar = union { -  boolean: bool, -  int: i16, -  float: f32, +    boolean: bool, +    int: i16, +    float: f32,  };  // Both syntaxes are equivalent. @@ -622,8 +621,8 @@ const foo: Bar = .{ .int = 42 };  ```  ### Tagged unions. -```zig +```zig  // Unions can be declared with an enum tag type, allowing them to be used in  // switch expressions. @@ -653,8 +652,8 @@ switch (nay) {  ```  ### Defer and errdefer. -```zig +```zig  // Make sure that an action (single instruction or block of code) is executed  // before the end of the scope (function, block of code).  // Even on error, that action will be executed. @@ -695,23 +694,24 @@ Thus, the standard library lets developers handle memory as they need, through s  **NOTE**: the choice of the allocator isn't in the scope of this document.  A whole book could be written about it.  However, here are some examples, to get an idea of what you can expect: -- page_allocator. +- `page_allocator`.    Allocate a whole page of memory each time we ask for some memory.    Very simple, very dumb, very wasteful. -- GeneralPurposeAllocator. +- `GeneralPurposeAllocator`.    Get some memory first and manage some buckets of memory in order to    reduce the number of allocations.    A bit complex. Can be combined with other allocators.    Can detect leaks and provide useful information to find them. -- FixedBufferAllocator. +- `FixedBufferAllocator`.    Use a fixed buffer to get its memory, don't ask memory to the kernel.    Very simple, limited and wasteful (can't deallocate), but very fast. -- ArenaAllocator. -  Allow to free all allocted memory at once. -  To use in combinaison with another allocator. +- `ArenaAllocator`. +  Allow to free all allocated memory at once. +  To use in combinations with another allocator.    Very simple way of avoiding leaks.  A first example. +  ```zig  // "!void" means the function doesn't return any value except for errors.  // In this case we try to allocate memory, and this may fail. @@ -735,8 +735,8 @@ fn foo() !void {  ```  ### Memory allocation combined with error management and defer. -```zig +```zig  fn some_memory_allocation_example() !void {      // Memory allocation may fail, so we "try" to allocate the memory and      // in case there is an error, the current function returns it. @@ -759,8 +759,8 @@ fn some_memory_allocation_example() !void {  ```  ### Memory allocators: a taste of the standard library. -```zig +```zig  // Allocators: 4 main functions to know  //   single_value = create (type)  //   destroy (single_value) @@ -825,7 +825,7 @@ fn arena_allocator_fn() !void {  // Combining the general purpose and arena allocators. Both are very useful, -// and their combinaison should be in everyone's favorite cookbook. +// and their combinations should be in everyone's favorite cookbook.  fn gpa_arena_allocator_fn() !void {      const config = .{.safety = true};      var gpa = std.heap.GeneralPurposeAllocator(config){}; @@ -846,8 +846,8 @@ fn gpa_arena_allocator_fn() !void {  ```  ### Comptime. -```zig +```zig  // Comptime is a way to avoid the pre-processor.  // The idea is simple: run code at compilation. @@ -883,6 +883,7 @@ list.items[0] = 10;  ```  ### Conditional compilation. +  ```zig  const available_os = enum { OpenBSD, Linux };  const myos = available_os.OpenBSD; @@ -905,6 +906,7 @@ const myprint = switch(myos) {  ```  ### Testing our functions. +  ```zig  const std = @import("std");  const expect = std.testing.expect; @@ -925,7 +927,7 @@ test "returns true" {  The compiler has special functions called "built-ins", starting with an "@".  There are more than a hundred built-ins, allowing very low-level stuff:  - compile-time errors, logging, verifications -- type coercion and convertion, even in an unsafe way +- type coercion and conversion, even in an unsafe way  - alignment management  - memory tricks (such as getting the byte offset of a field in a struct)  - calling functions at compile-time @@ -936,6 +938,7 @@ There are more than a hundred built-ins, allowing very low-level stuff:  - etc.  Example: enums aren't integers, they have to be converted with a built-in. +  ```zig  const Value = enum { zero, stuff, blah };  if (@enumToInt(Value.zero)  == 0) { ... } @@ -943,38 +946,36 @@ if (@enumToInt(Value.stuff) == 1) { ... }  if (@enumToInt(Value.blah)  == 2) { ... }  ``` -  ### A few "not yourself in the foot" measures in the Zig language. -- Namespaces: names conflicts are easily avoided. -  In practice, that means an unified API between different structures (data types). +- Namespaces: name conflicts are easily avoided. +  In practice, that means a unified API between different structures (data types).  - Enumerations aren't integers. Comparing an enumeration to an integer requires a conversion.  - Explicit casts, coercion exists but is limited.    Types are slightly more enforced than in C, just a taste:      Pointers aren't integers, explicit conversion is necessary. -    You won't lose precision by accident, implicit coercions are only authorized in case no precision can be lost. -    Unions cannot be reinterpreted (in an union with an integer and a float, one cannot take a value for another by accident). +    You won't lose precision by accident, implicit coercions are only authorized in cases where no precision can be lost. +    Unions cannot be reinterpreted (in a union with an integer and a float, one cannot take a value for another by accident).      Etc.  - Removing most of the C undefined behaviors (UBs), and when the compiler encounters one, it stops. -- Slice and Array structures are prefered to pointers. +- Slice and Array structures are preferred to pointers.    Types enforced by the compiler are less prone to errors than pointer manipulations.  - Numerical overflows produce an error, unless explicitly accepted using wrapping operators. -- Try and catch mechanism. +- `try` and `catch` mechanism.    It's both handy, trivially implemented (simple error enumeration), and it takes almost no space nor computation time. -- Unused variables are considered as errors by the compiler. -- Many pointer types exist in order to represent what is pointed. +- Unused variables are considered to be errors by the compiler. +- Many pointer types exist in order to represent what is pointed to.    Example: is this a single value or an array, is the length known, etc. -- Structures need a value for their attributes, and it still is possible to give an undefined value (stack garbage), but at least it is explicitely undefined. +- Structures need a value for their attributes, and it is still possible to give an undefined value (stack garbage), but at least it is explicitly undefined.  ## Further Reading -For a start, some concepts are presented on the [Zig learn website][ziglearn]. - -The [official website][zigdoc] provides a reference documentation to the language. +For a start, some concepts are presented on [zig.guide][zigguide]. -For now, documentation for standard library is WIP. +The [official website][zigdoc] provides the reference documentation of the language. The standard library [has its own documentation][zigstd].  [ziglang]: https://ziglang.org -[ziglearn]: https://ziglearn.org/ +[zigguide]: https://zig.guide/  [zigdoc]: https://ziglang.org/documentation/ +[zigstd]: https://ziglang.org/documentation/master/std/ | 
