Returning a value from a future computation

88 views
Skip to first unread message

vin...@gmail.com

unread,
Apr 27, 2021, 8:47:53 PM4/27/21
to VAST Community Forum

Hi

Here is an attempt to get a value from a future computation:

| a |
p := (EsPromise async future then: [ a := 5 factorial ]) complete: nil.

(Delay forSeconds: 5) wait.
p isComplete and: [ a isNil ]

The whole thing evaluates to true so a is nil. How do I get a value from a future computation?

Vince

vin...@gmail.com

unread,
Apr 27, 2021, 8:53:04 PM4/27/21
to VAST Community Forum
This works as expected:

| a |

[ a := 5 factorial ] fork.
(Delay forSeconds: 5) wait.
a

So then next questions is, what are the recommendations around when to use Futures and Promises, and when to just stick to forks and callbacks?

Vince

Seth Berman

unread,
Apr 27, 2021, 9:27:46 PM4/27/21
to VAST Community Forum
Hi Vince,

Futures
A Future represents the completion of a computation.
computeFactorial := EsFuture on: [5 factorial].

You then chain together more tasks using #then:
Maybe in this example, after you have computed a factorial, then add 3 to the result.
computedFactorialPlus3 := computeFactorial then: [:factorial | factorial + 3].

You can keep going on and on, chaining together futures for complicated workflows, which is a heck of a lot nicer than lots of forks, semaphores and callback hell...especially when it involves exception handling.
Even more advanced usage such as the EsFuture class>>all: and EsFuture class>>any: is worth trying out.

Exception handling is another big win with the async framework.
There are also equivalents to the ensure: [] block as well.
Try the following.
future := EsFuture on: [Exception signal: 'Uh-oh'].
handledEx := future then: ["I never make it here"] catch: [:ex :st | ex inspect. st inspect].
complete := handledEx ensure: [Transcript show: 'I have finished'].

It's generally frowned on to add synchronous code to these workflows.  That is why in Dart (from which this EsFuture/EsPromise framework was ported) it has no analog to blocking on waiting for a future completion.
However, I found it was necessary in the VAST environment, so I added it.  You can add #waitFor to any future, and the current smalltalk process will block until its completed and answer the completion result of the future.
[complete waitFor.]

Promises
Promises are a great way to take synchronous code and create an asynchronous interface to it.  Its usually used by the implementor side of the house.
In fact, I recently did an async version of SstHttpClient by subclassing it and using promises to create an async interface that returned futures and didnt' block.

| future promise |
promise := EsPromise new.
future := promise future.
future then: [:number | number inspect].
promise complete: 42.

The big win from these frameworks are with I/O.
When network and disk I/O is in involved, the asynchronous framework can help make your code dramatically more efficient.
The examples shown above don't really do it justice, but they are just simple examples.
A nicer example might do something like wrap an SstHttpClient fetch with it.
Something like
(EsFuture on: [SstHttpClient fetch: 'https://www.instantiations.com'])
     then: [:response | response inspect]

Be sure to read the method and class comments carefully.  I tried to bring all the commenting over from Dart, and made the necessary
Smalltalk changes.

Let me know what other specific questions you have beyond these and I'll try and help.  It is getting a little late for me so I was trying to keep it short for tonight:)

- Seth

Seth Berman

unread,
Jul 7, 2021, 10:33:15 AM7/7/21
to VAST Community Forum
Hello,

Just a quick follow up on this thread since there is now a recorded video primarily focused on the value and usage of Futures and Promises in VAST.

VAST Platform Technology Demo: 2021 and Beyond
Speaker: Mariano Martinez Peck, Senior Software Engineer at Instantiations

- Seth
Reply all
Reply to author
Forward
0 new messages