I’m glad to see this idea worked out in detail, and for the record.

Given we want to give users control at several points over potential flatness, we must choose either a separate storage classes channel or a variation in variable types themselves.

And my overall sense is that it’s a “pick your poison” situation. But I think complexifying the types goes down a little smoother than adding a new channel to most (but not all) variables. Generic variables can benefit from a type-based solution, but not from a SC-based solution, as this analysis shows.

The SC-based solution shrinks the surface of the flat-vs-not choice, but makes it correspondingly more irregular.

One irregularity you don’t mention is signature alignment. In order to link to a method or field (or override a method) you need the signatures aligned. (We don’t want bridges today please.) This means that the `.flat` annotations are part of the signature (since they compile to Q-types). This means signatures depend on something besides types, surely an add to the net complexity.

Also, type inference can carry flatness in the design of record, but cannot do so in a SC-based design, at least not without more irregular hacks. (Maybe that doesn’t matter?)

On 20 Jul 2022, at 13:05, [email protected] wrote:

Maybe you want or maybe you don't, here is an interesting implementation of ArrayList

public classs ArrayList<E> {
  private E[] array;
  private int size;

  public ArrayList() {
    array = new E.flat[16];   // ahah, flat by default !
  }

  public boolean add(E element) {  // E is not flat
    if (element == null && !array.getClass().isNullable()) {
var newArray = new E[array.length]; // need to store null, use a nullable array
      System.arraycopy(array, 0, newArray, 0, array.length);
      array = newArray;
    }
    if (array.length == size) {
      array = Arrays.copyOf(array, size * 2);
    }
    array[size++] = element:
    return true;
  }
}

It starts with a flat array and if an element null is added, it "unflat" itself. This implementation is interesting because once recompiled with the new generics, a new ArrayList<Integer>() will use a flatten array by default.

I've no idea about the performance of such kind of implementations, but using T.flat give better control on what is flattenable or not in the implementation.

If we choose, we can code this trick in the design of record as well.

So it’s not an advantage of the `.flat` proposal; it’s just a trick that is forced on the programmer willy nilly.

Today a variable is a type, and an optional name. If it is a local or a field it has a name. If it is inside an array or a (possibly generic) container, there is no name. I can refactor my variables all day long through named and unnamed temps, fields, arrays, and other containers. If some but not all of those locations accept my chosen SC, my refactorings have greater friction.

It seems like adding new types is less disruptive than adding a whole new classification for variables.

Reply via email to