-
Notifications
You must be signed in to change notification settings - Fork 30.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Macro brainstorming for Maybe<>/MaybeLocal<> #1872
Comments
You can with gcc and clang but I don't know about MSVC 2013, it's notoriously bad at inferring types. Easy to test though.
You can use I'd take the more explicit approach, like V8 does. |
Typically, get_foo_from_v8().then([](auto foo) {
// only gets executed if the maybe contains the value, doesn't get executed otherwise
}); However, that doesn't seem to fit very well with the code structure and probably has a performance penalty. The problem is that putting |
Macros that declare variables are usually clumsy, as they cannot, say, be used as rvalues. Real functional languages usually also offer pattern matching and lazy evaluation, which makes it easier to unwrap and to make functions accept maybe types as well as unwrapped ones. Here, writing a bunch of overloads for every possible Maybe-argument in every function is not that pleasant. While somewhat clumsy, the way things are is better than the possible alternatives. This stuff cannot really be papered over in a "good" way. |
Well, pointing out that most compilers (GCC, clang and MSVC) support and optimize (inline) lambdas, so it's possible to do: template< class T, class S >
MaybeLocal<S> bind_maybe(MaybeLocal<T>& maybe, std::function<MaybeLocal<S>(T)> fn) {
Local<Object> x;
if (!maybe.ToLocal(&x)) {
return MaybeLocal<T>();
}
// if we want sugar, we can also accept a function that returns an S and not a MaybeLocal<S>
// which would be similar to how promises allow returning both a promise or a value which
// gets wrapped.
return fn(x); // pass a reference instead of a value?
} Which would let you do: bind_maybe(get_foo_from_v8(), [](Local<Object> x){ // or auto x?
// do work on x, needs another overload for `void`
return someWorkOn(x);
}); |
Is this actually reasonable? If not, can we close? |
I think we first need to decide how we want to deal with these cases. Currently it's common to simply abort if something fails. e.g. if malloc fails. But now there's a way to propagate these types of issues, should we? It's also possible to remove all TryCatch. Basically we need more planning, but using macros to deal with the new API would be helpful. |
I think @benjamingr's idea is pretty neat, now that I know compilers inline those correctly. I would be interested in how much of an improvement it is in the real world. @benjamingr, if you have time, do you mind taking a Maybe-heavy function or two (node_contextify.cc has a few simple ones) and doing a before/after? |
@domenic sure but none of the functions in node_contextify (at least on master) have any Let's look at compiling, running a script and returning the result for example. Looking at auto maybe_context = magically_get_context();
auto source = magically_get_source_to_run();
Local<Context> context;
if (!maybe_context.ToLocal(&context)) {
return MaybeLocal<Value>();
}
auto maybe_script = Script::Compile(context, source);
Local<Script> script;
if (!maybe_script.ToLocal(&script)) {
return MaybeLocal<Value>();
}
return script->Run(); Which auto source = magically_get_source_to_run();
auto script = bind_maybe(magically_get_context(), [](Local<Context> ctx){
return Script::Compile(ctx, source);
});
return bind_maybe(script, [](Local<Script> script) { return script->Run(); }); The transition of a MaybeLocal to a MaybeLocal is in fact the transition all functional languages do. |
@benjamingr sorry, I meant on next... Anyway, that does look pretty nice. I'd be interested in a few more examples, and other contributors' opinions, but I'd be pretty happy. |
Hmm, that only contains a single use of |
https://github.com/nodejs/io.js/blob/next/src/node_contextify.cc#L350-L375 is kind of what I was thinking... https://github.com/nodejs/io.js/blob/next/src/node_contextify.cc#L392-L418 has stuff for |
Closing due to inactivity. |
Dealing with
Maybe<>
s andMaybeLocal<>
s in V8 4.3 are a pain, as I found out in #1773 and @trevnorris found out in #1825. This could maybe be made better with macros.Here is one proposal:
This would introduce a local variable
foo
of typeLocal<Object>
(and another onemaybe_foo
of typeMaybeLocal<Object>
) in the exact same way as the above code. Either the function will have returned, orfoo
will contain a non-emptyLocal<Object>
. I am 95% sure this is easy to write a macro for.Ideas/issues:
Object
part for us. Can it, perhaps using auto or decltype or something?Local<Object> foo = UN_MAYBE(get_foo_from_v8())
. Does anyone have good enough macro skills for that?void
, we'd need a return type too.has_pending_exception
throughout the code). Is there a good reason for that? Should we do something more like that?The text was updated successfully, but these errors were encountered: