2020 report
Aleksandr Kuzmenko. HaxeIn 2020.
HaxeUp Hamburg
February 2020
April: BENCHS.HAXE.ORG
Alexander Blum �aka �AlexHaxe
May: Haxe 4.1 is released!
Over one hundred other additions, improvements, optimizations and bugfixes.
May: dts2hx
A tool to convert TypeScript definitions to Haxe externs.
https://github.com/haxiomic/dts2hx
By George Corney aka haxiomic
Haxe 4.1: JVM is official
Hard way to success
One of the best targets now
JVM
Haxe 4.1: SSL support for interpreter
API packages:
haxe.Http.requestUrl("https://haxe.org")
Haxe 4.1: New exception handling
Base class for exceptions: haxe.Exception
Custom exceptions
Wildcard catch
similar to
throw new haxe.Exception('Terrible error');
class MyException extends haxe.Exception {}
//...
throw new MyException('Terrible error');
try {
//...
} catch(e:haxe.Exception) {
//...
}
try {
//...
} catch(e:Dynamic) {
//...
}
Haxe 4.1: New exception handling
Old style (still works)
New style
try {
doSomething();
throw 'Terrible error!';
} catch(e:String) {
trace(CallStack.toString(CallStack.exceptionStack()));
//rethrows with new stack
throw e;
} catch(e:Dynamic) {
trace(e);
trace(CallStack.toString(CallStack.exceptionStack()));
}
try {
doSomething();
throw new TerribleException();
} catch(e:TerribleException) {
trace(e.stack);
//keeps original stack
throw e;
} catch(e:haxe.Exception) {
trace(e); //prints message only
trace(e.details()); //message+stack
}
Haxe 4.1: New exception handling
Haxe 4.1: New exception handling
Omitting type hint in “catch”
Implicitly typed as haxe.Exception
try {
//...
} catch(e) {
trace(e.details());
}
Haxe 4.1: Tail recursion elimination
static function iteratorLoop<K,V>(node:TreeNode<K, V>, acc:Array<V>) {
if (node != null) {
iteratorLoop(node.left, acc);
acc.push(node.value);
iteratorLoop(node.right, acc);
}
}
static iteratorLoop(node,acc) {
while(true) {
if(node != null) {
haxe_ds_BalancedTree.iteratorLoop(node.left,acc);
acc.push(node.value);
node = node.right;
continue;
}
return;
}
}
compiled to
Automatically transforms recursive calls into loops.
Haxe 4.1: Tail recursion elimination
Haxe 4.1: other notable changes
June: Haxe Evolution
Online meeting of the core team members
to discuss active evolution proposals.
Hint: create an issue in the repo to discuss the idea before submitting a proposal.
Proposal: Void as unit type
Author: Dan Korostelev https://github.com/HaxeFoundation/haxe-evolution/pull/76
Allow using Void in value places similar to unit types in other languages
Verdict: open questions to decide before accepting
var signal = new Signal<Void>();
signal.trigger(Void);
Proposal: Metadata for local variables
Author: Peter Achberger https://github.com/HaxeFoundation/haxe-evolution/pull/74
Add new syntax for metadata on local variables.
Verdict: accepted
var @:meta foo:Bar;
Proposal: Typed metadata
Author: Mario Carbajal https://github.com/HaxeFoundation/haxe-evolution/pull/73
Add typed metadata that has to be imported to be used. Compiler checks for metadata names.
Verdict: rejected. We want the feature, but let’s look for alternative syntax.
package my.lib;
@.haxe.meta.MetadataType
abstract MyMeta(Any) {}
import my.lib.MyMeta;
@.MyMeta class Foo {
// Full paths also work
@.my.lib.MyMeta function mop() {}
// Error RandomMetaName is unknown
@.RandomMetaName function bar() {}
}
Proposal: Multi-argument array access
Author: ErikRikoo https://github.com/HaxeFoundation/haxe-evolution/pull/72
Allow multiple arguments for array access syntax.
Verdict: not decided. Investigate how tricky the change would be.
array[a, b, c];
Proposal: Abstract classes
Author: Aleksandr Kuzmenko https://github.com/HaxeFoundation/haxe-evolution/pull/69
Introduce classes that provide incomplete implementation and cannot be instantiated directly.
Verdict: accepted
abstract class Abstr {
public function commonMethod():Int {
return 123;
}
abstract function implementMe():Void;
}
Proposal: Default implementations on interfaces
Author: shohei909 https://github.com/HaxeFoundation/haxe-evolution/pull/70
Allow implementations in interface declarations.
Verdict: rejected. We don’t want to have code in interfaces because it mixes concepts.
interface A {
function a():Void {
trace("A");
}
}
class B implements A {}
Proposal: Onsite getters and setters
Author: Dmitry Hryppa https://github.com/HaxeFoundation/haxe-evolution/pull/63
Allow implementations for getters and setters directly in places where they are declared.
Verdict: not decided. We agreed that this would be good, but it’s unclear if the syntax is ok.
public var dataExists(() -> data != null, never):Bool;
Proposal: Self access for abstracts
Author: Mark Knol https://github.com/HaxeFoundation/haxe-evolution/pull/62
Add a way to access “self” for abstracts, which is a getter for `(cast this:MyAbstract)`
Verdict: not decided. The feature is useful, but the syntax remains an open question.
abstract MyAbstract(MyType) as selfIdent {
public function doSomething() {
selfIdent.print();
}
function print() {
trace(this);
}
}
Proposal: Default type parameters
Author: benmerckx https://github.com/HaxeFoundation/haxe-evolution/pull/50
Optionally declare a default type for generic type parameters.
Verdict: not decided. Open questions remain.
class Test<T = String> {}
$type((null: Test)); // Test<String>
Proposal: Polymorphic “this” types
Author: matulkum https://github.com/HaxeFoundation/haxe-evolution/pull/36
A polymorphic “this” type represents a type that is the subtype of the containing class or interface.
Verdict: not decided. This would be useful, but it’s unclear how to implement it.
interface Config {
function setBase(v:Int):this;
}
interface ConfigExt extends Config {
function setExt(v:Bool):this;
}
configExt.setBase(1).setExt(true);
class BaseButton {
function onClick(cb:(btn:this)->Void);
//...
class TabButton extends BaseButton {
function extra();
//...
var button = new TabButton();
button.onClick((tab:TabButton) -> tab.extra());
Proposal: Type parameter variance of enum
Author: shohei909 https://github.com/HaxeFoundation/haxe-evolution/pull/28
Support type parameter covariance and contravariance of enum.
Verdict: rejected. This should be approached in a broader scope, not just for enums.
var optionFloat:Option<Float>;
var optionInt = Option.Some(1);
optionFloat = optionInt;
Road to Haxe 4.2
Road to Haxe 4.2: implemented
Module-level statics
Allow to declare variables and functions without a class declaration.
Tools.hx
Main.hx
package my.pack;
function isEven(n:Int):Bool {
return n % 2 == 0;
}
import my.pack.Tools;
function main() {
trace(isEven(14));
}
Road to Haxe 4.2: implemented
Abstract classes
“Classic” Java-style abstract classes.
abstract class Shape {
public function new() {}
abstract public function vertices():Array<Int>;
}
class Square extendss Shape{
public function vertices():Array<Int> {
return [0,0, 1,0, 1,1, 0,1];
}
}
Road to Haxe 4.2: implemented
Event loops for threads
Road to Haxe 4.2: implemented
Event loops for threads
Threads has to be created with event loop explicitly
function main() {
var mainThread = Thread.current();
var secondary = Thread.createWithEventLoop(() -> {
Sys.sleep(1); //useful work
mainThread.events.run(() -> {
trace('This is printed from the main thread');
});
});
secondary.events.run(() -> {
trace('This is printed from the secondary thread');
});
Sys.sleep(2); //wait for the thread to complete
}
Road to Haxe 4.2: implemented
Event loops for threads
Threads without event loop throw sys.thread.NoEventLoopException
function main() {
var mainThread = Thread.current();
var secondary = Thread.create(() -> {
Sys.sleep(1); //useful work
mainThread.events.run(() -> {
trace('This is printed from the main thread');
});
});
//Throws sys.thread.NoEventLoopException
secondary.events.run(() -> {
trace('This is never printed');
});
}
Road to Haxe 4.2: implemented
Event loops for threads: deferred events
thread.events.promise() keeps the event loop alive until thread.events.runPromised(job)
function main() {
var mainThread = Thread.current();
Thread.create(() -> {
mainThread.events.promise();
Sys.sleep(1); //useful work
mainThread.events.runPromised(() -> {
trace('This is printed from the main thread');
});
});
}
Road to Haxe 4.2: implemented
New features for abstracts
Thanks to Dmitrii Maganov (github @vonagam)
Road to Haxe 4.2: implemented
New features for abstracts
Transitivity
Enable transitive casts using @:transitive meta
abstract Items(Array<Int>) from Array<Int> to Array<Int> {}
@:transitive abstract Collection(Items) from Items to Items {}
var collection:Collection = [123];
var array:Array<Int> = collection;
Road to Haxe 4.2: implemented
New features for abstracts
Variance forwarding
Forward variance using @:forward.variance meta
Now Any may be used instead of Dynamic in type parameters
@:forward.variance abstract Money(Int) {}
var arrayOfInt = [1, 2, 3];
var arrayOfMoney:Array<Money> = arrayOfInt;
Road to Haxe 4.2: implemented
Other things
Thanks to Nat Quayle Nelson (github @NQNStudios)
Thanks to Mario Carbajal (github @basro)
See the blog post “The type Inference mystery novel” on https://haxe.org/blog
Road to Haxe 4.2: in progress
Low-level asynchronous system API
FileSystem.openFile(path, Append, (error, file) -> {
file.write(data, offset, length, (error, bytesWritten) -> {
file.close((_, _) -> {});
});
});
Road to Haxe 4.2: in progress
Libuv bindings for interpreter (eval target)
import sys.thread.Thread;
import eval.luv.*;
var addr = SockAddr.ipv4('127.0.0.1', 1234).resolve();
var udp = Udp.init(Thread.current().events.handle).resolve();
udp.send(['Hello, World!'], addr, (result -> {
result.resolve();
udp.close(() -> {});
}));
Further plans
HAXE IS GREAT
Questions?
alex@stablex.ru
twitter @RealyUniqueName