Pointers in Prolog

Our example demonstrates how Prolog handles references and modifications to data. In Prolog, we use logical variables and unification instead of pointers.

:- use_module(library(writef)).

% We'll show how Prolog handles data modification in contrast to 
% the original example's use of pointers. We'll use two predicates: 
% `zero_val` and `zero_ref`. `zero_val` takes a value and attempts 
% to unify it with 0, which won't affect the original value.

zero_val(0).

% `zero_ref` takes a mutable reference (using `nb_setarg`) which 
% allows us to modify the original data. This is somewhat analogous 
% to using a pointer in other languages.

zero_ref(Ref) :-
    nb_setarg(1, Ref, 0).

main :-
    I = 1,
    writef('initial: %w\n', [I]),

    % Attempting to unify I with 0 (which fails)
    (zero_val(I) -> true ; true),
    writef('zero_val: %w\n', [I]),

    % Creating a compound term to hold our mutable value
    Ref = ref(I),
    zero_ref(Ref),
    Ref = ref(NewI),
    writef('zero_ref: %w\n', [NewI]),

    % In Prolog, we don't have direct pointer equivalents, 
    % but we can show the internal reference of a term
    writef('reference: %w\n', [Ref]).

:- main.

To run this Prolog program:

$ swipl -q -t main -s pointers.pl
initial: 1
zero_val: 1
zero_ref: 0
reference: ref(0)

In this Prolog version, zero_val doesn’t change the I in main, but zero_ref does because it uses a mutable reference to modify the value. The concept of pointers is approximated using Prolog’s logical variables and compound terms with mutable arguments.

Note that Prolog’s approach to data and variables is fundamentally different from imperative languages. Variables in Prolog are logical entities that can be unified with values, rather than mutable storage locations. The use of nb_setarg for mutable state is generally discouraged in pure logical programming, but it’s used here to demonstrate a concept similar to pointer modification.