Re: [erlar] Dialyzer y Módulos Parametrizados
- From:
- Juan Jose Comellas
- Date:
- 2010-10-01 @ 14:26
Creo que la respuesta simple es que dialyzer no soporta completamente los
tipos parametrizados todavía. Por ahí deberías mandar un mail a la lista de
Erlang a ver qué contesta Kostis Sagonas, que es el líder del equipo que
hizo el dialyzer, si no me equivoco.
2010/10/1 Fernando Benavides <fernando.benavides@inakanetworks.com>
> Hola muchachos, ¿qué tal?
> Siendo uno de los (creo) pocos fans de dialyzer, ayer me topé con un lindo
> problemita que probablemente requiera una solución creativa. A ver qué
> opinan...
>
> Yo sé que desde la versión 2.2.0, Dialyzer soporta módulos parametrizados,
> al menos así lo dicen sus "release notes". Así que, siendo que tengo la
> versión 2.3.1, me dispuse a probarlo...
>
> Digamos entonces que, por alguna razón misteriosa (o_O), me encuentro con
> un módulo parametrizado para trabajar con colas de atoms (Es sólo de
> ejemplo, no vale preguntarse si esto tiene sentido en la vida real)...
> Muy bien, ahí va el módulo entonces:
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> -module(atom_queue, [Queue]).
>
> -export([push/1, pop/0]).
>
> pop() -> case Queue of
> [] -> {undefined, atom_queue:new([])};
> [X|Rest] -> {X, atom_queue:new(Rest)}
> end.
>
> push(X) -> atom_queue:new(lists:reverse([X|Queue])).
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>
> Probablemente si lo compilo y luego ejecuto dialyzer no reciba ningún warning,
> pero eso es porque no puse ninguna especificación (spec) en el código y no
> lo estoy compilando con los warnings activados. Ahora bien, si al
> compilarlo uso la opción with warn_missing_spec, el compilador me dirá que
> me olvidé de especificar las funciones pop/0 y push/1. Así que, les agrego
> las correspondientes specs:
>
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> -module(atom_queue, [Queue]).
>
> -export([push/1, pop/0]).
>
> *-spec pop() -> {undefined | atom(), {?MODULE, [atom()]}}. *
> pop() -> case Queue of
> [] -> {undefined, atom_queue:new([])};
> [X|Rest] -> {X, atom_queue:new(Rest)}
> end.
>
> *-spec push(atom()) -> {?MODULE, [atom()]}. *
> push(X) -> atom_queue:new(lists:reverse([X|Queue])).
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>
> Ahora, al compilar, no recibo más warnings. El problema es que al ejecutar
> dialyzer aparecen dos:
> Contract for function that does not exist: atom_queue:pop/0
> Contract for function that does not exist: atom_queue:push/1
>
> Si yo quisiera que dialyzer no se quejara, debería modificar los specs de
> la siguiente manera:
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
> -module(atom_queue, [Queue]).
>
> -export([push/1, pop/0]).
>
> -spec pop(*{?MODULE, [atom()]}*) -> {undefined | atom(), {?MODULE,
> [atom()]}}.
> pop() -> case Queue of
> [] -> {undefined, atom_queue:new([])};
> [X|Rest] -> {X, atom_queue:new(Rest)}
> end.
>
> -spec push(atom(), *{?MODULE, [atom()]}*) -> {?MODULE, [atom()]}.
> push(X) -> atom_queue:new(lists:reverse([X|Queue])).
> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
>
> Pero claro, al tratar de compilar ese código, el compilador presenta dos
> errores (ya ni siquiera son warnings):
> spec for undefined function atom_queue:pop/1
> spec for undefined function atom_queue:push/2
>
> Así que, en definitiva, mi pregunta es: ¿Cómo puedo hacer para compilar mi
> módulo parametrizado con specs sin generar errores de compilación ni
> warnings por parte del dialyzer?
>
> ------------------------------
>
> *Fernando Benavides <http://google.com/profiles/greenmellon>*
>
> *fernando@inakanetworks.com*
>
Re: [erlar] Dialyzer y Módulos Parametrizados
- From:
- Mariano Guerra
- Date:
- 2010-10-01 @ 14:18
2010/10/1 Fernando Benavides <fernando.benavides@inakanetworks.com>
>
> Hola muchachos, ¿qué tal?
> Siendo uno de los (creo) pocos fans de dialyzer, ayer me topé con un
lindo problemita que probablemente requiera una solución creativa. A ver
qué opinan...
>
> Así que, en definitiva, mi pregunta es: ¿Cómo puedo hacer para compilar
mi módulo parametrizado con specs sin generar errores de compilación ni
warnings por parte del dialyzer?
es raro, debe ser por la magia que se usa para hacer modulos
parametrizados. este es el module_info del modulo:
1> atom_queue:module_info().
[{exports,[{new,1},
{instance,1},
{pop,1},
{push,2},
{module_info,0},
{module_info,1}]},
asi que efectivamente la aridad es pop/1 y push/2. Como veo que ya
sabes el modulo parametrizado agrega una tupla como utlimo argumento
que contiene el estado del modulo.
el problema es que a alto nivel pop es pop/0 y push/1:
compilando con -P:
-export([push/1,pop/0]).
pop() ->
case Queue of
[] ->
{undefined,atom_queue:new([])};
[X|Rest] ->
{X,atom_queue:new(Rest)}
end.
push(X) ->
atom_queue:new(lists:reverse([X|Queue])).
compilando con -E
pop({_,Queue} = THIS) ->
case Queue of
[] ->
{undefined,atom_queue:new([])};
[X|Rest] ->
{X,atom_queue:new(Rest)}
end.
push(X, {_,Queue} = THIS) ->
atom_queue:new(lists:reverse([X|Queue])).
como ves le agrega magicamente el argumento pero a un mas bajo nivel,
puede que dializer haga el analisis en un nivel y se confunda.
PD: no te estoy ayudando en mucho, solo pienso en voz alta mientras
analizo el problema :P