let%bs (err,arg1,arg2) = test {x = 1} a in
let%bs (err,arg1,arg2) as x (* give a name to the call back? *) = test2 { x= 3} b in
xx
Generated JS:
test({x:1}, a, function(err,arg1,arg2){
test2({x:3}, b, function x(err,arg1,arg2){
...
}
})
Note that we can also
Could this be a general purpose transform that runs with native code as well?
@jordwalke it's already generic isn't it? This is what it desugars to, in Reason:
[%bs
{
let (err, arg1, arg2) = test {x: 1} a;
[%bs
{
let (err, arg1, arg2) as x /* give a name to the call back? */ = test2 {x: 3} b;
xx
}
]
}
];
Though, once we've implemented prettier let sugar:
let%bs (err, arg1, arg2) = test {x: 1} a;
/* named */
let%bs (err, arg1, arg2) as x = test2 {x: 3} b;
xx;
This is a clever but probably misleading sugar. The return type of that last expression is really unit. You can't pass xx as a first-class thing. Not sure how I feel about it.
Yes, but names are important for stacktrace, maybe reason can have better syntax
note that it can be generalized into other use cases:
let%bs (match_,p1,p2) = str.replace [%re "/(x_*)|(-)/g"] in
...
let%bs (key,value) = JSON.parse {| { "p" : 6 } |} in
...
@chenglou I understand how it would easily work with Reason, but what I meant was: can it work with Reason non JS native code? What would the ppx compile to?
@bobzhang I meant the returned value isn't xx, but the previous function call. So you can't pass that around.
@jordwalke we can just stub this ppx right? It's an easy transform
Reason can provide a even better syntax, but we need this sugar for vanilla ocaml users too : )
[email protected] At: 02/15/17 01:34:04" data-digest="From: [email protected] At: 02/15/17 01:34:04" style="">
From: [email protected] At: 02/15/17 01:34:04
To: [email protected]
Cc: HONGBO ZHANG (BLOOMBERG/ 731 LEX), [email protected]
Subject: Re: [bloomberg/bucklescript] syntax sugar for NodeJS callback hell (#1214)
@bobzhang I meant the returned value isn't xx, but the previous function call. So you can't pass that around.
@jordwalke we can just stub this ppx right? It's an easy transform
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
@jordwalke this is suggested syntax for Reason, which looks pretty cool
await (err,arg0,arg1) = f {x : 1 };
Out of curiosity, how does this differ from the existing Lwt-like ppxs? let%bind ... = f x in ...
@hcarty see https://github.com/bloomberg/bucklescript/issues/1214#issuecomment-279929013
since let%bs foo = bar 1 in foo doesn't actually return foo (desugars bar: int => (fooType => unit) => unit), you can't pass foo around as a first-class thing. Plus, for better or worse, there's no memoization here:
let curried = bar 1
(* much later *)
let%bs result1 = bar 1 in result 1
(* much later *)
let%bs result2 = bar 1 in result 1
Promises would memoize the result. This sugar wouldn't.
Also, I'm not sure what the convenient cascading error handling here would be;
let%bs (result1, err) = baz 1 in
let%bs (result2, err) = qux 1 in
...
Seems easy to neglect errors? Under promises you can have a catch-all case somewhere else.
But then again, this sugar also doesn't need runtime support, or dragging in libraries (and understanding promises), or cost perf. I'm kinda torn
I did not know that promises memoize anything. That's kind of weird.
If you have a foo that you carry around and in one place you do foo.then bar and in another foo.then baz, it makes sense it should be memoized. It's not based on any parameter or whatever. It's the reference to that foo, which makes it less weird (you know what I mean?)
Another alternative syntax would be
let [] err0, a = readFile filename 'utf8' in
let [] err1, b = readDB xxx 'xx' in
let [] err2, c = push 'xx' in
let [] c = push 'x' (* in this case we insert error handling logic here *)
vs
let [@bs] err0, a = readFile filename 'utf8' in
let [@bs] err1, b = readDB xxx 'xx' in
let [@bs] err2, c = push 'xx'
match [@bs] promise with
| x0 -> .. (*Promise.then*)
| exception xx -> (*Promise.catch *)
Note that I am a fan of tweaking syntax, but given async is so important, shadowing some syntax maybe worthwhile, it would be nice that if we can override let[] like let! in F#
The classic await for loop can be expressed as below
async function forLoop(){
for (var i = 0; i < 100; ++i){
await sleep (100)
}
}
let rec forLoop i =
let [] () = sleep 100 in
forLoop (i+1)
the let [] is a cool hack, but finally I am convinced to use this(which will allow overriding)
let [@bs] v1 = promise1 in (* Monadic binding: default to promise *)
let [@bs] v2 = promise2 in
let [@bs Option] = promise3 in (* Monadic binding: now default to Option.bind *)
...
Using attribute instead of extension point allows us to customization for different monadic style or even NodeJS plain callback
closed as we settle down on #1326
I'm trying to wrap my head around how the following JS snippet will look like with the proposed syntax?
async function getUserInfo () {
const api = new Api()
const user = await api.getUser()
const friends = await api.getFriends(user.id)
const photo = await api.getPhoto(user.id)
return { user, friends, photo }
}
Most helpful comment
@jordwalke this is suggested syntax for Reason, which looks pretty cool