#Can I make a function at compile time based on some arguments?

1 messages · Page 1 of 1 (latest)

north solar
#

Example

fn fooA1B1(_: std.mem.Allocator) void {
  const input_a = comptime get_a(1);
  const input_b = comptime get_b(1);
  bar(input_a, input_b);
}

fn fooA1B2(_: std.mem.Allocator) void {
  const input_a = comptime get_a(1);
  const input_b = comptime get_b(2);
  bar(input_a, input_b);
}

fn fooA2B1(_: std.mem.Allocator) void {
  const input_a = comptime get_a(2);
  const input_b = comptime get_b(1);
  bar(input_a, input_b);
}

...

Instead, I would like something like this:

const FooAxBy: type = fn(std.mem.Allocator) void;

fn make_fooAxBy(x: comptime_int, y: comptime_int) FooAxBy {
  const input_a = comptime get_a(x);
  const input_b = comptime get_b(y);
  // madeup syntax
  return fn foo(_: std.mem.Allocator) void {
    bar(input_a, input_b);
  }
}

Context

I am running benchmarks with Zbench, and since it expects the functions I benchmark to have a certain type signature (i.e. receives an allocator and nothing else), I am creating a lot of wrapper functions since I want to benchmark my code on a lot of different types of inputs.

Question

Is it possible to make and return functions like I have shown above?
Is there another way to reduce boilerplate in my situation? (avoid XY problem)

turbid breach
#
const std = @import("std");

const FooAxBy: type = fn (std.mem.Allocator) void;

fn get_a(i: comptime_int) comptime_int {
    return i;
}

fn get_b(i: comptime_int) comptime_int {
    return i;
}

fn bar(i: comptime_int, j: comptime_int) void {
    _ = i;
    _ = j;
}

fn make_fooAxBy(x: comptime_int, y: comptime_int) FooAxBy {
    const input_a = comptime get_a(x);
    const input_b = comptime get_b(y);
    // madeup syntax
    return struct {
        fn foo(_: std.mem.Allocator) void {
            bar(input_a, input_b);
        }
    }.foo;
}

test "make fooAxBy" {
    const foo = make_fooAxBy(1, 2);
    foo(std.testing.allocator);
}

This seems to work for me

north solar
#

is that how I am expected to do it or is that just a hack that will stop working a few zig versions later?

turbid breach
#

Can't guarantee it won't stop working, zig has every right to change, but AFAIK it's convention for lambda-style code in zig. It's also not reliant on anything particularly weird or obscure.

#

Trying to find one in the stdlib if that helps to make it seem more "legit"

#

Yeah no examples in the stdlib based on some regex search. I can't imagine what would break it though.

north solar
#

Seems to be working