Futures, in Scale (was: Re: Embeddable Smalltalk (was: Re: Behold Pharo: The Modern Smalltalk))

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Futures, in Scale (was: Re: Embeddable Smalltalk (was: Re: Behold Pharo: The Modern Smalltalk))

Herby Vojčík
Hi,

I have looked at Scale b/c of different question, and I see it uses futures.

I'd like to ask if those futures are one-off, or is there any consensus
on how futures should look like in Pharo. The reason I ask is b/c Amber
already has something like that - Promises, which do not use the native
JS API directly (though it is inspired), but do have an API of their
own; and since those concepts seems to be similar (or maybe are the
same, just called differently), if the API used shouldn't be sort-of
standardized / used the same way in all occasions.

Herby

P.S.: Including state-of-the-art Promises.st from Amber master branch to
get a picture:

Smalltalk createPackage: 'Kernel-Promises'!
Object subclass: #Promise
        instanceVariableNames: ''
        package: 'Kernel-Promises'!

!Promise class methodsFor: 'composites'!

all: aCollection
"Returns a Promise resolved with results of sub-promises."
<inlineJS: 'return Promise.all($recv(aCollection)._asArray())'>
!

any: aCollection
"Returns a Promise resolved with first result of sub-promises."
<inlineJS: 'return Promise.race($recv(aCollection)._asArray())'>
! !

!Promise class methodsFor: 'instance creation'!

forBlock: aBlock
"Returns a Promise that is resolved with the value of aBlock,
and rejected if error happens while evaluating aBlock."
        ^ self new then: aBlock
!

new
"Returns a dumb Promise resolved with nil."
<inlineJS: 'return Promise.resolve()'>
!

new: aBlock
"Returns a Promise that is eventually resolved or rejected.
Pass a block that is called with one argument, model.
You should call model value: ... to resolve the promise
and model signal: ... to reject the promise.
If error happens during run of the block,
promise is rejected with that error as well."
<inlineJS: 'return new Promise(function (resolve, reject) {
     var model = {value: resolve, signal: reject};
     aBlock._value_(model);
})'>
!

signal: anObject
"Returns a Promise rejected with anObject."
<inlineJS: 'return $recv(anObject)._in_(function (x) {return
Promise.reject(x)})'>
!

value: anObject
"Returns a Promise resolved with anObject."
<inlineJS: 'return $recv(anObject)._in_(function (x) {return
Promise.resolve(x)})'>
! !

Trait named: #TThenable
        package: 'Kernel-Promises'!

!TThenable methodsFor: 'promises'!

catch: aBlock
<inlineJS: 'return self.then(null, function (err) {return
$core.seamless(function () {
     return aBlock._value_(err);
})})'>
!

on: aClass do: aBlock
<inlineJS: 'return self.then(null, function (err) {return
$core.seamless(function () {
     if (err._isKindOf_(aClass)) return aBlock._value_(err);
     else throw err;
})})'>
!

on: aClass do: aBlock catch: anotherBlock
        ^ (self on: aClass do: aBlock) catch: anotherBlock
!

then: aBlockOrArray
"Accepts a block or array of blocks.
Each of blocks in the array or the singleton one is
used in .then call to a promise, to accept a result
and transform it to the result for the next one.
In case a block has more than one argument
and result is an array, first n-1 elements of the array
are put into additional arguments beyond the first.
The first argument always contains the result as-is."
<inlineJS: '
var array = Array.isArray(aBlockOrArray) ? aBlockOrArray : [aBlockOrArray];
return array.reduce(function (soFar, aBlock) {
     return soFar.then(typeof aBlock === "function" && aBlock.length > 1 ?
         function (result) {return $core.seamless(function () {
             if (Array.isArray(result)) {
                 return
aBlock._valueWithPossibleArguments_([result].concat(result.slice(0,
aBlock.length-1)));
             } else {
                 return aBlock._value_(result);
             }
         })} :
         function (result) {return $core.seamless(function () {
             return aBlock._value_(result);
         })}
     );
}, self)'>
!

then: aBlockOrArray catch: anotherBlock
        ^ (self then: aBlockOrArray) catch: anotherBlock
