HaxeFoundation / haxe-evolution

Repository for maintaining proposal for changes to the Haxe programming language
111 stars 58 forks source link

Global using at declaration site. #35

Closed back2dos closed 6 years ago

back2dos commented 6 years ago

The idea would is to allow using clauses on enum, interface and perhaps also class (although I don't see the use case there).

enum Option<T> using OptionTools {
  Some(v:T);
  None;
}

class OptionTools {
  static public function map<In, Out>(o:Option<T>, f:In->Out):Option<Out> { 
    /* and so on */
  }
  /* and so forth */
}

This would globally apply the static extension, but only to the type being declared. It would solve https://github.com/HaxeFoundation/haxe-evolution/issues/10 - albeit in a slightly awkward way.

On interfaces it could also do some good:

interface Iterable<T> using Lambda {
  function iterator():Iterator<T>;
}
nadako commented 6 years ago

That's an interesting idea!

Simn commented 6 years ago

I had this same idea before. I wonder if this should be implemented as a first step to solve #10. The second step would then be to automatically move function declarations in enums to such static extension classes, and add the using OptionTools implicitly.

On its own, I wonder if its worth it given that we have import.hx and can just add using OptionTools there. I agree this looks nicer, but I'm not sure it's enough to warrant a syntax change.

RealyUniqueName commented 6 years ago

Import.hx cannot be distributed with haxelib.

back2dos commented 6 years ago

Also, on second thought, I would like this for abstracts too as it allows dispatching on type parameters. Here's a poor example that hopefully still gets the point across:

//Array.hx
@:coreType class Array<T> using ArrayTools { /* all methods except sort */ }
//ArrayTools.hx
class ArrayTools {
  static public function sort<T>(a:Array<T>, compare:T->T->Int):Void;
}
class NumericArrayTools {
  static public function sort<T:Float>(a:Array<T>):Void;
  static public function sum<T:Float>(a:Array<T>):T;
}
class DateArrayTools {
  static public function sort(a:Array<Date>):Void;
}
class ComparableArrayTools {
  static public function sort<T:{ function compare(that:T):Int; }>(a:Array<T>):Void;
}
bendmorris commented 6 years ago

and perhaps also class (although I don't see the use case there)

It gives a nice method for adding "mixins" to your classes. Multiple classes can declare using with the same extension class. AFAIK you can only do this with tink/macros currently.

RealyUniqueName commented 6 years ago

@back2dos are you going to convert this idea to a proposal?

back2dos commented 6 years ago

Well, if @ncannasse could confirm that he'll at least genuinely consider it, I can do that ^^

Simn commented 6 years ago

This needs a proper proposal. I can't speak for Nicolas, but I for one would genuinely consider it.

kaikoga commented 5 years ago

Whoa, I thought this had been already implemented, but was just closed and forgotten...

Is this going to become a proposal?

kaikoga commented 5 years ago

oh sorry, I've overlooked HaxeFoundation/haxe#7462

FuriouZz commented 5 years ago

Does not seem to works with abstract =/. I have Vec4 has no field add.

class Vec4Tool {

  public static inline function add(out: Vec4, v0: Vec4, v1: Vec4) : Vec4 {
    out[0] = v0[0] + v1[0];
    out[1] = v0[1] + v1[1];
    out[2] = v0[2] + v1[2];
    out[3] = v0[3] + v1[3];
    return out;
  }

}

@:using(Vec4.Vec4Tool)
@:forward abstract Vec4(Float32Array) from Float32Array to Float32Array {
  public function new() {
    this = new Float32Array([ 0.0, 0.0, 0.0, 1.0 ]);
  }

  @:arrayAccess
  public inline function getValue(index: Int) {
    return this[index];
  }

  @:arrayAccess
  public inline function setValue(index: Int, value: Float) {
    return this[index] = value;
  }

}
back2dos commented 5 years ago

You should file a bug report, specifying which Haxe version you're using.