class Event<T> {
public var subscribers : Array<T -> Void>;
public function subscribe(f : T -> Void) {
subscribers.push(f);
}
public function new() {
subscribers = new Array<T -> Void>();
}
}
and when i try to use it like this
var event = new Event<Void>();
event.subscribe(function() { trace("!"); });
i get
Void -> Void should be (Void) -> Void
is it even possible to use Void as type parameter in that way? it works with any non-Void type i tried it with, but it would be nice to use this event class as notifier without any data too.
EDIT:
i used “blockquote” instead of “Preformatted text”, so some haven’t been visible
Hi! It is not possible to pass a function with no arguments, because it has different arity than required, and there’s no unit type in Haxe, so functions without arguments have zero arity.
There are a couple ways around it:
add your own “unit type” and use it instead of Void, e.g.:
enum abstract NoData(Dynamic) {
var NoData = null; // just a simple null value at run-time
}
then you can have Event<NoData>, callbacks that take NoData and dispatch(NoData)
use an abstract for your callbacks with an implicit conversion from a “niladic” function
abstract EventCallback<T>(T->Void) from T->Void {
@:from static inline function fromNiladic<T>(f:()->Void):EventCallback<T> {
return _ -> f(); // could be just `cast f` for the targets that don't care like JS
}
}
You can also combine them and make fromNiladic return EventCallback<NoData> if you want to forbid passing no-argument functions for anything else than EventCallback<NoData>.
I think your class needs to be parameterized too: class Event<T> { ..
You could give the T a name, by doing so: (data:T) -> Void, that’ll make your callbacks more descriptive.
You could also make typedef for this callback, that avoids repeating T -> Void over again.
class Event<T> {
public var subscribers : Array<EventCallBack<T>>;
public function subscribe(f : EventCallBack<T>) {
subscribers.push(f);
}
public function new() {
subscribers = new Array<EventCallBack<T>>();
}
}
private typedef EventCallBack<T> = (data:T) -> Void;
Now back to your example, you don’t provide a event value to your subscribe function, so this should work:
var event = new Event();
event.subscribe(function(data) { trace(data + "!"); });
If you don’t even want to have data, then the EventCallBack could look like this:
private typedef EventCallBack<T> = () -> Void;
Using older syntax that is Void -> Void, but I hope you’re on Haxe 4 too
Another option is to generalize type parameter even more:
class Event<T> {
public function subscribe(f : T) {
subscribers.push(f);
}
public function new() {
subscribers = new Array<T>();
}
}
//and then
var event = new Event();
event.subscribe(function() { trace("!"); }); // Ok!
$type(event); // Event<Void->Void>
You can add haxe.Constraints.Function constraint to limit allowed type parameters to functions only.