Js extern and extension mechanism.

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

Js extern and extension mechanism.

sledorze
Hi!

I want to stress this idea to use the new extension mechanism we've discussed with Juraj and implemented as a macro for Js externs (at least).

I think it could makes things a lot easier (better completion) and provide the ability something impossible today; to use others extensions at the same time.

A good example is the mongodb signature; it has a lot of variant signatures in it, all those ending with some callbacks.

A good pattern for certain usages is to be able to automatically transform a function finishing by a callback into a function returning a Future.

I've already done that as a test and it works perfectly but not with typedef overloads (as they rely on a fallback in the compiler, so can't trigger the futures extensions ).

So, this new mechanism will give us the ability to better handle such scenarios.


Wondering now if you would use it and if we then should rework Dion's node externs..

I need some feedback..
Stephane
Reply | Threaded
Open this post in threaded view
|

Re: Js extern and extension mechanism.

Dion Whitehead Amago
Hey Stephane,

I wish I could provide some better feedback, but I would really need to dive into it more to provide something constructive.  For example, I haven't dealt explicitly with Futures, and don't have a good feeling of whether they force users to write code in a style they may not want to.  On the surface is sounds like a good idea though, if it means that code is more readable and easier to follow.

That's not even 2 cents.  :-)

On Fri, Oct 21, 2011 at 4:08 PM, sledorze <[hidden email]> wrote:
Hi!

I want to stress this idea to use the new extension mechanism we've
discussed with Juraj and implemented as a macro for Js externs (at least).

I think it could makes things a lot easier (better completion) and provide
the ability something impossible today; to use others extensions at the same
time.

A good example is the mongodb signature; it has a lot of variant signatures
in it, all those ending with some callbacks.

A good pattern for certain usages is to be able to automatically transform a
function finishing by a callback into a function returning a Future.

I've already done that as a test and it works perfectly but not with typedef
overloads (as they rely on a fallback in the compiler, so can't trigger the
futures extensions ).

So, this new mechanism will give us the ability to better handle such
scenarios.


Wondering now if you would use it and if we then should rework Dion's node
externs..

I need some feedback..
Stephane


--
View this message in context: http://haxe.1354130.n2.nabble.com/Js-extern-and-extension-mechanism-tp6918566p6918566.html
Sent from the Haxe mailing list archive at Nabble.com.

--
haXe - an open source web programming language
http://haxe.org


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Js extern and extension mechanism.

Juraj Kirchheim
In reply to this post by sledorze
On Fri, Oct 21, 2011 at 11:08 PM, sledorze <[hidden email]> wrote:
> Hi!
>
> I want to stress this idea to use the new extension mechanism we've
> discussed with Juraj and implemented as a macro for Js externs (at least).
>
> I think it could makes things a lot easier (better completion) and provide
> the ability something impossible today; to use others extensions at the same
> time.

This is definitely the right step towards simple JS-integration
without sacrificing haXe-awesomeness.
Hope some people will start using it, so there's some feedback from field tests.

> A good example is the mongodb signature; it has a lot of variant signatures
> in it, all those ending with some callbacks.
>
> A good pattern for certain usages is to be able to automatically transform a
> function finishing by a callback into a function returning a Future.

There's two things to consider:
1. Not every function is a callback (consider filter/map/reduce operations).
2. You might be shadowing the actual return value.

I think there's a solution to each:
1. Don't make this the default. Instead, if the return type is a
Future, assume the callback was there
2. Let the Future contain the return value

It would look something like this:

        interface Future < Data, Immediate > {
                function get(handler:Data->Dynamic):Immediate;
        }
        class SimpleFuture < Data, Immediate > implements Future <Data, Immediate> {
                public var immediate:Immediate;
                var d:Data;
                var isDone:Bool;
                var handlers:Array < Data->Dynamic > ;
                public function new() {
                        this.isDone = false;
                        this.handlers = new Array();
                }
                public function get(handler:Data->Dynamic):Immediate {
                        if (isDone) handler(d);
                        else handlers.push(handler);
                        return immediate;
                }
                public function done(data:Data):Void {
                        if (isDone) throw 'assert';
                        isDone = true;
                        d = data;
                        for (handler in handlers)
                                handler(data);
                        handlers = null;
                }
        }

And then the following code:

      @:native(bar) function foo(a:A, b:B):Future<{ x:X, y:Y }, C>;

Will generate

        static public inline function foo(target:TargetType, a:A, b:B):Future
< { x:X, y:Y }, C > {
                var ret = new SimpleFuture< { x:X, y:Y }, C >();
                ret.immediate = untyped target.bar(a, b, function (x:X, y:Y):Void {
                        ret.done( { x:x, y:y } );
                });
                return ret;
        }

Which will be used as:

        myTargetTypeInstance.foo(someA, someB).get(function (data)
...).someMethodOfC()

