const expect = @import("std").testing.expect; // Functions are declared like this fn add(a: i8, b: i8) i8 { return if (a == 0) b else a + b; } // The export specifier makes a function externally visible in the generated // object file, and makes it use the C ABI. export fn sub(a: i8, b: i8) i8 { return a - b; } // The extern specifier is used to declare a function that will be resolved // at link time, when linking statically, or at runtime, when linking // dynamically. extern "c" fn atan2(a: f64, b: f64) f64; // The @setCold builtin tells the optimizer that a function is rarely called. fn abort() noreturn { @setCold(true); while (true) {} } // The naked calling convention makes a function not have any function prologue // or epilogue. This can be useful when integrating with assembly. fn _start() callconv(.Naked) noreturn { abort(); } // The inline specifier forces a function to be inlined at all call sites. // If the function cannot be inlined, it is a compile-time error. inline fn shiftLeftOne(a: u32) u32 { return a << 1; } // The pub specifier allows the function to be visible when importing. // Another file can use @import and call sub2 pub fn sub2(a: i8, b: i8) i8 { return a - b; } // Functions can be used as values and are equivalent to pointers. fn do_op(fn_call: fn (a: i8, b: i8) i8, op1: i8, op2: i8) i8 { return fn_call(op1, op2); } test "function" { expect(do_op(add, 5, 6) == 11); expect(do_op(sub2, 5, 6) == -1); } const Point = struct { x: i32, y: i32 }; fn foo(point: Point) i32 { // Here, `point` could be a reference, or a copy. The function body // can ignore the difference and treat it as a value. Be very careful // taking the address of the parameter - it should be treated as if // the address will become invalid when the function returns. return point.x + point.y; } test "pass struct to function" { expect(foo(Point{ .x = 1, .y = 2 }) == 3); } fn addFortyTwo(x: anytype) @TypeOf(x) { return x + 42; } test "fn type inference" { expect(addFortyTwo(1) == 43); expect(@TypeOf(addFortyTwo(1)) == comptime_int); const y: i64 = 2; expect(addFortyTwo(y) == 44); expect(@TypeOf(addFortyTwo(y)) == i64); } test "fn reflection" { expect(@typeInfo(@TypeOf(expect)).Fn.return_type.? == void); expect(@typeInfo(@TypeOf(expect)).Fn.is_var_args == false); }