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
Mirrors: Provide synchronous equivalents to async APIs #4633
Comments
There is a lot to say about this issue. a. I expect Dart's support for asynchronous programming to evolve so that it is considerably less onerous. That said, the async version will never be as easy as the synchronous one. b. We are trying to keep the async parts to a minimum. Once you get an object, you can introspect synchronously on its code. Almost all of the planned mirror builder API is synchronous. c. It is a goal (admittedly ambitious) to make reflective code work cross-isolate. There are just too many examples of tools that would be very useful in a distributed setting, but were designed without distribution in mind. We'd like the norm for Dart reflective tools to be cross-isolate. So, before we admit defeat (and before the API is even complete) we'd like to stick to the plan. If, when all is said and done, we find that it is still too painful to handle local reflection, we can always give up then - and we may; I'm not saying that we shall never surrender. However, we shouldn't surrender prematurely. Set owner to @gbracha. |
This comment was originally written by pr...@gmail.com Appreciate your comments Gilad. Regarding item 'c'. I certainly agree with the potential benefits of cross-isolate reflection. My argument is (admittedly more based on intuition than data) that the majority of the reflection-usage scenarios will remain within the same isolate context, and so a synchronous peer of the async API would seem quite useful. And certainly: Don't give up! :) |
Removed Type-Defect label. |
This comment was originally written by gp7...@gmail.com Hi, I miss synchronous mirror operations as well. And I do not understand why the ambition of the Dart team to use only the asynchronous variants could be a reason to leave out the synchronous variants which have their own use cases. For now my solution looks like this: The while loop is just silly and might be technically inefficient.
|
This comment was originally written by ladicek@gmail.com gp789...: The while loop is not only silly, it also can't possibly work. Never ever. Just don't do that. The reason why it looks like it's working is that mirrors are synchronous right now, so the loop body is actually never reached. The reason why it won't work once mirrors become asynchronous is that async code in Dart doesn't necessarily mean parallel code. You will fire a request to the mirror library and continue in your own code. Once your code will give up, event handlers for completed events will be called. But you will never give up, as you just entered an infinite loop. Seriously, infinite loop is always terrible idea, but it's even more terrible in Dart where code can't be interrupted by other code. |
This comment was originally written by gp78...@gmail.com Ladislav, thank for your comment and explanation. Unfortunately I do not understand your objection. |
This comment was originally written by gp789654...@gmail.com So you mean that the system passes the single thread to my loop code and never switches back to the "invoke" method ? I hope the Dart team does think about such cases when implementing their thread scheduling. |
This comment was originally written by ladicek@gmail.com That's about right. It isn't exactly about thread scheduling, it's about doing async in one thread (because that is what actually happens -- there is no multithreading inside single isolate). Or, if you prefer, you can think about it as cooperative multitasking -- each "thread" has to give up sometimes so that other "threads" can work too -- except that here, "thread" doesn't mean real parallel thread, but rather a sequence of synchronously processed instructions, and "give up" actually means finishing the sequence to the end. |
This comment was originally written by gp7...@gmail.com I can understand that Javascript switches the task when the (event handler) code has finished. So there is no way to have synchronous mirror operations for now ? |
This comment was originally written by gp7...@gmail.com Well for now it works. But it is important to have an answer from Google that if things become asynchronous, that there will be synchronous variants. And for now I can not continue my work because of this issue. |
If we prevent the async version working synchronously in the same isolate, there are two possibilities: a. Code that relies on the synchronous behavior has to be revised to account for the possibility of asynchrony. We have not decided which of those paths to take. Each has advantages: (a) means that al reflective code works in a distributed setting. (b) means there is an easy path for code that only works in a single isolate. |
This comment was originally written by gp78965...@gmail.com Thank you for the response. For a simple implementation of an interpreter I was trying to make any use of Dart libraries via Mirrors. |
I don't think (a) can possibly work. Not every bit of code can magically work in a distributed setting. Things like evaluators/inspectors/debuggers need to be constructed intentionally, and they will no doubt want to use some degree of asynchrony. But there are a ton of use cases for reflection that need to be synchronous. By requiring async, it means mirrors will not be used in those scenarios, leaving Dart with less dynamic capabilities than many competing languages. |
This comment was originally written by Seth.Il...@gmail.com Agreed with the point that (a) cannot possibly work for everyday coding. An excellent example is JSONObject (https://github.com/chrisbu/dartwatch-JsonObject). This is very useful library, but since it uses reflection, it returns futures. This is highly undesirable for my codebase, and I would imagine many others. If only we had wait() or yield() in the language, we would get the best of both worlds, but that is a separate discussion, on a separate bug. |
John, Having returned to look at this issue recently, I'm inclined to agree. In the current state of play, using async methods in the mirror API spreads the async contagion to the API of the user, and so forth ad nauseum. This was not the case with the policies in place when we first designed the API. So I lean toward (b). It shouldn't be to hard to make that change, and worry about the remote reflection case later. We'lls ee what others think though. |
This comment was originally written by @chrisbu That's good to hear. I suspect that option b would cover a majority of use cases for reflection. |
This comment was originally written by @sethladd Very great to hear, thanks for reconsidering! |
This comment was originally written by greg...@gmail.com I recently bumped into this too. Here's my use case in case it helps: Assuming: class Person { Stream<Map<String, dynamic>> query(String sql) { ... } This is what I'd like to be able to do: query("select firstname, lastname from person") This is pretty simple when done synchronously: createMapper(Type type) { I started to write the async version of this, but gave up. I think you need to pause and restart the Stream for each event. |
This comment was originally written by LouisSt...@gmail.com Looks like there's been progress on this one :) https://code.google.com/p/dart/source/detail?r=21591 |
This issue was originally filed by prujohn...@gmail.com
Understanding from this thread
https://groups.google.com/a/dartlang.org/forum/#!topic/misc/AoaiQnCWD4w
that many of the instancing pieces of the current mirror API are asynchronous, because of the (requirement?) to provide cross-isolate reflection.
I would like to propose that there be synchronous equivalents to these APIs, where cross-isolate reflection is naturally restricted. This is based on the assumption that most reflective work will occur in the current isolate context. I am finding this to be true in my case, anyhow.
The future-based API works well (I have a branch of Buckshot that is building templates dynamically using it now: https://github.com/prujohn/Buckshot/blob/mirrors/lib/templates/XmlTemplateProvider.dart), but it introduces more overhead and complexity to the application control flow, and is more difficult to debug.
The text was updated successfully, but these errors were encountered: