Description
At the October TC39 f2f, I presented a newly added syntax: Module Functions
One core motivation for Module Blocks is providing a language-level primitive that unlocks patterns for parallelism, because JavaScript can’t (easily) adopt the shared memory parallelism model that most other languages utilize.
I did some research into the ergonomics and patterns of other languages and other platforms, and found that many use functions as their fundamental primitive. For example, here’s reactive programming in Swift on iOS and Kotlin on Android:
Observable<Int>.create {
// ...
}
.map { value -> value * 2 }
.observeOn(SerialDispatchQueueScheduler(qos: .background))
.map { value -> value * 3 }
.observeOn(MainScheduler.instance)
.subscribe(onNext: { element -> putOnScreen(element) })
.disposed(by: disposeBag)
userObservable
.subscribeOn(Schedulers.io())
.flatMap { users -> Observable.from(users) }
.observeOn(Schedulers.computation())
.map { it.name.length }
.distinct()
.observeOn(AndroidSchedulers.mainThread())
.subscribe { putOnScreen(it) }
While JavaScript shouldn’t be adopting other language’s idioms 1:1 due to the lack of shared memory, I want to enable similar patterns in JavaScript. If we use a RxJS-inspired observable syntax, I think it becomes clear that a full module syntax would be quite noisy for this use-case.
new Observable(subscriber => { /* ... */ })
.pipe(map(module {
export default function(value) {
return value * 2;
}
}))
.observeOn(Observable.Threads.backgroundThread)
.pipe(map(module {
// Arrow functions make it slightly better
export default value => value * 3;
}))
.observeOn(Observable.Threads.thisThread)
.subscribe(element => putOnScreen(element));
To allow JS to implement these patterns in a syntactically lightweight way, I added function short-hand to the proposal that merely acts as syntactic sugar.
new Observable(subscriber => { /* ... */ })
.pipe(map(module value => value * 2))
.observeOn(Observable.Threads.backgroundThread)
.pipe(map(module value => value * 3))
.observeOn(Observable.Threads.thisThread)
.subscribe(element => putOnScreen(element));
Thinking along Observables also made me revise my statement in a previous issue: I am not as confident anymore, that import-less module blocks would be that uncommon.
I feel like this is a very lightweight addition to the proposal that can make a lot of common patterns a lot easier to follow in JS.
Looking on input, so pinging some folks I know have opinions! @Jack-Works @domenic @nicolo-ribaudo @guybedford @leobalter