My mess with modules and undefined predicates, I.e. current_directory/1

I’m using: SWI-Prolog version (threaded, 64 bits, version 7.6.4)

I want the code to: use the predicate current_directory/1

But what I’m getting is:
ERROR: Undefined procedure: file_systems:current_directory/1

My code (currently, after many experiments and changes) looks like this:

test :-
	file_systems:current_directory(CD),
	write(CD).

Some explanation: I keep getting errors of “undefined procedures” (if I remember correctly), in other words, the interpreter does not seem to find the definitions of the predicates I want to use.

It is quite probable that I am making a stupid systematic mistake I fail to see, but anyway, nothing seems to work. I have tried use_module(library(file_systems)), and got the message that this library cannot be found. I have tried the predicate with and without a module specifier in front. the whole code within and without a module itself, I have tried the same on two different computers. Nothing seems to work, and I am half expecting a hint towards a very stupid and embarrassing mistake on my side, given that I am not a beginner, but a SWIPL user of decades. So please, enlighten/embarrass me if you can. Thanks in advance!

It seems you want to list the files in the current directory.

The way to do that with SWI-Prolog is using directory_files/2.
The documentation for directory_files/2 shows

directory_files (+Directory, -Entries)

The + means the value for Directory must be ground upon calling.

The way to get the current current directory with SWI_Prolog is to use working_directory/2.
The documentation for working_directory/2 shows

working_directory (-Old, +New)

but the associated text

Unify Old with an absolute path to the current working directory and change working directory to New. Use the pattern working_directory(CWD, CWD) to get the current directory. See also absolute_file_name/2 and chdir/1.bug Note that the working directory is shared between all threads.

notes that working_directory(CWD, CWD) returns the current directory.


Here is example code demonstrating the predicates. The example shows that SWI-Prolog top level is started and then that the predicates are available without loading any modules.

Welcome to SWI-Prolog (threaded, 64 bits, version 8.3.26)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- working_directory(Directory,Directory).
Directory = 'c:/users/groot/documents/prolog/'.

?- working_directory(Directory,Directory),directory_files(Directory,Entries).
Directory = 'c:/users/groot/documents/prolog/',
Entries = ['.', ..].

HTH


EDIT

If you are using the Prolog top level and just want to quickly show the name of the current directory then pwd/0 works.

?- pwd.
% c:/users/groot/documents/prolog/
true.

Thanks for the hint! In fact I wanted to continue an old, half finished project, and it did not find a file. So I tried to get the current directory using the mentioned current_directory. Just tried out, working_directory works as described. So thank you, this is at least a workaround for noiw, but of course it would still be interesting in its own right what mistake I’ve made before.

If you watch carefully in the docs you can see that current_directory/1 is part of the SICStus Prolog emulation layer. Normally, do not use stuff from the emulation layers unless you want to write code that is compatible with the emulated dialect. 99% has a simple replacement. In any case, just using Module:Goal generally does not work. You need to use use_module/1,2 to load and import the module, after which you can simply call is as Goal.

I think the docs should make it more explicit that predicates come from an emulation layer (and which).

Thanks.

I initially could not find current_directory/1 but after reading your reply used the search feature of the SWI-Prolog documentation to find the predicate.

image

https://www.swi-prolog.org/search?for=current_directory

Ah, thanks, this makes at least clear why the direct call has not worked, and no, I do not require compatibility. So that settles a lot and works for me.

Just for completeness: I have tried the use_module approach, both with
use_module(library(file_systems))
and
use_module(file_systems),

none of them worked, the interpreter answered with

    source_sink `library(file_systems)' does not exist

and

    source_sink `file_systems' does not exist

respectively

I have used the following lines there:


:- module(moduletest, [test/0]).
:- use_module(library(file_systems)).

test :-
	current_directory(CD),
	write(CD).

(with and without 'library(..)')

Concerning the docmentation, from my experience I can agree that sometimes it is not immediately clear for me to determine where a predicate comes from. In this case, I have seen its origin library first from the URL of the help page. I might have seen it from the content list on the left side, too. Long term it would probably be better to keep that information and more about the origin closer to the text.

The correct way to do it would have been:

use_module(library(dialect/sicstus4/file_systems))

Admittedly this is also not immediately obvious from the docs.

1 Like

Thanks for this information. This settles the whole phenomenon. And yes, I agree - I was already wondering whether it would be a nested module name, but did not find indication thereof in the docs (or didn’t search thoroughly enough).