I'm not sure whether wrapping up the arguments into an object is a
good idea. However it makes SimpleFuture in itself entirely type-safe.
No Reflect.callMethod things going on.

Anyway, great work so far :)

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Js extern and extension mechanism.

sledorze
In reply to this post by Dion Whitehead Amago
Just to clarify,

the intend is not to write externs with any Future abstraction, just use the plain new extensions mechanism so that IF one wants to use other extensions (think using) based library (like Future's) he then can do it.

Stephane

On Fri, Oct 21, 2011 at 11:46 PM, Dion Whitehead Amago [via Haxe] <[hidden email]> wrote:
Hey Stephane,

I wish I could provide some better feedback, but I would really need to dive into it more to provide something constructive.  For example, I haven't dealt explicitly with Futures, and don't have a good feeling of whether they force users to write code in a style they may not want to.  On the surface is sounds like a good idea though, if it means that code is more readable and easier to follow.

That's not even 2 cents.  :-)

On Fri, Oct 21, 2011 at 4:08 PM, sledorze <[hidden email]> wrote:
Hi!

I want to stress this idea to use the new extension mechanism we've
discussed with Juraj and implemented as a macro for Js externs (at least).

I think it could makes things a lot easier (better completion) and provide
the ability something impossible today; to use others extensions at the same
time.

A good example is the mongodb signature; it has a lot of variant signatures
in it, all those ending with some callbacks.

A good pattern for certain usages is to be able to automatically transform a
function finishing by a callback into a function returning a Future.

I've already done that as a test and it works perfectly but not with typedef
overloads (as they rely on a fallback in the compiler, so can't trigger the
futures extensions ).

So, this new mechanism will give us the ability to better handle such
scenarios.


Wondering now if you would use it and if we then should rework Dion's node
externs..

I need some feedback..
Stephane


--
View this message in context: http://haxe.1354130.n2.nabble.com/Js-extern-and-extension-mechanism-tp6918566p6918566.html
Sent from the Haxe mailing list archive at Nabble.com.

--
haXe - an open source web programming language
http://haxe.org


--
haXe - an open source web programming language
http://haxe.org


If you reply to this email, your message will be added to the discussion below:
http://haxe.1354130.n2.nabble.com/Js-extern-and-extension-mechanism-tp6918566p6918667.html
To unsubscribe from Js extern and extension mechanism., click here.



--
Stéphane Le Dorze


Reply | Threaded
Open this post in threaded view
|

Re: Js extern and extension mechanism.

Juraj Kirchheim
In reply to this post by Juraj Kirchheim
On second thought, when the first parameter of Future is not an
anonymous type, then it should be assumed the callback only receives
one argument that will be passed to the SimpleFuture directly (without
creating an object).

On Sat, Oct 22, 2011 at 1:06 AM, Juraj Kirchheim
<[hidden email]> wrote:

> On Fri, Oct 21, 2011 at 11:08 PM, sledorze <[hidden email]> wrote:
>> Hi!
>>
>> I want to stress this idea to use the new extension mechanism we've
>> discussed with Juraj and implemented as a macro for Js externs (at least).
>>
>> I think it could makes things a lot easier (better completion) and provide
>> the ability something impossible today; to use others extensions at the same
>> time.
>
> This is definitely the right step towards simple JS-integration
> without sacrificing haXe-awesomeness.
> Hope some people will start using it, so there's some feedback from field tests.
>
>> A good example is the mongodb signature; it has a lot of variant signatures
>> in it, all those ending with some callbacks.
>>
>> A good pattern for certain usages is to be able to automatically transform a
>> function finishing by a callback into a function returning a Future.
>
> There's two things to consider:
> 1. Not every function is a callback (consider filter/map/reduce operations).
> 2. You might be shadowing the actual return value.
>
> I think there's a solution to each:
> 1. Don't make this the default. Instead, if the return type is a
> Future, assume the callback was there
> 2. Let the Future contain the return value
>
> It would look something like this:
>
>        interface Future < Data, Immediate > {
>                function get(handler:Data->Dynamic):Immediate;
>        }
>        class SimpleFuture < Data, Immediate > implements Future <Data, Immediate> {
>                public var immediate:Immediate;
>                var d:Data;
>                var isDone:Bool;
>                var handlers:Array < Data->Dynamic > ;
>                public function new() {
>                        this.isDone = false;
>                        this.handlers = new Array();
>                }
>                public function get(handler:Data->Dynamic):Immediate {
>                        if (isDone) handler(d);
>                        else handlers.push(handler);
>                        return immediate;
>                }
>                public function done(data:Data):Void {
>                        if (isDone) throw 'assert';
>                        isDone = true;
>                        d = data;
>                        for (handler in handlers)
>                                handler(data);
>                        handlers = null;
>                }
>        }
>
> And then the following code:
>
>      @:native(bar) function foo(a:A, b:B):Future<{ x:X, y:Y }, C>;
>
> Will generate
>
>        static public inline function foo(target:TargetType, a:A, b:B):Future
> < { x:X, y:Y }, C > {
>                var ret = new SimpleFuture< { x:X, y:Y }, C >();
>                ret.immediate = untyped target.bar(a, b, function (x:X, y:Y):Void {
>                        ret.done( { x:x, y:y } );
>                });
>                return ret;
>        }
>
> Which will be used as:
>
>        myTargetTypeInstance.foo(someA, someB).get(function (data)
> ...).someMethodOfC()
>
> I'm not sure whether wrapping up the arguments into an object is a
> good idea. However it makes SimpleFuture in itself entirely type-safe.
> No Reflect.callMethod things going on.
>
> Anyway, great work so far :)
>

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Js extern and extension mechanism.

sledorze
In reply to this post by Juraj Kirchheim
Hmmm.. I think we can go simpler by defining something like that once and foreall for last param functions.
 (return null; needs an implementation):

class Fut0 {
  public static function cc < R > (f : (R -> Void) -> Void) : Future<R> { return null; }
}
class Fut1 {
  public static function cc < A, R > (f : A -> (R -> Void) -> Void, a : A) : Future<R> { return null; }
}
class Fut2 {
  public static function cc < A, B, R > (f : A -> B -> (R -> Void) -> Void, a : A, b : B) : Future<R> { return null; }
}
class Fut3 {
  public static function cc < A, B, C, R> (f : A -> B -> C -> (R -> Void) -> Void, a : A, b : B, c : C) : Future<R> { return null; }
}
...
(replace cc with an appropriate naming)


Considering nodeJs brings two parameters; we may provide other signatures; and this time introduce the Either object...

class Fut1 {
  public static function cc < A, R > (f : A -> (Error -> R -> Void) -> Void, a : A) : Future<Either<Error, R>> { return null; }
}

..then, it starts to become interesting..



then the minimale definition of a monadic Future:

class Future<T> {
  static public function create<T>(x : T) : Future<T>  { return null;  }
  public function bind<U>(f : T -> Future<U>) : Future<U> { return null;  }
}


P.S.: There's as much Future implementations as one want to brings some concepts in it.
For instance; a good implementation of Future in Stax which also includes a cancelling behavior.
You can also find an interesting one I've done in Scala on my Blog (promise) which natively handles failures and ensure termination.
The interesting bits comes when you define an empty Future as you can bring some choice operator, which, in addition to timing make possible something like:

getDatas("...").before(100).orElse(getOtherDatas("..")) // self descriptive.. 

getDatas("...").before(100).or(getOtherDatas("..")) // not the same behavior.. (sometimes subtile)




On Sat, Oct 22, 2011 at 1:08 AM, Juraj Kirchheim [via Haxe] <[hidden email]> wrote:
On Fri, Oct 21, 2011 at 11:08 PM, sledorze <[hidden email]> wrote:
> Hi!
>
> I want to stress this idea to use the new extension mechanism we've
> discussed with Juraj and implemented as a macro for Js externs (at least).
>
> I think it could makes things a lot easier (better completion) and provide
> the ability something impossible today; to use others extensions at the same
> time.

This is definitely the right step towards simple JS-integration
without sacrificing haXe-awesomeness.
Hope some people will start using it, so there's some feedback from field tests.

> A good example is the mongodb signature; it has a lot of variant signatures
> in it, all those ending with some callbacks.
>
> A good pattern for certain usages is to be able to automatically transform a
> function finishing by a callback into a function returning a Future.

There's two things to consider:
1. Not every function is a callback (consider filter/map/reduce operations).
2. You might be shadowing the actual return value.

I think there's a solution to each:
1. Don't make this the default. Instead, if the return type is a
Future, assume the callback was there
2. Let the Future contain the return value

It would look something like this:

        interface Future < Data, Immediate > {
                function get(handler:Data->Dynamic):Immediate;
        }
        class SimpleFuture < Data, Immediate > implements Future <Data, Immediate> {
                public var immediate:Immediate;
                var d:Data;
                var isDone:Bool;
                var handlers:Array < Data->Dynamic > ;
                public function new() {
                        this.isDone = false;
                        this.handlers = new Array();
                }
                public function get(handler:Data->Dynamic):Immediate {
                        if (isDone) handler(d);
                        else handlers.push(handler);
                        return immediate;
                }
                public function done(data:Data):Void {
                        if (isDone) throw 'assert';
                        isDone = true;
                        d = data;
                        for (handler in handlers)
                                handler(data);
                        handlers = null;
                }
        }

