Libraries
IJust like the functions we define ourselves, all the functions we call in Zig - including those from the standard library - have their declarations in the source code itself. For example, the print function that we use so often…
We can find its implementation in the path where we downloaded Zig. In the std subdirectory, we will find the debug.zig file.
In that file, we will find the definition of the function:
|
/// Print to stderr, silently returning on failure. /// ... pub fn print(comptime fmt: []const u8, args: anytype) void { //... |
If we wanted to modify that function - or any other - even if we detect a bug or want to create our own version, we are free to do so.
Since our declarations for modeling towers, the river, and so on are growing, we can write them in our own file, for example:
|
hydro.zig |
|
const std = @import("std"); // a tower with oscillating buckets pub const HydroTower = struct { const N_EFFICIENCY_PER_METER: f32 = 0.91; n_efficiency_per_meter: ?f32, // optional n_height: f32, pub fn lift_water( self: *const HydroTower, n_input: ?f32, ) struct { f32, f32 } { return .{ (n_input orelse 0) * std.math.pow( f32, self.n_efficiency_per_meter orelse HydroTower.N_EFFICIENCY_PER_METER, self.n_height, ), self.n_height, }; } // simulate a tower height built between 3.5 and 5m pub fn get_height_btw(n_min: f32, n_max: f32) f32 { return round2(get_rand( n_min, n_max, )); } }; // river flow carried to the tower pub const WaterFlow = struct { n_liters_per_second: f32, pub fn get_fps(self: *const WaterFlow) f32 { const n_min = self.n_liters_per_second * 0.90; return round2(get_rand( n_min, self.n_liters_per_second, )); } }; // inline function to round to 2 decimals pub inline fn round2(n_x: f32) f32 { return @floor(100 * n_x) / 100; } // inline function to get a random number between n_min and n_max inline fn get_rand(n_min: f32, n_max: f32) f32 { return std.Random.float(std.crypto.random, f32) * (n_max - n_min) + n_min; } |
This file will not be executable on its own, but it contains the functions and structures we have defined and can be used by other Zig files. Just as we import print from std.debug, we can now reuse our own functions in the same way. This way, we do not have to define the same code over and over again, making our programs significantly shorter. We have modularized the program.
For a function or structure declared in a library to be callable from outside, we must write the reserved word pub in front of its declaration:
|
pub const WaterFlow = struct { |
o
|
pub inline fn round2(n_x: f32) f32 { |
However, this function will be unreachable from outside the file that contains it:
|
inline fn get_rand(n_min: f32, n_max: f32) f32 { |
Import and use the module like this:
|
const std = @import("std"); const std = @import("std"); const print = std.debug.print; const ArrayList = std.ArrayList; // import the hydro library we wrote const hydro = @import("./hydro.zig"); const WaterFlow = hydro.WaterFlow; const HydroTower = hydro.HydroTower; // if we have not imported a function // explicitly // will have to call it using the // library prefix hydro.round2(n_riverflow) |