Functions

    Shell

    1. 1/1 test "function"... OK
    2. All 1 tests passed.

    Function values are like pointers:

    test.zig

    1. const assert = @import("std").debug.assert;
    2. comptime {
    3. assert(@TypeOf(foo) == fn()void);
    4. assert(@sizeOf(fn()void) == @sizeOf(?fn()void));
    5. }
    6. fn foo() void { }

    Shell

    Structs, unions, and arrays can sometimes be more efficiently passed as a reference, since a copy could be arbitrarily expensive depending on the size. When these types are passed as parameters, Zig may choose to copy and pass by value, or pass by reference, whichever way Zig decides will be faster. This is made possible, in part, by the fact that parameters are immutable.

    pass_by_reference_or_value.zig

    1. x: i32,
    2. y: i32,
    3. fn foo(point: Point) i32 {
    4. // Here, `point` could be a reference, or a copy. The function body
    5. // can ignore the difference and treat it as a value. Be very careful
    6. // taking the address of the parameter - it should be treated as if
    7. // the address will become invalid when the function returns.
    8. return point.x + point.y;
    9. }
    10. const expect = @import("std").testing.expect;
    11. try expect(foo(Point{ .x = 1, .y = 2 }) == 3);

    Shell

    1. $ zig test pass_by_reference_or_value.zig
    2. 1/1 test "pass struct to function"... OK
    3. All 1 tests passed.

    For extern functions, Zig follows the C ABI for passing structs and unions by value.

    test_fn_type_inference.zig

    Shell

    1. $ zig test test_fn_type_inference.zig
    2. 1/1 test "fn type inference"... OK
    3. All 1 tests passed.

    test_fn_reflection.zig

    1. const expect = @import("std").testing.expect;
    2. test "fn reflection" {
    3. try expect(@typeInfo(@TypeOf(expect)).Fn.args[0].arg_type.? == bool);
    4. try expect(@typeInfo(@TypeOf(expect)).Fn.is_var_args == false);
    5. }

    Shell