String Functions in Prolog

Our example demonstrates various string operations in Prolog. Prolog doesn’t have a built-in string type, but it uses atoms or lists of characters to represent strings. We’ll use both representations in this example.

% Define a predicate to print with a label
print_labeled(Label, Value) :-
    write(Label), write(': '), write(Value), nl.

% Main predicate to demonstrate string operations
string_operations :-
    % Contains (sub_atom/5)
    (sub_atom(test, _, _, _, es) -> Contains = true ; Contains = false),
    print_labeled('Contains  ', Contains),

    % Count (count occurrences of a character in an atom)
    atom_chars(test, Chars),
    include(=(t), Chars, TChars),
    length(TChars, Count),
    print_labeled('Count     ', Count),

    % HasPrefix (sub_atom/5)
    (sub_atom(test, 0, 2, _, te) -> HasPrefix = true ; HasPrefix = false),
    print_labeled('HasPrefix ', HasPrefix),

    % HasSuffix (sub_atom/5)
    atom_length(test, Len),
    SuffixStart is Len - 2,
    (sub_atom(test, SuffixStart, 2, 0, st) -> HasSuffix = true ; HasSuffix = false),
    print_labeled('HasSuffix ', HasSuffix),

    % Index (sub_atom/5)
    sub_atom(test, Index, 1, _, e),
    print_labeled('Index     ', Index),

    % Join (atomic_list_concat/3)
    atomic_list_concat([a, b], '-', Joined),
    print_labeled('Join      ', Joined),

    % Repeat (replicate/3 from library(lists))
    length(RepeatedList, 5),
    maplist(=(a), RepeatedList),
    atom_chars(Repeated, RepeatedList),
    print_labeled('Repeat    ', Repeated),

    % Replace (atom_chars/2 and substitute/4 from library(lists))
    atom_chars(foo, FooChars),
    substitute(o, 0, FooChars, Replaced1Chars),
    atom_chars(Replaced1, Replaced1Chars),
    print_labeled('Replace   ', Replaced1),

    substitute(o, 0, FooChars, [_|Replaced2Chars], 1),
    atom_chars(Replaced2, [F|Replaced2Chars]),
    print_labeled('Replace   ', Replaced2),

    % Split (atomic_list_concat/3)
    atomic_list_concat(Split, '-', 'a-b-c-d-e'),
    print_labeled('Split     ', Split),

    % ToLower (downcase_atom/2)
    downcase_atom('TEST', ToLower),
    print_labeled('ToLower   ', ToLower),

    % ToUpper (upcase_atom/2)
    upcase_atom(test, ToUpper),
    print_labeled('ToUpper   ', ToUpper).

% Helper predicate to substitute elements in a list
substitute(_, _, [], []).
substitute(O, R, [O|T], [R|T2]) :- substitute(O, R, T, T2).
substitute(O, R, [H|T], [H|T2]) :- H \= O, substitute(O, R, T, T2).

% Helper predicate to substitute with a limit
substitute(_, _, L, L, 0).
substitute(O, R, [O|T], [R|T2], N) :- N > 0, N1 is N - 1, substitute(O, R, T, T2, N1).
substitute(O, R, [H|T], [H|T2], N) :- H \= O, substitute(O, R, T, T2, N).

To run this program, you would typically save it in a file (e.g., string_operations.pl) and then consult it in a Prolog interpreter. Here’s how you might run it:

?- [string_operations].
?- string_operations.
Contains  : true
Count     : 2
HasPrefix : true
HasSuffix : true
Index     : 1
Join      : a-b
Repeat    : aaaaa
Replace   : f00
Replace   : f0o
Split     : [a,b,c,d,e]
ToLower   : test
ToUpper   : TEST
true.

This example demonstrates various string operations in Prolog. Note that Prolog’s approach to string manipulation is quite different from imperative languages. It often involves working with atoms or lists of characters, and using predicates to perform operations. The atomic_list_concat/3 predicate is particularly useful for joining and splitting strings.

Some operations, like case conversion, are straightforward with built-in predicates. Others, like finding substrings or replacing characters, require more complex predicates or custom implementations.

Remember that Prolog is a logic programming language, so these operations are implemented as logical relations rather than functions in the traditional sense.