Je ne sais pas, mais au toplevel la modification du terme composé est annulée lors d'un retour en arrière pour une raison quelconque (SWI-Prolog 8.3.14) :
Toplevel
?-
functor(A, array, 5),
forall(
arg(Index, A, _),
(format("~q: ~q\n",[Index,A]),
nb_setarg(Index, A, 0),
format("~q: ~q\n",[Index,A]))).
Ensuite, nous voyons de nouvelles array/5
des termes composés avec des variables nouvelles à chaque passage de forall
1: array(_3228,_4334,_4336,_4338,_4340)
1: array(0 ,_4334,_4336,_4338,_4340)
2: array(_4332,_3228,_4336,_4338,_4340)
2: array(_4332,0, _4336,_4338,_4340)
3: array(_4332,_4334,_3228,_4338,_4340)
3: array(_4332,_4334, 0,_4338,_4340)
4: array(_4332,_4334,_4336,_3228,_4340)
4: array(_4332,_4334,_4336,0, _4340)
5: array(_4332,_4334,_4336,_4338,_3228)
5: array(_4332,_4334,_4336,_4338,0)
A = array(_4332, _4334, _4336, _4338, _4340).
En règle générale
new_array(A,N) :-
functor(A, array, N),
forall(
arg(Index, A, _),
(format("~q: ~q\n",[Index,A]),
nb_setarg(Index, A, 0),
format("~q: ~q\n",[Index,A]))).
Entonces:
?- new_array(A,5).
1: array(_2498,_2500,_2502,_2504,_2506)
1: array(0,_2500,_2502,_2504,_2506)
2: array(0,_2500,_2502,_2504,_2506)
2: array(0,0,_2502,_2504,_2506)
3: array(0,0,_2502,_2504,_2506)
3: array(0,0,0,_2504,_2506)
4: array(0,0,0,_2504,_2506)
4: array(0,0,0,0,_2506)
5: array(0,0,0,0,_2506)
5: array(0,0,0,0,0)
A = array(0, 0, 0, 0, 0).
D'autre part, la mise en œuvre est le suivant :
forall(Cond, Action) :-
\+ (Cond, \+ Action).
Le prédicat ci-dessus n'est pas un bon prédicat à utiliser comme boucle.
Cependant, le comportement dans le "rule setting" semble correct.
En la documentation dit :
Le prédicat forall/2
est mis en œuvre sous la forme \+ ( Cond, \+ Action)
, c'est-à-dire, Il n'y a pas d'instanciation de Cond
pour lequel Action
est faux . L'utilisation de la double négation implique que forall/2
ne modifie aucune liaison de variable. Il prouve une relation. Les forall/2
La structure de contrôle peut être utilisée pour ses effets secondaires.
Tout à fait.
Il n'y a rien de particulier dans la description de nb_setarg/3
soit.
C'est comme si nb_setarg/3
travaillaient en tant que setarg/3
au niveau supérieur ?
La trace ne révèle rien :
^ Call: (13) format("~q: ~q\n", [1, array(_30756, _32086, _32088, _32090, _32092)]) ? creep
1: array(_30756,_32086,_32088,_32090,_32092)
^ Exit: (13) format("~q: ~q\n", [1, array(_30756, _32086, _32088, _32090, _32092)]) ? creep
Call: (13) setarg(1, array(_30756, _32086, _32088, _32090, _32092), 0) ? creep
Exit: (13) setarg(1, array(0, _32086, _32088, _32090, _32092), 0) ? creep
^ Call: (13) format("~q: ~q\n", [1, array(0, _32086, _32088, _32090, _32092)]) ? creep
1: array(0,_32086,_32088,_32090,_32092)
^ Exit: (13) format("~q: ~q\n", [1, array(0, _32086, _32088, _32090, _32092)]) ? creep
Next "forall" passage: we are using a new compound term!
^ Call: (13) format("~q: ~q\n", [2, array(_32084, _30756, _32088, _32090, _32092)]) ? creep
2: array(_32084,_30756,_32088,_32090,_32092)
^ Exit: (13) format("~q: ~q\n", [2, array(_32084, _30756, _32088, _32090, _32092)]) ? creep
Call: (13) setarg(2, array(_32084, _30756, _32088, _32090, _32092), 0) ? creep
Exit: (13) setarg(2, array(_32084, 0, _32088, _32090, _32092), 0) ?
Comme il s'agit d'une question relative à SWI-Prolog, vous pouvez la poser sur le site suivant Discours .
Mise à jour
Essai en ligne en GNU Prolog .
GNU Prolog exige que l'index de arg/3
peut être instancié et n'a pas de nb_setarg/3
(ni un forall/2
? ?).
Mais essayons ce qui suit dans SWI-Prolog :
functor(A, array, 5),
\+ (
between(1,5,Index),arg(Index, A, _),
\+
(format("~q: ~q\n",[Index,A]),
nb_setarg(Index, A, 0),
format("~q: ~q\n",[Index,A]))).
Cela ne fonctionne pas non plus.
Mise à jour : Essayer quelque chose de plus simple et de plus dépouillé
Comme prévu :
?-
A=p(1,2,3),nb_setarg(1,A,foo).
A = p(foo, 2, 3).
Avec double négation. Conserve également la valeur définie de manière non rétroactive :
?-
A=p(1,2,3),\+ \+ nb_setarg(1,A,foo).
A = p(foo, 2, 3).