sintaxis - prolog sentencia if
¿Por qué es que, en la versión 6.4.1 de SWI-Prolog, current_functor/2 es falso para los predicados de 0-arity? (2)
Estoy usando la versión 6.4.1 de SWI-Prolog en OS X 7, y estoy experimentando el siguiente comportamiento inesperado con el predicado current_functor/2
:
Teniendo en cuenta los hechos
p(a).
q.
Recibo estas respuestas a las consultas:
?- current_functor(p, Y).
Y = 1
?- current_functor(q, Y).
false.
?- current_functor(q, 0).
true.
No solo las consultas segunda y tercera parecen descaradamente inconsistentes, sino que la falla de la segunda no parece ser consistente con el manual de referencia de SWI-Prolog, que describe current_functor/2
siguiente manera:
current_functor (? Name,? Arity) Unifica sucesivamente Nombre con el nombre y Arity con la cantidad de funtores conocidos por el sistema.
¿Alguien puede ayudarme a entender por qué el predicado está funcionando de esta manera?
Editar:
En términos de resolver mi problema particular de probar si los predicados se habían definido o no, incluso ciertos de arios, terminé siguiendo los consejos de false y escribiendo lo siguiente:
current_pred(P) :-
current_predicate(P/_).
Creo que podría haber un error en la línea 391 de pl-funct.c. Esa línea leída
if ( fd && fd->arity > 0 && (!nm || nm == fd->name) )
Ahora intentaré corregir a fd->arity >= 0
y probar ...
editar Aparentemente funcionó:
1 ?- [user].
yy.
|:
% user://1 compiled 0.00 sec, 2 clauses
true.
2 ?- current_functor(yy,X).
X = 0 ;
false.
Intentaré comprometerme, pero no creo que tenga acceso de git a la fuente completa ...
edita de hecho, git se niega a aceptar mi cambio ... Informaré en la lista de correo de SWI-Prolog.
TL; DR: ¡no!
current_functor/2
es un predicado incorporado específico de SWI que no encontrarás en ninguna otra parte (excepto el único DECsystem 10 históricamente relevante). La razón de este predicado está relacionada con la representación específica de funtores en SWI. En resumen, SWI necesita registrar cada functor, antes de usarlo. (Y antes de eso, necesita registrar el átomo relacionado.) ¿Qué sucede si el functor ya no se usa? ¿Seguirá estando presente o no? ¿Se recolecta este recurso basura?
Para responder a su pregunta: current_functor/2
solo tendrá éxito para los funtores. No hay funtores de arity 0. Un término con arity 0 se llama átomo y se maneja de manera diferente.
En cualquier caso, escribirá un código que depende de una implementación única que es mantenida por una sola persona. No es una apuesta muy segura para un proyecto más grande.
Otros sistemas Prolog funcionan de manera diferente. También necesitan registrar átomos, pero luego pueden construir cualquier functor hasta max_arity
sin usar ningún otro recurso global. Por este motivo, muchos sistemas ofrecen current_atom/1
.
Pero incluso ese mismo predicado está mal definido. Después de todo, ¿qué significa que un átomo todavía está presente? ¿Puede un compilador de optimización eliminar un átomo y cambiar así su significado? ¿Es un medio para inspeccionar los átomos confidenciales que una aplicación utiliza mediante un código de consulta que de otro modo sería inofensivo?
Todo esto es realmente una lata de gusanos. Evítalos a toda costa. Tal vez use current_predicate
lugar.
Dicho todo esto, si aún crees que lo necesitas, hazlo:
current_f(F, A) :-
current_functor(F, A).
current_f(F, 0) :-
current_atom(F).