In this code example in the SWI-Prolog documentation (ref)
:- prolog_load_context(directory, Dir),
asserta(user:file_search_path(myapp, Dir)).
was thinking that it should instead work as
user:file_search_path(myapp, Dir) :-
prolog_load_context(directory, Dir).
In the first it is a directive (:-
) that gets the directory from prolog_load_context/2 and then uses asserta/1 to add the hook predicate user:file_search_path/2
with the alias myapp
.
However since user:file_search_path/2
is a hook that is typically called from absolute_file_name/2 then the second way should work. However in trying that in code if failed.
So looking into the predicates see in the documentation for prolog_load_context/2
Obtain context information during compilation.
which leads me to think that this predicate will only work correctly during the compiling. Now in Prolog when I think of what happens during compilation I naturally think of conditional compilation and program transformation so was expecting one of those in the call path when looking at the implementation of prolog_load_context/2 but in looking at the source code find.
(ref)
prolog_load_context(directory, D) :-
input_file(F),
file_directory_name(F, D).
(ref)
input_file(File) :-
( system:'$load_input'(_, Stream)
-> stream_property(Stream, file_name(File))
),
!.
input_file(File) :-
source_location(File, _).
with $load_input
being asserted and volatile
(ref)
:- thread_local
'$load_input'/2.
:- volatile
'$load_input'/2.
'$open_source'(stream(Id, In, Opts), In,
restore(In, StreamState, Id, Ref, Opts), Parents, _Options) :-
!,
'$context_type'(Parents, ContextType),
'$push_input_context'(ContextType),
'$prepare_load_stream'(In, Id, StreamState),
asserta('$load_input'(stream(Id), In), Ref).
'$open_source'(Path, In, close(In, Path, Ref), Parents, Options) :-
'$context_type'(Parents, ContextType),
'$push_input_context'(ContextType),
'$open_source'(Path, In, Options),
'$set_encoding'(In, Options),
asserta('$load_input'(Path, In), Ref).
with the asserted term being erased when closing the source
(ref)
'$close_source'(close(In, _Id, Ref), Message) :-
erase(Ref),
call_cleanup(
close(In),
'$pop_input_context'),
'$close_message'(Message).
'$close_source'(restore(In, StreamState, _Id, Ref, Opts), Message) :-
erase(Ref),
call_cleanup(
'$restore_load_stream'(In, StreamState, Opts),
'$pop_input_context'),
'$close_message'(Message).
thus the data for prolog_load_context/2 as noted in the documentation is only available when the code is being loaded and thus called with a Prolog directive.
So if Jan W. can just confirm that this line of reasoning is correct it would be nice to know. Then I have to add another concept to my long list of how SWI-Prolog really works.