|
| 1 | +// |
| 2 | +// "We live on a placid island of ignorance in the midst |
| 3 | +// of black seas of infinity, and it was not meant that |
| 4 | +// we should voyage far." |
| 5 | +// |
| 6 | +// from The Call of Cthulhu |
| 7 | +// by H. P. Lovecraft |
| 8 | +// |
| 9 | +// Zig has at least four ways of expressing "no value": |
| 10 | +// |
| 11 | +// * undefined |
| 12 | +// |
| 13 | +// var foo: u8 = undefined; |
| 14 | +// |
| 15 | +// "undefined" should not be thought of as a value, but as a way |
| 16 | +// of telling the compiler that you are not assigning a value |
| 17 | +// _yet_. Any type may be set to undefined, but attempting |
| 18 | +// to read or use that value is _always_ a mistake. |
| 19 | +// |
| 20 | +// * null |
| 21 | +// |
| 22 | +// var foo: ?u8 = null; |
| 23 | +// |
| 24 | +// The "null" primitive value _is_ a value that means "no value". |
| 25 | +// This is typically used with optional types as with the ?u8 |
| 26 | +// shown above. When foo equals null, that's not a value of type |
| 27 | +// u8. It means there is _no value_ of type u8 in foo at all! |
| 28 | +// |
| 29 | +// * error |
| 30 | +// |
| 31 | +// var foo: MyError!u8 = BadError; |
| 32 | +// |
| 33 | +// Errors are _very_ similar to nulls. They _are_ a value, but |
| 34 | +// they usually indicate that the "real value" you were looking |
| 35 | +// for does not exist. Instead, you have an error. The example |
| 36 | +// error union type of MyError!u8 means that foo either holds |
| 37 | +// a u8 value OR an error. There is _no value_ of type u8 in foo |
| 38 | +// when it's set to an error! |
| 39 | +// |
| 40 | +// * void |
| 41 | +// |
| 42 | +// var foo: void = {}; |
| 43 | +// |
| 44 | +// "void" is a _type_, not a value. It is the most popular of the |
| 45 | +// Zero Bit Types (those types which take up absolutely no space |
| 46 | +// and have only a semantic value. When compiled to executable |
| 47 | +// code, zero bit types generate no code at all. The above example |
| 48 | +// shows a variable foo of type void which is assigned the value |
| 49 | +// of an empty expression. It's much more common to see void as |
| 50 | +// the return type of a function that returns nothing. |
| 51 | +// |
| 52 | +// Zig has all of these ways of expressing different types of "no value" |
| 53 | +// because they each serve a purpose. Briefly: |
| 54 | +// |
| 55 | +// * undefined - there is no value YET, this cannot be read YET |
| 56 | +// * null - there is an explicit value of "no value" |
| 57 | +// * errors - there is no value because something went wrong |
| 58 | +// * void - there will NEVER be a value stored here |
| 59 | +// |
| 60 | +// Please use the correct "no value" for each ??? to make this program |
| 61 | +// print out a cursed quote from the Necronomicon. ...If you dare. |
| 62 | +// |
| 63 | +const std = @import("std"); |
| 64 | + |
| 65 | +const Err = error{Cthulhu}; |
| 66 | + |
| 67 | +pub fn main() void { |
| 68 | + var first_line1: *const [16]u8 = ???; |
| 69 | + first_line1 = "That is not dead"; |
| 70 | + |
| 71 | + var first_line2: Err!*const [21]u8 = ???; |
| 72 | + first_line2 = "which can eternal lie"; |
| 73 | + |
| 74 | + std.debug.print("{s} {s} / ", .{ first_line1, first_line2 }); |
| 75 | + |
| 76 | + printSecondLine(); |
| 77 | +} |
| 78 | + |
| 79 | +fn printSecondLine() ??? { |
| 80 | + var second_line2: ?*const [18]u8 = ???; |
| 81 | + second_line2 = "even death may die"; |
| 82 | + |
| 83 | + std.debug.print("And with strange aeons {s}.\n", .{second_line2.?}); |
| 84 | +} |
0 commit comments