#Does Zig cache evaluated return types of functions?

1 messages ยท Page 1 of 1 (latest)

wide abyss
#

I know that Zig caches comptime function results. But does it cache the values of expressions specifying the return types of functions? E.g.

fn func(comptime a: i32, b: anytype) Expr { ... }

where Expr is a complicated expression involving a and @TypeOf(b).
Is Expr going to be comptime-evaluated per each callsite, or only per each combination of a and @TypeOf(b)?

steady saddle
#

As long as the result is the same, it makes no practical matter except perhaps for performance or calculating branch quota. What are you going to do differently based on a yes or no answer?

wide abyss
#

My concern is exactly the compilation time. If a function is called from multiple sites with the same combination of a and @TypeOf(b), will it unnecessarily increase the compilation time, and should I make effort in code to cache return types manually.

#

NB. Along the same lines, one could argue that caching return values of comptime functions makes no practical matter either. If you know what I mean...

steady saddle
#

YAGNI/premature optimization.. Worry about that after you've done the simple thing and discover you have a performance problem. Otherwise, you can try it both ways, measure, and see if it makes a difference worthwhile.

wide abyss
#

Thanks for the suggestion. Do I take it that there's no explicit answer to the question? ๐Ÿ˜‰

#

Measuring is a bit difficult, as I'm writing a library. As usually with libraries, one needs to tend to think a bit more in advance than in normal app development, since API changes might create larger overhead.

proud kiln
#

assuming my logic isnt flawed, it does appear to analyze it multiple times

fn func(comptime a: i32, b: anytype) blk: {
    @compileLog(a, b);
    break :blk void;
} {}

pub fn main() void {
    func(0, "hi");
    func(0, "hi");
    func(0, "hi");
}

but only if the block is inline like this

#

if you move the blks logic into a separate function it seems to only get called once

steady saddle
#

I don't know the answer, and it would be a point-in-time answer with no guarantees it doesn't change tomorrow. For your library it's worthwhile to write examples in parallel so that you know that your API makes sense to consume.

proud kiln
#

@noble forum since youre online id like to make sure im correct here ๐Ÿ™ƒ

steady saddle
#

Andrew has spoken about getting comptime performance on par with python, but that optimization phase will likely come closer to 1.0. All the more reason not to bake in choices based on current state unless you really need to.

wide abyss
wide abyss
# steady saddle Andrew has spoken about getting comptime performance on par with python, but tha...

I'm working with cases where return type inferrence is quite complicated if done using reflection, if not occasionally impossible. So I'd like to know if I can use the pattern:

fn (arguments) @TypeOf(blk: { function body }) {
    function body
}

because if not, I need to spend significant time implementing the return type inference using the reflection (and make sure it is possible in all cases - which may become a challenge per se, in which case I might need to rethink the entire API).

#

Especially since in some cases the job of providing function return types might be on the side of the library user, which could raise the complexity of library usage prohibitively.

noble forum
drifting arrow
#

I am guessing that memoising happens after the evaluation of the signature, since function memoising that I am aware of does so based off of the signature, including comptime parameters

wide abyss
#

I now realized that I got concerned about it, since in my case the complexity would be O(N^2) if the results are not cached. Even though in practice N should be small. I guess I have a subconscious detector of complexities larger than O(N log N) ๐Ÿ˜„