Difference between anytype and type

I notice in some case I can use type and anytype interchangeably. For example

fn List(comptime value: anytype) type {
    return struct {
        values: []const value,
    };
}

vs

fn List(comptime value: type) type {
    return struct {
        values: []const value,
    };
}

compiles and seems to do the same thing.

While in other cases, I cannot use the two interchangeable. For example in the return type.

This does not work, ie anytype in the return position, while type works.

fn List(comptime value: anytype) type {
    return struct {
        values: []const value,
    };
}

What are the differences between these two language elements?

anytype can be any type, including the type type. anytype is only allowed in function parameters, as it’s not a real type, but a placeholder.

2 Likes

From Function-Parameter-Type-Inference:

Function parameters can be declared with anytype in place of the type. In this case the parameter types will be inferred when the function is called.

Example:

fn increment(value: anytype) @TypeOf(value) {
    return value + 1;
}

anytype is a mechanism to infer the type from the call value.

Not sure I see how this prevents it from also appearing in the return position?

The return type can also be inferred based on how the return type is used too right?

They explicitly decided agaisn’t type inference in the return type. I don’t remember the issue, but Andrew said it simplified the compiler and lead to more readable code.

1 Like

Zig grammar prevent this. While the return can be TypeExpr the ParamType is:

ParamType
    <- KEYWORD_anytype
     / TypeExpr

anytype is a keyword that can appear only as function parameter type.

1 Like

Oh my! All of these sounds arbitrary to me :expressionless: but I guess it is the price you pay for jumping into a language still influx :slight_smile:

#230 and #447 (var was anytype)

3 Likes

999 times out of 1000, not being able to specify what a function returns is a failure of the abstraction.

What are you trying to do that you need the return type inferred?

2 Likes

Nothing in particular. When learning a new language I usually just try things out and see what works or does not, as I try to get a better understanding of how to use the language

Dropping a link to a doc related to this subject: Generic Programming and anytype

2 Likes

And with this, I discovered the doc section! Thanks!

1 Like

You can write Type Functions to calculate return types, if there’s some kind of relation with the input type.

For example, in the parser combinator library mecha, there are two Type Functions ParserResult and ReturnType which calculate return types for some functions based on the type passed into a function through anytype.

ReturnType takes a type as a parameter, and depending on whether it’s a pointer to a function or a function itself, uses typeinfo to find the return type of the parse function.

Since all parsers wrap their results in a struct created through the Type Function Result, they store the type of the result value as a member of the struct, which ParserResult can directly access.

So when the exact relationship between the return type of a function and the input type is known, you can write a type level function to calculate the return type in place of actual return type deduction. It’s certainly not a replacement for complete return type deduction, but it can allow you to write functions you would otherwise have to rely on type erasure for (meaning returning *anyopaque then casting it back to its original type).

3 Likes