And then the following code:

      @:native(bar) function foo(a:A, b:B):Future<{ x:X, y:Y }, C>;

Will generate

        static public inline function foo(target:TargetType, a:A, b:B):Future
< { x:X, y:Y }, C > {
                var ret = new SimpleFuture< { x:X, y:Y }, C >();
                ret.immediate = untyped target.bar(a, b, function (x:X, y:Y):Void {
                        ret.done( { x:x, y:y } );
                });
                return ret;
        }

Which will be used as:

        myTargetTypeInstance.foo(someA, someB).get(function (data)
...).someMethodOfC()

I'm not sure whether wrapping up the arguments into an object is a
good idea. However it makes SimpleFuture in itself entirely type-safe.
No Reflect.callMethod things going on.

Anyway, great work so far :)

--
haXe - an open source web programming language
http://haxe.org



If you reply to this email, your message will be added to the discussion below:
http://haxe.1354130.n2.nabble.com/Js-extern-and-extension-mechanism-tp6918566p6918868.html
To unsubscribe from Js extern and extension mechanism., click here.



--
Stéphane Le Dorze


Reply | Threaded
Open this post in threaded view
|

Re: Js extern and extension mechanism.

sledorze
In reply to this post by Juraj Kirchheim
Sorry, forgot to write the (simplifid) usage, you to give a feel.. :

function retrieveInfo(user : User, cb : Data -> Void) : Void {
}

function reply(data : Data) {
}

coll.findUser.cc({fbuser : context.user.id}).flatMap(retrieveInfo.cc).foreach(reply)


(retrieveInfo.cc as type User -> Future<Data>)




On Sat, Oct 22, 2011 at 1:38 AM, Stephane Le Dorze <[hidden email]> wrote:
Hmmm.. I think we can go simpler by defining something like that once and foreall for last param functions.
 (return null; needs an implementation):

class Fut0 {
  public static function cc < R > (f : (R -> Void) -> Void) : Future<R> { return null; }
}
class Fut1 {
  public static function cc < A, R > (f : A -> (R -> Void) -> Void, a : A) : Future<R> { return null; }
}
class Fut2 {
  public static function cc < A, B, R > (f : A -> B -> (R -> Void) -> Void, a : A, b : B) : Future<R> { return null; }
}
class Fut3 {
  public static function cc < A, B, C, R> (f : A -> B -> C -> (R -> Void) -> Void, a : A, b : B, c : C) : Future<R> { return null; }
}
...
(replace cc with an appropriate naming)


Considering nodeJs brings two parameters; we may provide other signatures; and this time introduce the Either object...

class Fut1 {
  public static function cc < A, R > (f : A -> (Error -> R -> Void) -> Void, a : A) : Future<Either<Error, R>> { return null; }
}

..then, it starts to become interesting..



then the minimale definition of a monadic Future:

class Future<T> {
  static public function create<T>(x : T) : Future<T>  { return null;  }
  public function bind<U>(f : T -> Future<U>) : Future<U> { return null;  }
}


P.S.: There's as much Future implementations as one want to brings some concepts in it.
For instance; a good implementation of Future in Stax which also includes a cancelling behavior.
You can also find an interesting one I've done in Scala on my Blog (promise) which natively handles failures and ensure termination.
The interesting bits comes when you define an empty Future as you can bring some choice operator, which, in addition to timing make possible something like:

getDatas("...").before(100).orElse(getOtherDatas("..")) // self descriptive.. 

getDatas("...").before(100).or(getOtherDatas("..")) // not the same behavior.. (sometimes subtile)




On Sat, Oct 22, 2011 at 1:08 AM, Juraj Kirchheim [via Haxe] <[hidden email]> wrote:
On Fri, Oct 21, 2011 at 11:08 PM, sledorze <[hidden email]> wrote:
> Hi!
>
> I want to stress this idea to use the new extension mechanism we've
> discussed with Juraj and implemented as a macro for Js externs (at least).
>
> I think it could makes things a lot easier (better completion) and provide
> the ability something impossible today; to use others extensions at the same
> time.

This is definitely the right step towards simple JS-integration
without sacrificing haXe-awesomeness.
Hope some people will start using it, so there's some feedback from field tests.

> A good example is the mongodb signature; it has a lot of variant signatures
> in it, all those ending with some callbacks.
>
> A good pattern for certain usages is to be able to automatically transform a
> function finishing by a callback into a function returning a Future.

There's two things to consider:
1. Not every function is a callback (consider filter/map/reduce operations).
2. You might be shadowing the actual return value.

I think there's a solution to each:
1. Don't make this the default. Instead, if the return type is a
Future, assume the callback was there
2. Let the Future contain the return value

It would look something like this:

        interface Future < Data, Immediate > {
                function get(handler:Data->Dynamic):Immediate;
        }
        class SimpleFuture < Data, Immediate > implements Future <Data, Immediate> {
                public var immediate:Immediate;
                var d:Data;
                var isDone:Bool;
                var handlers:Array < Data->Dynamic > ;
                public function new() {
                        this.isDone = false;
                        this.handlers = new Array();
                }
                public function get(handler:Data->Dynamic):Immediate {
                        if (isDone) handler(d);
                        else handlers.push(handler);
                        return immediate;
                }
                public function done(data:Data):Void {
                        if (isDone) throw 'assert';
                        isDone = true;
                        d = data;
                        for (handler in handlers)
                                handler(data);
                        handlers = null;
                }
        }

And then the following code:

      @:native(bar) function foo(a:A, b:B):Future<{ x:X, y:Y }, C>;

Will generate

        static public inline function foo(target:TargetType, a:A, b:B):Future
< { x:X, y:Y }, C > {
                var ret = new SimpleFuture< { x:X, y:Y }, C >();
                ret.immediate = untyped target.bar(a, b, function (x:X, y:Y):Void {
                        ret.done( { x:x, y:y } );
                });
                return ret;
        }

Which will be used as:

        myTargetTypeInstance.foo(someA, someB).get(function (data)
...).someMethodOfC()

I'm not sure whether wrapping up the arguments into an object is a
good idea. However it makes SimpleFuture in itself entirely type-safe.
No Reflect.callMethod things going on.

Anyway, great work so far :)

--
haXe - an open source web programming language
http://haxe.org



If you reply to this email, your message will be added to the discussion below:
http://haxe.1354130.n2.nabble.com/Js-extern-and-extension-mechanism-tp6918566p6918868.html
To unsubscribe from Js extern and extension mechanism., click here.



--
Stéphane Le Dorze


Tel: <a href="tel:%2B33%20%280%29%206%2008%20%C2%A076%2070%2015" value="+33608767015" target="_blank">+33 (0) 6 08  76 70 15





--
Stéphane Le Dorze


Reply | Threaded
Open this post in threaded view
|

Re: Js extern and extension mechanism.

Justin Donaldson-3
In reply to this post by sledorze
I had a similar notion when using jquery callbacks. 

Also, remember that using works for methods.
You could also wrap arbitrary methods the same way so that they accept Future<T> versions of their T arguments.

class Wait0 {
  public static function wait <T> (f: (T->U)): (Future<T> ->Future<U>){
  ...
}

this means that with foo(x:String):Float could be easily turned into foo.wait(Future<String>): Future<Float>.  It's pretty easy to switch to futures, asyncs, etc. this way without having to write a lot of cps-style code, or chained methods.

I still think this functions as a workable async approach, in the absence of a compiler feature:
https://github.com/jdonaldson/sugar-async



-Justin

On Fri, Oct 21, 2011 at 4:38 PM, sledorze <[hidden email]> wrote:
Hmmm.. I think we can go simpler by defining something like that once and foreall for last param functions.
 (return null; needs an implementation):

class Fut0 {
  public static function cc < R > (f : (R -> Void) -> Void) : Future<R> { return null; }
}
class Fut1 {
  public static function cc < A, R > (f : A -> (R -> Void) -> Void, a : A) : Future<R> { return null; }
}
class Fut2 {
  public static function cc < A, B, R > (f : A -> B -> (R -> Void) -> Void, a : A, b : B) : Future<R> { return null; }
}
class Fut3 {
  public static function cc < A, B, C, R> (f : A -> B -> C -> (R -> Void) -> Void, a : A, b : B, c : C) : Future<R> { return null; }
}
...
(replace cc with an appropriate naming)


Considering nodeJs brings two parameters; we may provide other signatures; and this time introduce the Either object...

class Fut1 {
  public static function cc < A, R > (f : A -> (Error -> R -> Void) -> Void, a : A) : Future<Either<Error, R>> { return null; }
}

..then, it starts to become interesting..



then the minimale definition of a monadic Future:

class Future<T> {
  static public function create<T>(x : T) : Future<T>  { return null;  }
  public function bind<U>(f : T -> Future<U>) : Future<U> { return null;  }
}


P.S.: There's as much Future implementations as one want to brings some concepts in it.
For instance; a good implementation of Future in Stax which also includes a cancelling behavior.
You can also find an interesting one I've done in Scala on my Blog (promise) which natively handles failures and ensure termination.
The interesting bits comes when you define an empty Future as you can bring some choice operator, which, in addition to timing make possible something like:

getDatas("...").before(100).orElse(getOtherDatas("..")) // self descriptive.. 

getDatas("...").before(100).or(getOtherDatas("..")) // not the same behavior.. (sometimes subtile)




On Sat, Oct 22, 2011 at 1:08 AM, Juraj Kirchheim [via Haxe] <[hidden email]> wrote:
On Fri, Oct 21, 2011 at 11:08 PM, sledorze <[hidden email]> wrote:
> Hi!
>
> I want to stress this idea to use the new extension mechanism we've
> discussed with Juraj and implemented as a macro for Js externs (at least).
>
> I think it could makes things a lot easier (better completion) and provide
> the ability something impossible today; to use others extensions at the same
> time.

This is definitely the right step towards simple JS-integration
without sacrificing haXe-awesomeness.
Hope some people will start using it, so there's some feedback from field tests.

> A good example is the mongodb signature; it has a lot of variant signatures
> in it, all those ending with some callbacks.
>
> A good pattern for certain usages is to be able to automatically transform a
> function finishing by a callback into a function returning a Future.

There's two things to consider:
1. Not every function is a callback (consider filter/map/reduce operations).
2. You might be shadowing the actual return value.

I think there's a solution to each:
1. Don't make this the default. Instead, if the return type is a
Future, assume the callback was there
2. Let the Future contain the return value

It would look something like this:

        interface Future < Data, Immediate > {
                function get(handler:Data->Dynamic):Immediate;
        }
        class SimpleFuture < Data, Immediate > implements Future <Data, Immediate> {
                public var immediate:Immediate;
                var d:Data;
                var isDone:Bool;
                var handlers:Array < Data->Dynamic > ;
                public function new() {
                        this.isDone = false;
                        this.handlers = new Array();
                }
                public function get(handler:Data->Dynamic):Immediate {
                        if (isDone) handler(d);
                        else handlers.push(handler);
                        return immediate;
                }
                public function done(data:Data):Void {
                        if (isDone) throw 'assert';
                        isDone = true;
                        d = data;
                        for (handler in handlers)
                                handler(data);
                        handlers = null;
                }
        }

And then the following code:

      @:native(bar) function foo(a:A, b:B):Future<{ x:X, y:Y }, C>;

Will generate

        static public inline function foo(target:TargetType, a:A, b:B):Future
< { x:X, y:Y }, C > {
                var ret = new SimpleFuture< { x:X, y:Y }, C >();
                ret.immediate = untyped target.bar(a, b, function (x:X, y:Y):Void {
                        ret.done( { x:x, y:y } );
                });
                return ret;
        }

Which will be used as:

        myTargetTypeInstance.foo(someA, someB).get(function (data)
...).someMethodOfC()

I'm not sure whether wrapping up the arguments into an object is a
good idea. However it makes SimpleFuture in itself entirely type-safe.
No Reflect.callMethod things going on.

Anyway, great work so far :)

--
haXe - an open source web programming language
http://haxe.org



If you reply to this email, your message will be added to the discussion below:
http://haxe.1354130.n2.nabble.com/Js-extern-and-extension-mechanism-tp6918566p6918868.html
To unsubscribe from Js extern and extension mechanism., click here.



--
Stéphane Le Dorze


Tel: <a href="tel:%2B33%20%280%29%206%2008%20%C2%A076%2070%2015" value="+33608767015" target="_blank">+33 (0) 6 08  76 70 15




View this message in context: Re: Js extern and extension mechanism.
Sent from the Haxe mailing list archive at Nabble.com.

--
haXe - an open source web programming language
http://haxe.org


--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Js extern and extension mechanism.

Juraj Kirchheim
In reply to this post by sledorze
> then the minimale definition of a monadic Future:
> class Future<T> {
>   static public function create<T>(x : T) : Future<T>  { return null;  }
>   public function bind<U>(f : T -> Future<U>) : Future<U> { return null;  }
> }

As I explained, using this will shadow the actual return value.

Imagine following signature:

extern class DB {
     public function execute(query:Query, cb:Data->Void):DB;
}

You can't transform this into a call with a Future without loosing the
return value. My proposal for futures would allow that.

>
> P.S.: There's as much Future implementations as one want to brings some
> concepts in it.
> For instance; a good implementation of Future in Stax which also includes a
> cancelling behavior.
> You can also find an interesting one I've done in Scala on my Blog (promise)
> which natively handles failures and ensure termination.
> The interesting bits comes when you define an empty Future as you can bring
> some choice operator, which, in addition to timing make possible something
> like:
> getDatas("...").before(100).orElse(getOtherDatas("..")) // self
> descriptive..
> getDatas("...").before(100).or(getOtherDatas("..")) // not the same
> behavior.. (sometimes subtile)

Not sure what this means. Get data and timeout after 100 time units to
getOtherDatas?
I think the timeout behaviour needn't be implemented by the Future, as
long as it offers cancelation.
Assuming this:

       interface Future<T, S, I> {
              function bind(handler:T->Void):Future<T, S, I>;
              function source():S;
              function immediate():I;//assuming it is realistic that
the immediate result of a call that returns a future is anything else
than the source
              function cancel(?withDefault:T):Future<T, S, I>;
       }