!

then: aBlockOrArray on: aClass do: aBlock
        ^ (self then: aBlockOrArray) on: aClass do: aBlock
!

then: aBlockOrArray on: aClass do: aBlock catch: anotherBlock
        ^ ((self then: aBlockOrArray) on: aClass do: aBlock) catch: anotherBlock
! !

Promise setTraitComposition: {TThenable} asTraitComposition!
! !



[hidden email] wrote:

> https://github.com/guillep/Scale <https://github.com/guillep/Scale> is
> quite cool for quick scripts on *nix.
>
> Now for embeddable, yes it would help. Bootstrapping will be helpful but
> the current main issue is the VM interpret loop that is in the current VMs.
>
> It is not an intrinsic problem. Telepharo is also a great step to enable
> that to exist.
>
> Phil
>
> On Oct 7, 2017 13:05, "Herby Vojčík" <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     Ben Coman wrote:
>
>         Nice article. I like the way you've structured it and pushed the
>         "updated" angle.
>
>         I feel a bit too strong a claim is laid on Pharo producing the
>         CogVM.
>         Much of the Cog + Spur + 64bit VM work was originally done for
>         Squeak
>         with Pharo riding the coat-tails of that work.  Lately Pharo
>         community
>         has been involved in improving VM with hotspot optimisation with
>         Sista
>         and moving towards making Pharo embeddable.. (@Clement, is "hotspot
>
>
>     Hi, this made me curious. I always had the problem with Amber (and,
>     all the rest of Smalltalks in similar vein) that it is hard to use
>     to one-off scripting, as it presumes existence of the not really
>     small class library (objects, classes, collections, etc.). This
>     disadvantaged it IMO in the field of "can I just embed it here and
>     script it with a few lines?" scenarios.
>
>     Did you (the Pharo community that is "moving towards making Pharo
>     embeddable") find some way to work this around?
>
>         cheers -ben
>
>
>     Herby
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Futures, in Scale (was: Re: Embeddable Smalltalk (was: Re: Behold Pharo: The Modern Smalltalk))

Guillermo Polito
Hi Herby,

Scale does not implement futures by itself. It uses the ones implemented in taskit:


On Sat, Oct 7, 2017 at 2:22 PM, Herby Vojčík <[hidden email]> wrote:
Hi,

I have looked at Scale b/c of different question, and I see it uses futures.

I'd like to ask if those futures are one-off, or is there any consensus on how futures should look like in Pharo. The reason I ask is b/c Amber already has something like that - Promises, which do not use the native JS API directly (though it is inspired), but do have an API of their own; and since those concepts seems to be similar (or maybe are the same, just called differently), if the API used shouldn't be sort-of standardized / used the same way in all occasions.

Herby

P.S.: Including state-of-the-art Promises.st from Amber master branch to get a picture:

Smalltalk createPackage: 'Kernel-Promises'!
Object subclass: #Promise
        instanceVariableNames: ''
        package: 'Kernel-Promises'!

!Promise class methodsFor: 'composites'!

all: aCollection
"Returns a Promise resolved with results of sub-promises."
<inlineJS: 'return Promise.all($recv(aCollection)._asArray())'>
!

any: aCollection
"Returns a Promise resolved with first result of sub-promises."
<inlineJS: 'return Promise.race($recv(aCollection)._asArray())'>
! !

!Promise class methodsFor: 'instance creation'!

forBlock: aBlock
"Returns a Promise that is resolved with the value of aBlock,
and rejected if error happens while evaluating aBlock."
        ^ self new then: aBlock
!

new
"Returns a dumb Promise resolved with nil."
<inlineJS: 'return Promise.resolve()'>
!

new: aBlock
"Returns a Promise that is eventually resolved or rejected.
Pass a block that is called with one argument, model.
You should call model value: ... to resolve the promise
and model signal: ... to reject the promise.
If error happens during run of the block,
promise is rejected with that error as well."
<inlineJS: 'return new Promise(function (resolve, reject) {
    var model = {value: resolve, signal: reject};
    aBlock._value_(model);
})'>
!

