Relational Naming
Before moving on to coding, take a step back. After all, the idea in Prolog is to define relationships. Your name reverse_num/2 more likely to offer some action, num_reversed/2 might be a better name.
Define attitude
Your definition is not so bad, let me rewrite it to 1 :
num_reversed(Num, Reversed) :- number_chars(Num, Chars), reverse(Chars, Revchars), number_chars(Reversed, Revchars). ?- num_reversed(123,X). X = 321. ?- num_reversed(1230,X). X = 321. ?- num_reversed(12300,X). X = 321.
Do you see the template? All numbers N*10^I have the same result!
Now let me ask you more:
?- num_reversed(Num, 321). ERROR: number_chars/2: Arguments are not sufficiently instantiated
Hmm, what did we expect? In fact, we wanted to print all 123*10^I These are infinitely many solutions. Therefore, over the request, if he answered correctly, it will require infinitely many printing solutions. If we print them directly, it will take all the life of our universe and much more!
It is for this reason that Prolog creates a creation error instead. Thus, Prolog essentially states:
This goal is too general that I can give a good answer. Perhaps there are infinitely many solutions, maybe not. I dont know. But at least I point this out by issuing an error. To remove this error, you need to create some arguments.
So the Prologue response was not so bad! In fact, it is much better to make a pure mistake than, say, unsuccessfully. In general, Prolog errors are often a very useful hint for those semantic problems that you may encounter. See all error classes as.
Coroutining
Like the other suggested answers, coroutining using when/2 can solve this problem. However, the processing itself has many semantic problems. Not without reason systems such as XSB do not offer this because of the many problems associated with verification of jurisdiction. An implementation that would be compatible with it would be unexpectedly ineffective.
But for the sake of this, we could make our definition more universal by requesting it as
?- when(nonvar(Num), num_reversed(Num, Reversed)). when(nonvar(Num), num_reversed(Num, Reversed)).
Now we will return as an answer exactly to the request we requested. It is also known as floundering . Thus, there is a way to represent infinitely solvable solutions in a compact way! However, this comes at a fairly high price: you no longer know if a solution exists or not. Think:
?- when(nonvar(Num), num_reversed(Num, -1)). when(nonvar(Num), num_reversed(Num, -1)).
Others suggested waiting for
nonvar(Reversed) , which would be correct if we produced an infinitely many answers, but, as we saw, it takes too much time.
Corotting looked very promising in the early 80s. However, he never fell into the general programming methodology. Most of the time you get to flounder too much, which is just a pain and even more difficult to handle than, say, making mistakes.
However, a more promising descendant of this development is limitations. There mechanisms are much more clearly defined. For practical purposes, programmers will only use existing libraries such as CLPFD, CLPQ, or CHR. Implementing your own library is a completely non-trivial project. In fact, you can even provide an implementation of num_reversed/2 with library(clpfd) , that is, a restriction on the relationship to the integer case.
Mode dependent conditions
Traditionally, many such problems are resolved by explicitly checking for instances. It is a good style to do this exclusively with nonvar/1 and ground/1 as a condition in when/2 - other predicates of a type test are easily deduced for errors, an example of which is a different answer .
num_reversed(Num, Reversed) :- ( nonvar(Num) -> original_num_reversed(Num, Reversed) ; original_num_reversed(Reversed, Base), ( Base =:= 0 -> Num is 0 ; length(_, I), Num is Base*10^I ) ).
Above, the code very quickly breaks into floats using base 2 and a little later for base 10. Actually, with the classic base 2 it floats, the relation itself does not make much sense.
Regarding the definition of number_chars/2 , ISO / IEC 13211-1: 1995 has the following template and mode subheading :
8.16.7.2 Pattern and modes
number_chars(+number, ?character_list)
number_chars(-number, +character_list)
The first case is when the first argument is created (thus nonvar ). The second case is when the first argument is not created. In this case, a second argument must be created.
Please note, however, that due to very similar problems, number_chars/2 not a relation. As an example, Chs = ['0','0'], number_chars(0, Chs) succeeds, while number_chars(0, Chs), Chs = ['0','0'] does not work.
Very thin print
1 This rewrite is necessary because in many Prologs reverse/2 completes only if the first argument is known. And in SWI, this rewriting is necessary because of some particular inefficiency.