Hi @Araq: That seems like a reasonable opinion about non-local macros being undesirable if they're modifying the code non-locally. But surely you don't have a complaint about non-local macros that are merely reading / iterating-over / introspecting a module?
In the base case, a module-importing operation is arguably "local" because it's the point through which the external module is introduced into this one. So it seems very justifiable to me for that module-importing operation to have iteration+introspection capabilities.
But even for a global macro invocation within the same module, surely iterating+introspecting in a controlled, read-only fashion over the global types, procs, etc., that have been defined prior to the macro's point of invocation (and thus, will affect the context at that point within the module) can't be a bad thing? This second example is of course what the macro initPyModule does at the end of a Nim module in Pymod.
I don't think there is such a thing called "iterating+introspecting in a controlled, read-only fashion":
proc foo = discard "can I modify foo? Who knows, there is a macro invocation following"
mymacro()
But even for a global macro invocation within the same module, surely iterating+introspecting in a controlled, read-only fashion over the global types, procs, etc., that have been defined prior to the macro's point of invocation (and thus, will affect the context at that point within the module) can't be a bad thing?
Surely it is a bad thing. The proper way to do it is to annotate what is affected by macros like so:
proc foo {.mymarker.} = ...
Rumors are that you can {.push mymarker.} but this needs to be documented.
@Araq What about getType() then? I believe what thatch45 wants is something like getType(), but for modules.
I understand that module scope is quite a bit different than a type definition, but surely this could work for already imported modules, and just return a sequence of types and procedures?
but surely this could work for already imported modules, and just return a sequence of types and procedures?
But it's not about what could work (or what would be easy to implement), but about what is wise to do.
Sorry to revoke such an old thread, but from my understanding it would be great if nim had something equivalent with python’s "dir()", "obj.__dict__", “type(obj)" etc.
Especially considering the great metaprogramming capabilities of this language, it's a shame that this level of reflection is missing.
This might work. Untested example:
import macros
import mymodule
echo repr(getImpl(mymodule))
It's bad because depending on how it's implemented it means I cannot rename private symbols to something else because thanks to introspection the name could have leaked into the outside world
that's easily solved by passing a param publicOnly and requiring an experimental flag for publicOnly=false
Just to sharpen the conversation, the "should" question is more whether we "should make that one thing easy". I suspect (but do not know) that "symbols are only the beginning". You can only tell so much from a name. People will soon after want metadata on symbols. Eg., procs can have many overloads. The ambitious and judicious folk can use parseStmt(whole file) for anything already.
In short, I tend to agree with @Krux02's final pre-close PR comment. Some more completely thought out API seems more prudent.
The idea that we "can't go up the tree" is such a fundamental assumption in the design of the language that I cannot fathom the extent of corruption weakening this spec would foment. You're talking about breaking assumptions about encapsulation and abstraction of the AST who-knows-where and who-knows-when.
Please, no thank you.
The ambitious and judicious folk can use parseStmt(whole file) for anything already.
that has been discussed elsewhere already, it doesn't work in many cases since you get a different (duplicate) symbol, not the original symbol; this breaks down when symbols have state (eg a threadvar inside a proc) and many other corner cases once you start using it more, which I've tried before moduleSymbols.
The idea that we "can't go up the tree" is such a fundamental assumption in the design of the language that I cannot fathom the extent of corruption weakening this spec would foment.
it's not going up the tree if you call moduleSymbols(myModule) from a module that imports myModule. And that's what --experimental flags are for.
The feature has real use cases (repl, interactive docs, etc) and works for me just fine in my fork.
Some more completely thought out API seems more prudent.
So then let's wait indefinitely? That's what --experimental flags are for.
I just think you would have an easier time with a more complete reflection API than just symbols (and that too should be --experimental). I don't have a specific counter proposal, but it's not my itch to scratch.
Furthermore, plenty of languages support this kind of introspection/reflection, and it's very useful for writing tools in those;
You know what could make this argument compelling? If you actually wrote and published some Nim tools that demonstrate the need. Why should the language change for a need that doesn't exist?