Skip to content

comptime interfaces #1268

Closed as not planned
Closed as not planned
@ghost

Description

Proposal on comptime Interfaces / Traits (the terminology is left to the reader / implementer)

motivation

Zig currently has very bad code for expressing some sort of shared properties.

Look at mem.Allocator and heap.xyz for the implemenations if you have not already. (there are other places where this smells of course as well)
Notice the use of @fieldParentPtr and function pointers which make the code hard to read and unnecessarily inefficient by adding pointer indirections.

current state of the art

Currently Zig has compile time ducktyping.
However, one can not easily restrict input to a certain class of inputs. This yields bad compile error messages and very bad readability as explained in the following:
An example: a func that takes some struct with method foo() on it and calls foo(). If you pass in a struct that does not have foo() you get an error, possible deep down the hierarchy which bubbles up out of some library. This error should be brought up at the immediate calling position where you passed your struct.
Even more importantly its bad for documentation because its not clear to the reader what kind of var that func takes. It is much better to express that it takes a struct that has a fucntion foo() by using interfaces.

explanation

A missconception is that interfaces have to happen at runtime and or involve some notion of vtables.
As proposed, interfaces are just compile time checks on a type.
These improve performance because methods are just like regular methods on structs, not fucntion pointers that require an additional lookup.

syntax for interfaces should clearly be

const some_interface = interface {
    fn foo () i32;
    some_int: i32;
}

fn some_func (i: some_interface) {
    i.foo ();
    // ....
}

You can pass any struct to some_func that has a method foo() on it.


To be discussed:

  • a) interfaces can allow to specify member variable as well as functions
  • b) interfaces can be used as a member variable that has a variable that has the inteface
  • c) explicitly implement an interface, sometimes you want to make sure your custom_allocator actually implements the allocator interface, there can easily be added a small syntax to ensure this or a small hack like in golang using an anonymous variable, its not a big deal.

I think all those should be possible but i'd actually recommended to do a first implementation without those three because they can be added later without issues.


This proposal should go along with #1214 making inheritance obsolete by using clean composition.

Also see #1170 (comment) for extremly positive effects of this proposal.



There have been proposals for hacking interfaces using metaprogramming which would have bad consequences because error messages will suffer, everyone will roll their own incompatible imeplentation and as shown above interfaces offer an indespensible tool for structuring code.

If you just want to write c, you can ignore this proposal but your code will be harder to read for most people, harder to debug, refactor(see 2nd link) and possible inefficient.

thanks for your attention 👍

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions