Subject: Re: [SWIPL] About Applying a predicate to all the elements of a list

From: "Richard A. O'Keefe" <[email-masked]>
Date: Fri, 15 Dec 2000 13:55:33 +1300 (NZDT)

Rastei Amelia Viorela  <[email-masked]> wrote:
>  Consider I have a predicate
>    replace(El, Poz, List, Rez)
> which replaces the element from the position Poz in List with El and the
> resulting list is Rez.
	
I am suspicious of all code that refers to list elements by number.
There is often good reason to do this, but more often there is a better way.
For example, the Quintus library contains

    lists:nth0(?Index, ?List, ?Element)    % 0-origin
    lists:nth1(?Index, ?List, ?Element)    % 1-origin
    lists:nth0(?Index, ?AXZ, ?X, ?AZ)      % length(A, Index)
    lists:nth1(?Index, ?AXZ, ?X, ?AZ)	   % these two insert/delete

and the entire library(length) module is devoted to taking lists apart
constrained in various ways by a length parameter, but no-one ever found
replace/4 useful enough to include.

The DEC-10 Prolog library included a predicate replace/4,
but that's change_arg:/change_path_arg/4 in QP.

replace(NewElement, Offset, List, Result) :-
    length(Prefix, Offset),
    append(Prefix, [_|Suffix], List),
    append(Prefix, [NewElement|Suffix], Result).

> Consider then that List=[[1,2,3],[3,4,5,6],...] so a list of lists.
> And I want to apply predicate Replace to all the lists in List.
	
Yes, but how?  If you want to put the same NewElement at the same Offset
in all the elements of ListOfLists, 

    maplist(replace(NewElement, Offset), ListOfLists, Result)

will do the job.

Given the definition
l([[00,01,02,03],[10,11,12,13],[20,21,22,23],[30,31,32,33]]).
here are some example queries.

?- l(_X), maplist(replace(a,0), _X, Ans).
Ans = [[a, 1, 2, 3], [a, 11, 12, 13], [a, 21, 22, 23], [a, 31, 32, 33]] 
Yes

?- l(_X), maplist(replace(b,1), _X, Ans).
Ans = [[0, b, 2, 3], [10, b, 12, 13], [20, b, 22, 23], [30, b, 32, 33]] 
Yes

?- l(_X), maplist(replace(c,2), _X, Ans).
Ans = [[0, 1, c, 3], [10, 11, c, 13], [20, 21, c, 23], [30, 31, c, 33]] 
Yes

I used _X as a variable name here so that the original list would not be
displayed; we know what that is.

If you want to substitute different NewElements or at different Offsets,
you will not be able to use maplist/3 this way.

There are other ways to represent matrices in Prolog,
if that's what you are doing.