-
Notifications
You must be signed in to change notification settings - Fork 151
Document module qualification #2959
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
base: master
Are you sure you want to change the base?
Conversation
This is a very subtle part of the language and was omitted from #2030 (native builtins missing documentation). Heck, I'm not even sure whether it's correct to call it a "procedure", a "control construct" or something else entirely. It's also confusing to me where the definition of Please review this carefully for correctness. |
Reject |
Please recommend alternate documentation for this language feature. I may not have done it justice but it's important enough to document. |
@triska, @UWN, could you please re-review. I put this in builtins by analogy with #2265. But maybe it belongs in For background, SICStus documents the
|
@UWN Could you try and be a little more constructive and less passive aggressive? To any one watching this repository it just looks extremely hostile to contribute. |
Please refer to the past useless conversations. That is just trolling. |
Thank you for saying something. That's the way it feels sometimes.
There have been plenty of conversations which may seem useless to you but I've learned much from (including many I have not been a participant in but read after the fact!). I've tried to be as humble as possible, even though learning Prolog is extremely frustrating. If it's not worth your time to explain why you oppose my wording, then please write your own version of this PR so we can all learn. |
I'm against "trivial" documentations. Like is commonly found in different kinds of projects: "This is a constructor. It constructs an object" – it is just silly. Also users should not be encouraged in any way to use :- meta_predicate(goal_qualified_2(2,-)).
goal_qualified_2(G_2, G_2). IMHO bad documentation is worse then no documentation. For example I have couple of years of experience with Prolog and I'm not qualified (pun intended) to write a good documentation for how module system works – but I've spent quite a while reading it. Just adding comments here and there doesn't help the project. There are plenty of other issues that must be fixed. |
@hurufu Then maybe I agree that trivial documentation is bad. Documenting a symbol in searchable words, or a language feature not elsewhere documented is not trivial. |
I'm not understanding. How would you use your meta-predicate to write the equivalent of Even if |
It depends on why do you need it and what do you want to do with your qualified predicates. Here is one way of doing it. Utilities module (file :- module(q, [goal_qualified_1/2]).
:- meta_predicate(goal_qualified_1(1,-)).
goal_qualified_1(G_1, G_1). Let's say you have two modules :- module(a, [a_foo/1]).
:- use_module(q).
foo(42).
a_foo(Foo) :-
goal_qualified_1(foo, Foo). :- module(b, [b_foo/1]).
:- use_module(q).
foo(hello).
b_foo(Foo) :-
goal_qualified_1(foo, Foo). Finally in the main program: :- use_module(a).
:- use_module(b).
run([A,B]) :-
a_foo(AFoo),
b_foo(BFoo),
call(AFoo, A),
call(BFoo, B). Call this program:
|
...
This is a clean approach when one needs to refer to a predicate in an entirely different context, like when using attributed variables. But to resolve a name clash it seems better to add just interface modules that perform the renaming directly. |
Just for completeness and for future reference – usage example of interface predicates (at least my understanding): Modules Next add two more renaming modules: :- module(renamed_a, [a_foo/1]).
:- use_module(a).
a_foo(X) :- foo(X). :- module(renamed_b, [b_foo/1]).
:- use_module(b).
b_foo(X) :- foo(X). You can then import
The main benefit is that renamed predicates behave as regular predicates, they don't have strange functor BONUS: You can merge clauses – this can be useful in knowledge bases. Just define facade module: :- module(m, [foo/1]).
:- use_module(renamed_a).
:- use_module(renamed_b).
foo(A) :- a_foo(A).
foo(A) :- b_foo(A). Example query:
UPDATE: Obviously I know about discontiguous and multifile predicates, this is here just an example. |
Modifying the original module to rename the predicates apart or introducing new intermediate modules does not replace the use of
:- module(q, [goal_qualified_1/2]).
:- meta_predicate(goal_qualified_1(1,-)).
goal_qualified_1(G_1, G_1).
% ...
:- module(a, [a_foo/1]).
a_foo(Foo) :-
goal_qualified_1(foo, Foo).
% ...
a_foo(AFoo), In this example, It's also probably a corner-case for now, but also Wrapping a predicate with helper modules seems needlessly indirect. Contrast: :- module(renamed_a, [a_foo/1]).
:- use_module(a).
a_foo(X) :- foo(X).
% ...
:- module(renamed_b, [b_foo/1]).
:- use_module(b).
b_foo(X) :- foo(X).
% ...
:- module(m, [foo/1]).
:- use_module(renamed_a).
:- use_module(renamed_b).
foo(X) :- a_foo(X).
foo(X) :- b_foo(X). Versus explicit qualification in the consuming module: :- module(m, [foo/1]).
:- use_module(a). % note: for some reason this breaks with use_module(a, [])
:- use_module(b).
a_foo(X) :- a:call(foo(X)).
b_foo(X) :- b:call(foo(X)).
foo(X) :- a_foo(X).
foo(X) :- b_foo(X). Or just qualifying the predicate without intermediaries: :- module(m, [foo/1]).
:- use_module(a). % note: for some reason this breaks with use_module(a, [])
:- use_module(b).
foo(X) :- a:foo(X).
foo(X) :- b:foo(X). |
Have you tried your code? Does it work? UPDATE: Another question do really think adding module names has any merit? Consider C++ language they (C++ programmers) almost universally use explicit namespaces like For me using namespaces (aka explicit module names) should be rarely the case, and shall be used only to avoid name clash or in some special cases. Regardless of the language. |
In Prolog predicates such a |
@hurufu, the advantage of using extra intermediary modules for renaming shows when the predicates to be renamed have a meta_predicate declaration. With explicit qualification, the meta-arguments would inherit that explicit qualification. |
Oops! No, something weird is going on. It should work but for some reason, the explicit Stranger still,
True. But (1) that's done for meta-arguments (2) there is lots of opportunity here for optimization. I expect in most cases, the qualifying module will be known at compile time and can be inlined.
Yes, I think module names have tons of merit. I'd rather see the Another place where explicit module qualification can be useful is helper predicates (especially with dcgs for some complex grammars). Even if these are usually encapsulated inside some well-defined interface, it makes sense to module-qualify for unit testing. |
I don't know where else to document :/2 and I don't understand it well enough, but someone's gotta do it.