Prolog convert list of string to list of numbers

Viewed 853

I'm new at Prolog and want to convert a list of string numbers to a list of numbers. I would appreciate an explanation, as I'm struggling with list operations in this language.

Here is what I've got so far (recursively):

convert([], 0). # This is meant to be the simplest case, if there are no elements left in the list.
convert([H|T], L) :- # This is meant to be executed if there are elements in the list.
   string_to_atom(H, Elm), # Built in function from [here][1].
   convert([T|_],L1). # The recursive call to the tail T. Unsure about how to call this.

Thanks in advance!

Edit: link to string_to_atom function: https://www.swi-prolog.org/pldoc/man?predicate=string_to_atom/2

4 Answers

You really shouldn't need to do the recursion manually. Use maplist. And there is number_string/2 in SWI-Prolog that works both ways. So:

?- maplist(number_string, Numbers, ["1", "-2.0", "0.3e-2"]).
Numbers = [1, -2.0, 0.003].

The explanation is that number_string/2 works both ways: string to number, or a number to a string. See the docs. And maplist is what you can use to apply a predicate (like number_string/2) to lists, without doing the recursion yourself. Otherwise, you'd have to write:

numbers_strings([], []).
numbers_strings([N|Ns], [S|Ss]) :-
    number_string(N, S),
    numbers_string(Ns, Ss).

You were nearly there! Note that the character for comments is %, not #

convert(Xs, Ys) is the predicate establishing a relation between Xs and Ys, such that when there are elements in Xs, then the head element H is relation with Elm, where string_to_atom(H, Elm). So Elm is the atom equivalent of H.

convert([], []). % there are no elements in list Xs
convert([H|Ts], [Elm|Es]) :- % This is meant to be executed if there are elements in the list.
   string_to_atom(H, Elm), % Built in function from [here][1].
   convert(Ts, Es). % The recursive call to the tail T

You should read carefully the explanations for standard predicates like append/2. They give you the proper way to reason with relations.

There are a couple of problems here in this example. I have posted a solution below that way be doing what you want.

  1. Lines are commented in SWI prolog with %. The posted code did not compile with my version.
  2. L, L1 and Elm are Singletons, which usually points to an error. You are expressing the program as a logic expression, and the interpreter is not going to be able to assume any connection between them. In the solution below, I combined L and Elm to a combined list in the resulting term.
  3. H is always an element, and T is a list. T can therefore not be in front of '|', but can be used as a list by itself.
  4. The "type" of convert is different in both facts, as you are using a list and a number in the different cases.
    convert([ ], [ ]). 
    convert([H|T], [Elm|L]) :- string_to_atom(H, Elm), convert(T,L). 
    % call with
    % ?- convert(["a","b","c"],L).
    % L=[a, b, c].

You can try:

stringtonum(A,Y):-
    atom_number(A,K),
    number_codes(K,X1),
    maplist(plus(48),Y,X1).


?-stringtonum("1234",L)
L = [1,2,3,4]

?-stringtonum("548765456",P).
L = [5, 4, 8, 7, 6, 5, 4, 5, 6]
Related