Pregunta

He estado buscando tutoriales sobre lo que son los acumuladores y lo que hacen, sin embargo, todas las explicaciones parecen estar muy complicadas y realmente no me dan una imagen lo suficientemente clara de cómo funcionan para que pueda usarlo. Parece que entiendo que los acumuladores se aferran a algo como un número que luego pueden ser llamados por otras piezas de código y cambiadas. El problema es que, aunque entiendo qué es un acumulador y sé que cuando lo necesito, no estoy muy seguro de cómo usarlo realmente.

Quiero decir, por los tutoriales que he visto, a veces el acumulador parece ser una lista vacía, mientras que otras veces parece ser '0' dejándome preguntándome qué exactamente puede considerarse un acumulador y qué no. ¿Alguien puede explicarme en términos simples cómo se puede usar exactamente un acumulador?

También para la segunda parte de mi pregunta, parece haber notado que las personas que usan esto mucho en sus códigos Prolog:

\+member

He logrado deducir que tiene algo que ver con las listas, ya que siempre veo que se usa dentro de una línea de código que hace algo a una lista, sin embargo, después de buscar, descubrí que lo que el miembro +significa es "la negación como falla - No comprobable "aunque realmente no entiendo lo que esto significa o incluso si esa persona era correcta. Una vez más, ¿puede alguien explicarme qué hace exactamente +el miembro y para qué puede usarse al intentar mantener su explicación simples y grandes palabras me confunden XD?

Muchas gracias por cualquier ayuda con respecto a estos dos asuntos.

¿Fue útil?

Solución

Primero, \+ es la negación de un objetivo. Tiene éxito, cuando el objetivo que lo sigue falla. Por ejemplo:

?- member(3, [1,2,3]). # 3 is a member of the List
true.

?- member(4, [1,2,3]). # 4 is not a member
false.

?- \+member(4, [1,2,3]). # succeeds, because 'member' fails
true.

?- \+member(3, [1,2,3]).
false.

?- atom_chars('hi', C).
C = [h, i].

?- atom_chars('hi', [h, i]).
true.

?- atom_chars('hello', [h, i]).
false.

?- \+atom_chars('hello', [h, i]).
true.

En segundo lugar, un acumulador es una forma de enhebrar el estado a través de una recursión, para aprovechar la optimización de la recursión de la cola.

Considere estas dos formas equivalentes de calcular un factorial:

?- [user].
|: fact_simple(0, 1).
|: fact_simple(N, F) :- 
         N1 is N-1, 
         fact_simple(N1, F1), 
         F is N*F1.
|: % user://2 compiled 0.00 sec, 440 bytes
true.

?- fact_simple(6, F).
F = 720 .

[user].
|: fact_acc(N, F) :- fact_acc(N, 1, F).
|: fact_acc(0, Acc, Acc).
|: fact_acc(N, Acc0, F) :- 
         N1 is N-1, 
         Acc is Acc0 * N, 
         fact_acc(N1, Acc, F).
|: % user://4 compiled 0.00 sec, 1,912 bytes
true.

?- fact_acc(6, F).
F = 720 .

La primera versión solo se llama a sí misma en la recursión, espera a que se complete el subcall. Solo entonces multiplica su N-valuar con el resultado de la subcall.

La segunda versión emplea un acumulador en su lugar (Acc). Tenga en cuenta que 1 no es el acumulador, pero es valor inicial. Después de eso, cada llamada al predicado multiplica que es N-value con el acumulador y a medida que la recursión alcanza su caso base, el valor del acumulador ya es el valor final.

La pregunta realmente no es '¿Qué puede ser el acumulador? (0 o la lista vacía o cualquier cosa). Es solo una forma de acumular valores 'a medida que avanza' y nunca volver al predicado de llamadas. De esta manera, el sistema Prolog no tiene que construir una pila de llamadas cada vez mayor.

Tenga en cuenta, sin embargo, que en este ejemplo el orden de las multiplicaciones se invierte naturalmente. No importa para la multiplicación, pero para otros valores (como listas), uno tiene que encargarse de eso.

fact_simple hizo la multiplicación como 1 * 2 * 3 * 4 * 5 * 6, tiempo fact_acc lo tuvo como 1 * 6 * 5 * 4 * 3 * 2. Si eso no está claro, ¡solo haz un rastro de ambos!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top