File Paths in Prolog

Here’s the translation of the Go code to Prolog, with explanations in Markdown format suitable for Hugo:

% The filepath module provides predicates to parse and construct file paths
% in a way that is portable between operating systems.

% Import necessary modules
:- use_module(library(filesex)).
:- use_module(library(lists)).

main :-
    % join/2 should be used to construct paths in a portable way.
    % It takes a list of path components and constructs a hierarchical path.
    atomic_list_concat(['dir1', 'dir2', 'filename'], '/', P),
    format('p: ~w~n', [P]),

    % You should always use join/2 instead of concatenating
    % separators manually. It will also normalize paths by
    % removing superfluous separators and directory changes.
    atomic_list_concat(['dir1//', 'filename'], '/', Path1),
    format('~w~n', [Path1]),
    atomic_list_concat(['dir1/../dir1', 'filename'], '/', Path2),
    format('~w~n', [Path2]),

    % directory_file_path/3 can be used to split a path to the
    % directory and the file.
    directory_file_path(Dir, _, P),
    format('Dir(p): ~w~n', [Dir]),
    directory_file_path(_, Base, P),
    format('Base(p): ~w~n', [Base]),

    % We can check whether a path is absolute.
    (absolute_file_name('dir/file', _, [file_type(directory), solutions(all)])
     -> format('~w~n', [true])
     ;  format('~w~n', [false])),
    (absolute_file_name('/dir/file', _, [file_type(directory), solutions(all)])
     -> format('~w~n', [true])
     ;  format('~w~n', [false])),

    Filename = 'config.json',

    % Some file names have extensions following a dot.
    % We can split the extension out of such names with file_name_extension/3.
    file_name_extension(Name, Ext, Filename),
    format('.~w~n', [Ext]),

    % To find the file's name with the extension removed,
    % we can use the Name from file_name_extension/3.
    format('~w~n', [Name]),

    % relative_file_name/3 finds a relative path between a base and a target.
    % It fails if the target cannot be made relative to base.
    (relative_file_name('a/b/t/file', 'a/b', Rel1)
     -> format('~w~n', [Rel1])
     ;  format('Failed to find relative path~n', [])),

    (relative_file_name('a/c/t/file', 'a/b', Rel2)
     -> format('~w~n', [Rel2])
     ;  format('Failed to find relative path~n', [])).

To run this Prolog program, you would typically save it to a file (e.g., file_paths.pl) and then consult it in a Prolog interpreter:

$ swipl -s file_paths.pl -g main -t halt
p: dir1/dir2/filename
dir1/filename
dir1/filename
Dir(p): dir1/dir2
Base(p): filename
false
true
.json
config
t/file
../c/t/file

This example demonstrates how to work with file paths in Prolog, using predicates from the filesex library. The atomic_list_concat/3 predicate is used to join path components, similar to the filepath.Join function in Go. The directory_file_path/3 predicate is used to split paths into directory and file components.

The absolute_file_name/3 predicate is used to check if a path is absolute, and file_name_extension/3 is used to work with file extensions. Finally, relative_file_name/3 is used to find relative paths between two locations.

Note that Prolog doesn’t have built-in functions for all the operations shown in the Go example, so some adaptations were made to achieve similar functionality using available Prolog predicates.