signal: anObject
"Returns a Promise rejected with anObject."
<inlineJS: 'return $recv(anObject)._in_(function (x) {return Promise.reject(x)})'>
!

value: anObject
"Returns a Promise resolved with anObject."
<inlineJS: 'return $recv(anObject)._in_(function (x) {return Promise.resolve(x)})'>
! !

Trait named: #TThenable
        package: 'Kernel-Promises'!

!TThenable methodsFor: 'promises'!

catch: aBlock
<inlineJS: 'return self.then(null, function (err) {return $core.seamless(function () {
    return aBlock._value_(err);
})})'>
!

on: aClass do: aBlock
<inlineJS: 'return self.then(null, function (err) {return $core.seamless(function () {
    if (err._isKindOf_(aClass)) return aBlock._value_(err);
    else throw err;
})})'>
!

on: aClass do: aBlock catch: anotherBlock
        ^ (self on: aClass do: aBlock) catch: anotherBlock
!

then: aBlockOrArray
"Accepts a block or array of blocks.
Each of blocks in the array or the singleton one is
used in .then call to a promise, to accept a result
and transform it to the result for the next one.
In case a block has more than one argument
and result is an array, first n-1 elements of the array
are put into additional arguments beyond the first.
The first argument always contains the result as-is."
<inlineJS: '
var array = Array.isArray(aBlockOrArray) ? aBlockOrArray : [aBlockOrArray];
return array.reduce(function (soFar, aBlock) {
    return soFar.then(typeof aBlock === "function" && aBlock.length > 1 ?
        function (result) {return $core.seamless(function () {
            if (Array.isArray(result)) {
                return aBlock._valueWithPossibleArguments_([result].concat(result.slice(0, aBlock.length-1)));
            } else {
                return aBlock._value_(result);
            }
        })} :
        function (result) {return $core.seamless(function () {
            return aBlock._value_(result);
        })}
    );
}, self)'>
!

then: aBlockOrArray catch: anotherBlock
        ^ (self then: aBlockOrArray) catch: anotherBlock
!

then: aBlockOrArray on: aClass do: aBlock
        ^ (self then: aBlockOrArray) on: aClass do: aBlock
!

then: aBlockOrArray on: aClass do: aBlock catch: anotherBlock
        ^ ((self then: aBlockOrArray) on: aClass do: aBlock) catch: anotherBlock
! !

Promise setTraitComposition: {TThenable} asTraitComposition!
! !



[hidden email] wrote:
https://github.com/guillep/Scale <https://github.com/guillep/Scale> is
quite cool for quick scripts on *nix.

Now for embeddable, yes it would help. Bootstrapping will be helpful but
the current main issue is the VM interpret loop that is in the current VMs.

It is not an intrinsic problem. Telepharo is also a great step to enable
that to exist.

Phil

On Oct 7, 2017 13:05, "Herby Vojčík" <[hidden email]
<mailto:[hidden email]>> wrote:

    Ben Coman wrote:

        Nice article. I like the way you've structured it and pushed the
        "updated" angle.

        I feel a bit too strong a claim is laid on Pharo producing the
        CogVM.
        Much of the Cog + Spur + 64bit VM work was originally done for
        Squeak
        with Pharo riding the coat-tails of that work.  Lately Pharo
        community
        has been involved in improving VM with hotspot optimisation with
        Sista
        and moving towards making Pharo embeddable.. (@Clement, is "hotspot


    Hi, this made me curious. I always had the problem with Amber (and,
    all the rest of Smalltalks in similar vein) that it is hard to use
    to one-off scripting, as it presumes existence of the not really
    small class library (objects, classes, collections, etc.). This
    disadvantaged it IMO in the field of "can I just embed it here and
    script it with a few lines?" scenarios.

    Did you (the Pharo community that is "moving towards making Pharo
    embeddable") find some way to work this around?

        cheers -ben


    Herby







--

   

Guille Polito

Research Engineer

Centre de Recherche en Informatique, Signal et Automatique de Lille

CRIStAL - UMR 9189

French National Center for Scientific Research - http://www.cnrs.fr


Web: http://guillep.github.io

Phone: +33 06 52 70 66 13