Skip to content

Document listing/1 #2929

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

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft

Document listing/1 #2929

wants to merge 3 commits into from

Conversation

rotu
Copy link
Contributor

@rotu rotu commented Apr 30, 2025

fix #2923

@triska
Copy link
Contributor

triska commented Apr 30, 2025

Thank you a lot for working on this!

I think an important point to state in the documentation is that the predicate must be public so that its body can be inspected at all. One way to make a predicate public is to declare it as dynamic, using the dynamic/1 directive.

rotu added 2 commits April 30, 2025 14:20
Clarify what happens if no clauses
make it more obvious that pred must be "dynamic"
Copy link

@UWN UWN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A predicate without clauses that has been declared as dynamic must not fail in listing. That is the behavior in SICStus.

Also note that author intends to "apply Cunnigham's law" that is to produce incorrect answers on purpose!

@rotu
Copy link
Contributor Author

rotu commented May 13, 2025

A predicate without clauses that has been declared as dynamic must not fail in listing. That is the behavior in SICStus.

That’s what the current predicate does so I was documenting per implementation.

It would indeed be a good idea to align the behavior with other systems. I think that, e.g. SWI prints a message for private procedures.

edit: I misremembered. SWI succeeds but shows a comment-like message for procedures implemented in native code. I'm not sure if SWI even has private procedures.

?- listing(writeq/1).
%   Foreign: system:writeq/1

true.

I don't love this, but it seems better than an error if you try to list a whole module that re-exports a private procedure.

Also note that author intends to "apply Cunnigham's law" that is to produce incorrect answers on purpose!

Believe me, I’m quite good at being wrong without trying to!

@rotu
Copy link
Contributor Author

rotu commented May 13, 2025

A predicate without clauses that has been declared as dynamic must not fail in listing. That is the behavior in SICStus.

I can't find this in the SICStus documentation and don't have a license to try it myself.

What's the behavior in SICStus's listing/1 so I can correct the implementation and the documentation?

  • When given a PI that does not name a procedure, does it fail silently (like scryer) or with an error (like SWI)?
  • With a dynamic procedure with no clauses, does it print anything or just succeed silently?

@rotu
Copy link
Contributor Author

rotu commented May 15, 2025

@triska, @UWN I'm blocked on how to proceed. How should I fix the behavior? Or should I leave the no-clauses case undocumented?

@triska
Copy link
Contributor

triska commented May 15, 2025

You can get a free evaluation licence of SICStus!

A predicate that fails can be easily emitted as Head :- false..

@rotu
Copy link
Contributor Author

rotu commented May 15, 2025

A predicate that fails is similar but not identical to a predicate with no clauses.
Should listing/1 print such a "virtual" clause, a comment, or nothing when there truly are no clauses?

@rotu
Copy link
Contributor Author

rotu commented May 16, 2025

It seems that, on SICStus, the behavior is substantially different. It doesn't print anything for a dynamic predicate with no clauses, and even succeeds when called on a built-in predicate!

| ?- listing(foo/0). 
yes
| ?- listing(true/0).
* listing(user:true/0) - no matching predicate
yes

A predicate without clauses that has been declared as dynamic must not fail in listing. That is the behavior in SICStus.

Expecting the behavior of SICStus seems to be setting yourself up for disappointment.

@UWN
Copy link

UWN commented May 16, 2025

Many errors are issued in SICStus via messages. That is warnings. That's what you got. Scryer is more restrictive issuing directly errors.

@rotu
Copy link
Contributor Author

rotu commented May 16, 2025

Many errors are issued in SICStus via messages. That is warnings. That's what you got. Scryer is more restrictive issuing directly errors.

If I'm understanding correctly, the purpose of listing/1 seems to be either:

  • (a) interactively, to help a human understand whatever it can about a given procedure
  • (b) to convert the procedure to a form that can be fed into another database at a later time

@triska, @UWN, which is closer to the vision you have in mind for what listing/1 should be?

These use cases imply different, conflicting behaviors and I think that's why this method NEEDS documentation. I'll be happy to rewrite the procedure and the documentation to match.

@hurufu
Copy link
Contributor

hurufu commented May 20, 2025

IMHO listing/1 documentation should also include goal and term expansion into consideration and how it affects the output.

For example:

:- dynamic(a/2).
a --> "a".

And then the query:

?- listing(a/2).
a(A,B) :-
   A=[a|B].
   true.

@rotu
Copy link
Contributor Author

rotu commented May 21, 2025

@hurufu Don't quote me on this, but I think the intent is to be able to declare such a nonterminal with :- dynamic(a//0) and query it with listing(a//0) though currently this produces the identical output as listing(a/2).

Anyway, what's your desired output (even if it might be impossible to make happen at this time)?

Current output:

a(A,B) :-
   A=[a|B].
   true.

1:

a --> "a".

2:

a(A,B) :-
   A=[a|B].

% expanded from:
% a --> "a".

3:

a --> "a".

% expands to:
% a(A,B) :-
%    A=[a|B].
%    true.

Would you expect to see the :- dynamic(...), :- metapredicate(...) etc. declarations in the printed output as well?

@hurufu
Copy link
Contributor

hurufu commented May 21, 2025

@rotu I would vote for 1st variant, but my comment wasn't about expected behavior, but about that listing/1 documentation should contain a note that current implementation reports clauses after goal and term expansions, so that novices wouldn't get surprised when using DCG or CLPZ.

@rotu rotu marked this pull request as draft May 21, 2025 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Document listing/1
4 participants