1

I am trying to develop a prolog procedure that will convert numbers in any given list to a list of their square roots, using the univ (=..). So far I have

convert(X,Y): number(X), Y is X^2.
use([],_,[]).
use([_|X],convert,L):-
           convert(X,Y),
           L =..[convert,X,Y].

This evaluates false, what could be wrong in my logic or execution?

coder
  • 12,832
  • 5
  • 39
  • 53
  • Typo: `convert(X,Y): number(X)...` --> `convert(X,Y) :- number(X)...`. Do you mean square roots or squares? Your code is doing squares. Why are you using `=../2`? It's purpose is to provide an equivalence between a term and a list. It's unclear how you think this would solve your problem. – lurker Jul 15 '17 at 13:10

2 Answers2

4

You could also use maplist/3 to define use/2 with convert/2 as defined in your post:

use(X,Y) :- maplist(convert, X, Y).

   ?- use([1,2,3],L).
L = [1,4,9]

Note that use/2 is simply failing for lists that contain anything but numbers:

   ?- use([1,2,3,a],L).
no
coder
  • 12,832
  • 5
  • 39
  • 53
tas
  • 8,100
  • 3
  • 14
  • 22
  • 2
    That `convert/2`... succeeds for `convert(X, 2)` with `X = 2`, but fails for `X = 2, convert(X, 2)`. – false Jul 16 '17 at 07:27
  • @false: Thanks for pointing it out. That detail totally slipped my attention. I removed the faulty code. – tas Jul 17 '17 at 09:09
  • 2
    See [this](https://stackoverflow.com/questions/27306453/safer-type-tests-in-prolog) for a source of inspiration! – false Jul 17 '17 at 14:29
2

There are multiple errors:

  • why passing the name of the predicate convert/2?
  • Most important I see no recursive call!!
  • You ignore head element of the list by writing [_|X] which means a list with a head element and a tail X.
  • You try to use convert on X which is a list and assign the atom convert(X,Y) to L. Note that prolog is not a procedural language, convert(X,Y) will work only by just calling convert(X,Y) and the result will be in Y, you can't make assignments like: L = convert(X,Y) this will only assign the atom convert(X,Y) to L.

You don't need the operator =.., as a simple solution would be:

convert(X,Y):- number(X), Y is X^2.
use([],[]).
use([H|T],[Y|T1]):-
           convert(H,Y),
           use(T,T1).
coder
  • 12,832
  • 5
  • 39
  • 53