The specification should probably be

setarg(+Arg, !Term, +Value)

Position is 1-based and the predicate fails if *Value* is out-of-bounds:

?- X=f(a,b,c,d), setarg(0,X,foo). false. ?- X=f(a,b,c,d), setarg(1,X,foo). X = f(foo, b, c, d). ?- X=f(a,b,c,d), setarg(4,X,foo). X = f(a, b, c, foo). ?- X=f(a,b,c,d), setarg(5,X,foo). false.

Otherwise, works as expected:

?- X=f(a,Y,Y,d), setarg(2,X,Y). X = f(a, Y, Y, d).

?- X=f(a,Y,Y,d), setarg(2,X,f(Y)). X = f(a, f(Y), Y, d).

We need more information about *unexpected copying as well as unexpected noncopying of terms.*