# Why is prolog\_load\_context with user:file\_search\_path done this way?

**URL:** <https://swi-prolog.discourse.group/t/why-is-prolog-load-context-with-user-file-search-path-done-this-way/5543>\
**Category:** Predicate\
**Created:** [June 22, 2022, 10:11am UTC](https://swi-prolog.discourse.group/t/why-is-prolog-load-context-with-user-file-search-path-done-this-way/5543 "2022-06-22T10:11:13Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [June 22, 2022, 10:11am UTC](https://swi-prolog.discourse.group/t/why-is-prolog-load-context-with-user-file-search-path-done-this-way/5543/1 "2022-06-22T10:11:13Z")

</div>

In this code example in the SWI-Prolog documentation ([ref](https://www.swi-prolog.org/pldoc/man?section=projectpaths))

```prolog
:- prolog_load_context(directory, Dir),
   asserta(user:file_search_path(myapp, Dir)).

```

was thinking that it should instead work as

```prolog
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](https://www.swi-prolog.org/pldoc/man?section=progtransform) 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](https://github.com/SWI-Prolog/swipl-devel/blob/770879e9d5a230472437b44d480d891540996b49/boot/syspred.pl#L431-L433))

```prolog
prolog_load_context(directory, D) :-
    input_file(F),
    file_directory_name(F, D).

```

([ref](https://github.com/SWI-Prolog/swipl-devel/blob/770879e9d5a230472437b44d480d891540996b49/boot/syspred.pl#L462-L468))

```prolog
input_file(File) :-
    ( system:'$load_input'(_, Stream)
    -> stream_property(Stream, file_name(File))
    ),
    !.
input_file(File) :-
    source_location(File, _).

```

with `$load_input` being [asserted](https://www.swi-prolog.org/pldoc/man?predicate=asserta/2) and [volatile](https://www.swi-prolog.org/pldoc/man?predicate=volatile/1)

([ref](https://github.com/SWI-Prolog/swipl-devel/blob/ed23b935e0e33232699f8481556db37920bfd3bb/boot/init.pl#L1791-L1808))

```prolog
:- 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](https://github.com/SWI-Prolog/swipl-devel/blob/ed23b935e0e33232699f8481556db37920bfd3bb/boot/init.pl#L1821-L1832))

```prolog
'$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.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [June 22, 2022, 10:38am UTC](https://swi-prolog.discourse.group/t/why-is-prolog-load-context-with-user-file-search-path-done-this-way/5543/2 "2022-06-22T10:38:54Z")

</div>

> [@EricGT](#):
>
> So if Jan W. can just confirm that this line of reasoning is correct it would be nice to know.

This is how it works. prolog\_load\_context/2 comes from Quintus and is mostly needed for term/goal expansion, in particular to find locations, target module, etc.

There is another way to refer to the directory of a source file:

```prolog
dummy.

user:file_search_path(myapp, Dir) :-
    source_file(dummy, File),
    file_directory_name(File, Dir).

```

Usually you have other predicates defined in the file and you can pick any of them instead of `dummy`.
