arg/3 does not seem to be able to set deep terms when invoked in the foreach/2 context. I’ve discovered this in threaded 64bit version 8.4.2 running under Linux and confirmed that in threaded 64bit version 9.2.9.1 running under Windows OS. Below follows the code with explanation in the final comment:
data(1,1,0).
data(2,0,1).
data(3,4,4).
data(5,0,0).
make_array1(A):-
functor(A, array,10),
foreach(data(Nr,X,Y),(format("x=~q y=~q\n",[X,Y]),
arg(Nr,A,X:Y)) ).
bug1:-make_array1(A),writeln(a=A).
make_array2(A):-
functor(A, array,10),
foreach(data(Nr,X,Y),(format("x=~q y=~q\n",[X,Y]),
Z=X:Y,
arg(Nr,A,Z)) ).
bug2:-make_array2(B),writeln(b=B).
make_array3(A):-
functor(A, array,10),
foreach(data(Nr,X,Y),(format("x=~q y=~q\n",[X,Y]),
arg(Nr,A,X)) ).
nobug0:-make_array3(C),writeln(c=C).
make_array4(A):-
functor(A, array,10),
foreach(data(Nr,X,Y),(format("x=~q y=~q\n",[X,Y]),
arg(Nr,A,Z),
Z=X:Y )).
bug3:-make_array4(D),writeln(d=D).
make_array5(A):-
functor(A, array,10),
findall(n(N,X,Y),data(N,X,Y),L),
maplist({A}/[E]>>(E=n(N,X,Y),arg(N,A,X:Y)),L).
nobug1:-make_array5(E),writeln(e=E).
make_array6(A):-
functor(A, array,10),
findall(n(N,X,Y),data(N,X,Y),L),
do_make_array(L,A).
do_make_array([],_).
do_make_array([n(N,X,Y)|L],A):-arg(N,A,X:Y),do_make_array(L,A).
nobug2:-make_array6(F),writeln(f=F).
/* bug1, bug2 and bug3 only creates the template and does not fill values, i.e. the
output looks like so:
?- bug1.
x=1 y=0
x=0 y=1
x=4 y=4
x=0 y=0
a=array(_31412:_31414,_31412:_31414,_31412:_31414,_31394,_31412:_31414,_31398,_31400,_31402,_31404,_31406)
When filling just one coordinate using nobug0, it does enter the data:
?- nobug.
x=1 y=0
x=0 y=1
x=4 y=4
x=0 y=0
c=array(1,0,4,_542,0,_546,_548,_550,_552,_554)
nobug1 and nobug2 work just fine:
?- nobug2.
f=array(1:0,0:1,4:4,_47596,0:0,_47600,_47602,_47604,_47606,_47608)
true.
*/