You would use composition:

        class FutureTools {
                static public function timeout<T,S,I>(target:Future<T, S, I>,
msecs:Int, ?useDefault: Future<T,S,I>->T,
?orFinalize:Future<T,S,I>->Void):Future<T, S, I> {
                        target.bind(
                                function (_) {
                                        haxe.Timer.delay(function () {
                                                if (useDefault != null)
                                                        target.cancel(useDefault(target))
                                                else
                                                        target.cancel();
                                                if (orFinalize != null)
                                                        orFinalize(target);
                                        }, msecs).stop();
                                }
                        )
                }
        }

So with using FutureTools, it would look something like:

       mySource.someOp(foo, bar).bind(handleData).timeout(100,
function (_) return someDefault()).source().someOtherOp( ...
       //Or you just handle the the timeout:
       mySource.someOp(foo, bar).bind(handleData).timeout(100,
function (_) handleTheTimeout()).source().someOtherOp( ...

Also you shouldn't forget that haXe has enums. When the Future is
uncertain (;-)), i.e. you have multiple results, the cleanest option
is having the Future's data be of such a type:

       enum PossibleOutcome {
              Outcome1(they:Live, happily:EverAfter);
              Outcome2(theyGet:Kidnapped, by:Aliens);
              TotalFailure(for:Reason);
       }

Of course it is not clear how to generate code for that. So if this is
really necessary, one might need to refrain to a manual
implementation.

--
haXe - an open source web programming language
http://haxe.org
Reply | Threaded
Open this post in threaded view
|

Re: Js extern and extension mechanism.

sledorze
I agree it should not be shallowed, however thé future concept must remain orthogonal, the best should be to return a simple struct holding both the future and the value (like a tuple would do). Keeping it simpler..

Stephane

Sent from my iPhone

On 22 oct. 2011, at 11:04, "Juraj Kirchheim [via Haxe]" <[hidden email]> wrote:

> then the minimale definition of a monadic Future:
> class Future<T> {
>   static public function create<T>(x : T) : Future<T>  { return null;  }
>   public function bind<U>(f : T -> Future<U>) : Future<U> { return null;  }
> }

As I explained, using this will shadow the actual return value.

Imagine following signature:

extern class DB {
     public function execute(query:Query, cb:Data->Void):DB;
}

You can't transform this into a call with a Future without loosing the
return value. My proposal for futures would allow that.

>
> P.S.: There's as much Future implementations as one want to brings some
> concepts in it.
> For instance; a good implementation of Future in Stax which also includes a
> cancelling behavior.
> You can also find an interesting one I've done in Scala on my Blog (promise)
> which natively handles failures and ensure termination.
> The interesting bits comes when you define an empty Future as you can bring
> some choice operator, which, in addition to timing make possible something
> like:
> getDatas("...").before(100).orElse(getOtherDatas("..")) // self
> descriptive..
> getDatas("...").before(100).or(getOtherDatas("..")) // not the same
> behavior.. (sometimes subtile)
Not sure what this means. Get data and timeout after 100 time units to
getOtherDatas?
I think the timeout behaviour needn't be implemented by the Future, as
long as it offers cancelation.
Assuming this:

       interface Future<T, S, I> {
              function bind(handler:T->Void):Future<T, S, I>;
              function source():S;
              function immediate():I;//assuming it is realistic that
the immediate result of a call that returns a future is anything else
than the source
              function cancel(?withDefault:T):Future<T, S, I>;
       }

You would use composition:

        class FutureTools {
                static public function timeout<T,S,I>(target:Future<T, S, I>,
msecs:Int, ?useDefault: Future<T,S,I>->T,
?orFinalize:Future<T,S,I>->Void):Future<T, S, I> {
                        target.bind(
                                function (_) {
                                        haxe.Timer.delay(function () {
                                                if (useDefault != null)
                                                        target.cancel(useDefault(target))
                                                else
                                                        target.cancel();
                                                if (orFinalize != null)
                                                        orFinalize(target);
                                        }, msecs).stop();
                                }
                        )
                }
        }

So with using FutureTools, it would look something like:

       mySource.someOp(foo, bar).bind(handleData).timeout(100,
function (_) return someDefault()).source().someOtherOp( ...
       //Or you just handle the the timeout:
       mySource.someOp(foo, bar).bind(handleData).timeout(100,
function (_) handleTheTimeout()).source().someOtherOp( ...

Also you shouldn't forget that haXe has enums. When the Future is
uncertain (;-)), i.e. you have multiple results, the cleanest option
is having the Future's data be of such a type:

       enum PossibleOutcome {
              Outcome1(they:Live, happily:EverAfter);
              Outcome2(theyGet:Kidnapped, by:Aliens);
              TotalFailure(for:Reason);
       }

Of course it is not clear how to generate code for that. So if this is
really necessary, one might need to refrain to a manual
implementation.

--
haXe - an open source web programming language
http://haxe.org



If you reply to this email, your message will be added to the discussion below:
http://haxe.1354130.n2.nabble.com/Js-extern-and-extension-mechanism-tp6918566p6919682.html
To unsubscribe from Js extern and extension mechanism., click here.
Reply | Threaded
Open this post in threaded view
|

Re: Js extern and extension mechanism.

sledorze
In reply to this post by Juraj Kirchheim
Anyway, whatever the solution, it's another extern usage one can choose to use or not :)
That's what I like with externs; they compose! :)
Stéphane

P.S.:
I think our naming should be consistent between libraries and the best we can do is to be inspired by academic and existing foreign popular language libraries (that's why I am not a big fan of 'foreach' in the std lib which means something completely different in most of other language libraries..)
About naming, I am usually inspired by ML familly (Haskell) or Scala flavor..


On Sat, Oct 22, 2011 at 11:55 AM, Stephane Le Dorze <[hidden email]> wrote:
I agree it should not be shallowed, however thé future concept must remain orthogonal, the best should be to return a simple struct holding both the future and the value (like a tuple would do). Keeping it simpler..

Stephane

Sent from my iPhone

On 22 oct. 2011, at 11:04, "Juraj Kirchheim [via Haxe]" <[hidden email]> wrote:

> then the minimale definition of a monadic Future:
> class Future<T> {
>   static public function create<T>(x : T) : Future<T>  { return null;  }
>   public function bind<U>(f : T -> Future<U>) : Future<U> { return null;  }
> }

As I explained, using this will shadow the actual return value.

Imagine following signature:

extern class DB {
     public function execute(query:Query, cb:Data->Void):DB;
}

You can't transform this into a call with a Future without loosing the
return value. My proposal for futures would allow that.

>
> P.S.: There's as much Future implementations as one want to brings some
> concepts in it.
> For instance; a good implementation of Future in Stax which also includes a
> cancelling behavior.
> You can also find an interesting one I've done in Scala on my Blog (promise)
> which natively handles failures and ensure termination.
> The interesting bits comes when you define an empty Future as you can bring
> some choice operator, which, in addition to timing make possible something
> like:
> getDatas("...").before(100).orElse(getOtherDatas("..")) // self
> descriptive..
> getDatas("...").before(100).or(getOtherDatas("..")) // not the same
> behavior.. (sometimes subtile)
Not sure what this means. Get data and timeout after 100 time units to
getOtherDatas?
I think the timeout behaviour needn't be implemented by the Future, as
long as it offers cancelation.
Assuming this:

       interface Future<T, S, I> {
              function bind(handler:T->Void):Future<T, S, I>;
              function source():S;
              function immediate():I;//assuming it is realistic that
the immediate result of a call that returns a future is anything else
than the source
              function cancel(?withDefault:T):Future<T, S, I>;
       }

You would use composition:

        class FutureTools {
                static public function timeout<T,S,I>(target:Future<T, S, I>,
msecs:Int, ?useDefault: Future<T,S,I>->T,
?orFinalize:Future<T,S,I>->Void):Future<T, S, I> {
                        target.bind(
                                function (_) {
                                        haxe.Timer.delay(function () {
                                                if (useDefault != null)
                                                        target.cancel(useDefault(target))
                                                else
                                                        target.cancel();
                                                if (orFinalize != null)
                                                        orFinalize(target);
                                        }, msecs).stop();
                                }
                        )
                }
        }

So with using FutureTools, it would look something like:

       mySource.someOp(foo, bar).bind(handleData).timeout(100,
function (_) return someDefault()).source().someOtherOp( ...
       //Or you just handle the the timeout:
       mySource.someOp(foo, bar).bind(handleData).timeout(100,
function (_) handleTheTimeout()).source().someOtherOp( ...

Also you shouldn't forget that haXe has enums. When the Future is
uncertain (;-)), i.e. you have multiple results, the cleanest option
is having the Future's data be of such a type:

       enum PossibleOutcome {
              Outcome1(they:Live, happily:EverAfter);
              Outcome2(theyGet:Kidnapped, by:Aliens);
              TotalFailure(for:Reason);
       }

Of course it is not clear how to generate code for that. So if this is
really necessary, one might need to refrain to a manual
implementation.

--
haXe - an open source web programming language
http://haxe.org



If you reply to this email, your message will be added to the discussion below:
http://haxe.1354130.n2.nabble.com/Js-extern-and-extension-mechanism-tp6918566p6919682.html
To unsubscribe from Js extern and extension mechanism., click here.



--
Stéphane Le Dorze