1. 9
    1. 1

      Generics are a Nightmare. Generics are much harder to implement than templates.

      I got curious about the implementation… I’ve been reading through the Vale blog posts for a while but it’s gonna take me a while to digest some of this!

      struct Tup<T1, T2> {
        0 T1;
        1 T2;
      func drop<T1, T2>(tup Tup<T1, T2>)
      where func drop(T1)void, func drop(T2)void {
        [a, b] = tup;

      It looks like generic functions can query the existence of function overloads? I think it’s like an anonymous trait impl lookup?

      The implementation of Option (Opt) is also interesting

      abstract func isEmpty<T>(virtual opt Opt<T>) bool
      where func drop(T)void;
      func isEmpty<T>(opt None<T>) bool
      where func drop(T)void
      { return true; }
      func isEmpty<T>(opt Some<T>) bool
      where func drop(T)void
      { return false; }
      1. 2

        Your understanding is correct! These generics don’t require traits, they only require that a function exists for a certain type. It’s a nice way to decouple functions from data. They’re explained more here: https://verdagon.dev/blog/concept-functions

        Also, that Tup is actually a casualty of the great generics endeavor. Before generics, it used to work like in https://verdagon.dev/blog/const-generics-spread and handle any number of elements. It’ll be fun to get that working in a post-generics world.

        #!DeriveStructDrop means “don’t automatically generate a drop function for this, I’ll be doing it myself”

        Some planned syntactic improvements that might be relevant:

        • where ~T instead of where func drop(T)void
        • Default to #!DeriveStructDrop, so the automatic drop function is opt-in instead of opt-out.
        • Have some sort of block to surround e.g. those isEmpty funcs, so that we can write the common where clause once.

        Happy to clarify anything, and feel free to drop by the discord too! Lots of folks toss around questions in there.