Thanks Jan, also tested the problem reported in Text help fails in some cases, and it is solved.
Pushed a little more elegant solution that preserves this annotation.
Tested on my complete source, and seems good.
If my source has set_prolog_flag(autoload,false)
, and I turn autoload
on after loading it (and warn_autoload
is also set), I get this:
?- set_prolog_flag(autoload,true).
true.
?- help(transform_kythe_fact/2).
Warning: /home/peter/src/pykythe/pykythe/pykythe.pl:1151:
Warning: Auto-loading re_replace/4 from library(pcre) into module '$xref_tmp' is deprecated due to term- or goal-expansion
/home/peter/src/pykythe/pykythe/pykythe.pl
transform_kythe_fact(+Fact0, -Fact1) is det[private]
TODO: Note that this also changes fact_value to base64 and has special
cases for symtab, text, colors
true.
A quick search tells me this is causes by the cross-referencing module while trying to get (meta-)predicate properties. It is sure this is not desirable, but it is less clear what to do. Surely the cross referencer should remain silent. What about predicate_property/2 in general though? The idea behind the warning is that if a library defines public term/goal expansion, this may be necessary for proper operation and thus it is unsafe to call predicates from it using autoloading. Does that also apply to getting a predicate property?
Note that libraries that define some “predicate” using goal expansion also define the predicate itself. If it can only be used through the expansion, the implementation throws an error. In some cases, the expanded and runtime version have different semantics (library(yall)). This is rather undesirable. In most cases the runtime version is merely slower. Having a predicate though allows program analysis and documentation to work.
I’m not sure what predicate_property/2 should do in this situation. But library(pcre)
should have already been loaded by the use_module/2 directive, so there shouldn’t be any auto-loading warnings. Also, the error message (“into module ‘$xref_tmp’”) is confusing.
There seem to be bugs in predicate_property/2, and they occur whether library(pcre) is autoloaded or explicitly loaded with use_module/2:
imported_from
givesyall
instead ofpcre
line_count
seems wrong – and is it actually supposed to be the line number of the predicate, as the documentation says?size
seems wrongnumber_of_clauses
is wrong (I tested withpcre:split_range_regex/2
, which has two=>
clauses; I also tried user:goal_expansion/2, which also didn’t havemultifile
set)
Both line_count
and size
give the same result for all the predicates in library(pcre), whether they’re in Prolog or C.
?- forall(predicate_property(re_match/2, Z), writeln(Z)).
interpreted
visible
static
imported_from(yall)
transparent
meta_predicate? / 0
file(/home/peter/.local/lib/swipl/library/yall.pl)
line_count(275)
number_of_clauses(1)
number_of_rules(1)
last_modified_generation(5718)
defined
size(392)
true.
Peter, see the comment by @LogicalCapitain on the doc page.
You get library(yall) as a result because you’re asking for the predicate (/)/2, actually autoloaded from library(yall).
Great catch. This is a good example of how “types” as in other languages don’t really fit neatly in Prolog (I am referring to this discussion). More strict typing should catch such typos/thinkos, one would hope, but in fact both can be correct in some scenario. Same goes for syntactic sugar as discussed higher in the same thread.
But why is only re_replace/4 triggering this? There are a couple of meta-predicates in library(pcre), but re_replace/4 isn’t one of them.
Also, the goal expansion is only for re_match/2 and re_match/3, not re_replace/4 (and it’s controlled by a re_compile
flag).
(Goal expansion probably should be done for re_replace/4, as well as for most of the other predicates in the library.)
@jan – please point me to the code that’s doing the cross-referencing.
You get library(yall) as a result because you’re asking for the predicate (/)/2, actually autoloaded from library(yall).
This has bitten me in the past; but I had completely forgotten.
@jan – please point me to the code that’s doing the cross-referencing.
Check out library(prolog_xref). Search for xref_tmp
.
Also, the goal expansion is only for re_match/2 and re_match/3, not re_replace/4 (and it’s controlled by a
re_compile
flag).
The warning only checks that the library installs clauses for global expansion hooks. Not what they do. That is in general hard to figure out. For many of these libraries, some of the predicates work perfectly with autoloading and in most cases for the others the result should be merely slower. Sometimes much slower though
I think that the most elegant solution is for the autoloading by predicate_property/2 to ignore the warn_autoload
flag. The next question is “how”.
For the cross-referencer we want no such warnings anyway. Pushed a commit that silences these warnings of the xref
flag is set. This flag is set when cross-referencing a file and notably allows some expansions to not do their work when cross-referencing. This typically applies to “dirty” expansions that have side-effects.
This has bitten me in the past
Me too There is not much we can do though. Possibly yall should only be implemented using expansion. Then we still need the predicates for analysis and documentation though and (I guess) yall will stop working in interactive queries. So, not great either
Possibly yall should only be implemented using expansion
Possibly yall
shouldn’t be autoloaded.
[Although this will probably break some existing code …]
yall
defines expansions for >>
and /
, both of which have builtin meanings (in is/2). If I didn’t know about library(yall) and was reading some code that used these, I’d be very confused. If library(yall) required being explicitly loaded, that would be overall beneficial (IMHO, YMMV, etc.)
[Disclaimer: I’m from the “be explicit (with occasional exceptions to reduce verbosity)” school of large-scale programming, So, I don’t like C++ using-directives or Python import *
. Some people say "but a good IDE will help you read the code; but I don’t always have a good IDE available.]
Possibly
yall
shouldn’t be autoloaded.
Possibly. On the other hand, there are people who like using it at the toplevel. Of course, they can add it to their init.pl
>>
and/
, both of which have builtin meanings (in is/2).
As we have seen in another ongoing discussion, terms have different meaning in different contexts in Prolog. That may be confusing to new users. It also allows for a lot of nice things
Anyway, the plan is to first introduce the warn_autoload
flag defaulting to true
when this flag functions properly. After that we may consider to remove yall from the autoload list.
there are people who like using [yall] at the toplevel
use_module(library(yall))
works at the top level.
terms have different meaning in different contexts in Prolog
Indeed. I should have thought of trying help(/)
when I got the strange results from predicate_property(foo/2, P)
, but I didn’t. (Maybe predicate_property/2 can be “enhanced” to allow the foo/2
form of “head” that current_predicate/1 uses.)