0

I am trying to create a deep binary predicate text/2 which will process a list and replace each number in a list by the atom number.

Example:

 ?- text([a,[[13]],b,14,c(5),8], Xs).
 Xs = [a,[[number]],b,number,c(5),number].

Solution:

I tried doing it as below but getting

Warning: Attempt to read past end of file in SGETTOK

The code is:

toNumber(In,number) :-
   number(In),
   !.
toNumber(In,In).

maplist(_,[],[]).
maplist(Pred,[InListHead|InListTail],[OutListHead|OutListTail]) :-
   Term = [Pred,InListHead,OutListHead],
   call(Term),
   maplist(Pred,InListHead,OutListHEad).

text(InListHead,OutListHead) :-
   maplist(toNumber,InListHead,OutListHead).
Nazgul
  • 83
  • 10

1 Answers1

-1

You could use the following:

text(List,New):-
  maplist(item_replace,List,New).

item_replace(Item,number):-
  number(Item).
item_replace(Item,Item).

Q:

?- text([a,[[13]],b,14,c(5),8], Xs).
Xs = [a, [[13]], b, number, c(5), number] .

This will backtrack to other answers you may not want though. So you could add a cut.

item_replace(Item,number):-
  number(Item),!.
item_replace(Item,Item).

or

item_replace(Item,number):-
  number(Item).
item_replace(Item,Item):-
  \+number(Item).

Another method trying to use some logical purity predicates..

is_number(L,T):-
  number(L)->
  T =true;T=false.

item_replace(Item,Number):-
  if_(is_number(Item),Number=number,Number=Item).

text_2(List,New):-
  maplist(item_replace,List,New).

Q:

?-text([a,[[13]],b,14,c(5),8], Xs).
Xs = [a, [[13]], b, number, c(5), number].
user27815
  • 4,767
  • 14
  • 28
  • 1
    The parts of your which uses cut (`(!)/0`) is not steadfast. Look again at this code snippet of yours: `item_replace(Item,number) :- number(Item), !. item_replace(Item,Item).` Then compare the following queries, their logical semantics, and the actual query result: ` ?- item_replace(1,number).` `?- item_replace(X,number).` `?- item_replace(1,1).` – repeat Oct 10 '15 at 18:08
  • For the 2nd definition consider `?- item_replace(X,Y).`. It gives the single answer `X = Y`. That don't look right to me. – repeat Oct 10 '15 at 18:16
  • 1
    Keeping the effect of meta-logical predicates as tightly contained as possible is a good thing! Dragging the `(!)/0` out and then placing it in the rule body of `text/2` right *after* the `maplist/3` goal **would** have been much, much worse... I feel you are progressing weĺl, keep it up and you'll go far. – repeat Oct 10 '15 at 18:28
  • 1
    `flatten/2` is bad. Using it safely in logically pure code is next to impossible. But..., why do you even need to `flatten`? The OP gave a sample query with expected results, which explicitly stated that the OP does **not** want deep traversal of arbitrary Prolog compounds, but only shallow traversal of a list: this is completely covered by [tag:meta-predicate] `maplist/3`. So... why flatten? – repeat Oct 10 '15 at 20:10
  • How do you make item_replace/2 deterministic? ` is_number(L,T):- number(L)-> T =true;T=false. item_replace(Item,number):- is_number(Item,true). item_replace(Item,Item):- is_number(Item,false).` – user27815 Oct 10 '15 at 20:25
  • Getting the implementation of `is_number/2` right is tricky business! It appears to me that you got the relevant part right. Let me summarize: `is_number/2` got its extra argument for holding reified truth value. `is_number/2` always succeeds deterministically with either `R=true` or with `R=false`, even though `number/1` can either succeed or fail. So far... so good! – repeat Oct 10 '15 at 20:26
  • To remove the unnecessary non-determinism, use `if_/3` in combination with the right reified test predicate. Want to know (a lot) more? cf http://stackoverflow.com/a/30291357/4609915 , http://stackoverflow.com/questions/27306453/safer-type-tests-in-prolog/30600104 , http://stackoverflow.com/questions/24017420/which-meanings-of-type-are-used-in-the-standard?lq=1 – repeat Oct 10 '15 at 20:41
  • Yeah I just got it.. taking a while to sink in :) – user27815 Oct 10 '15 at 20:42
  • Good stuff! A small problem remains that has to do with the arcane details of Prolog's procedural semantics regarding type test predicates like `number/1`. Taken as it is, `number/1` (and friends like `integer/1`) do **two** things in one step. First, they check for **instantiation** (like `nonvar/1`). Second, if the prior test passed, they check the concrete dynamic type. From a declarative point of view, the concrete order in which variables are instantiated during the execution of the Prolog program should never be able to flip the logical meaning of the program. – repeat Oct 10 '15 at 20:56
  • One piece is missing, there you are: `number_t(V,T) :- number(V), !, T = true. number_t(V,T) :- nonvar(V), !, T = false. number_t(V,true) :- freeze(V, number(V)). number_t(V,false) :- freeze(V,\+number(V)).` Consider `?- A = a,B=[[13]],C=b,D=14,E=c(5),F=8,text_2([A,B,C,D,E,F], Xs). Xs = [a,[[13]],b,number,c(5),number].` and `?- text_2([A,B,C,D,E,F], Xs), A = a,B=[[13]],C=b,D=14,E=c(5),F=8. Xs = [a,[[13]],b,number,c(5),number] ; false.` The older implementation for `number_t/2` committed too early; the first query has ok, but the 2nd one was logically unsound. May the force be with U. – repeat Oct 10 '15 at 21:06
  • The code is running perfect on SWI-prolog but , its not running successfully on NU-prolog..giving the previous error – Nazgul Oct 12 '15 at 07:31
  • 1
    Right now, all four implementations of `item_replace/2` lose logical soundness when arguments are not instantiated sufficiently. Why not use exceptions / coroutining for preserving declarative semantics? – repeat Oct 12 '15 at 08:05