Translate

lunes, 10 de junio de 2024

Más Funciones Recursivas en Erlang parte 3


Otra función a implementar podría ser sublist/2, que toma una lista L y un número entero N, y devuelve los N primeros elementos de la lista. Como ejemplo, sublista([1,2,3,4,5,6],3) devolvería [1,2,3]. Nuevamente, el caso base intenta obtener 0 elementos de una lista. Sin embargo, tenga cuidado, porque sublist/2 es un poco diferente. ¡Tienes un segundo caso base cuando la lista aprobada está vacía! Si no verificamos si hay listas vacías, se generará un error al llamar a recursive:sublist([1],2). mientras que queremos [1] en su lugar. Una vez definido esto, la parte recursiva de la función solo tiene que recorrer la lista, manteniendo los elementos a medida que avanza, hasta llegar a uno de los casos base:

sublist(_,0) -> [];

sublist([],_) -> [];

sublist([H|T],N) when N > 0 -> [H|sublist(T,N-1)].


Que luego se puede transformar a una forma recursiva de cola de la misma manera que antes:


tail_sublist(L, N) -> tail_sublist(L, N, []).

 

tail_sublist(_, 0, SubList) -> SubList;

tail_sublist([], _, SubList) -> SubList;

tail_sublist([H|T], N, SubList) when N > 0 -> tail_sublist(T, N-1, [H|SubList]).


Hay un defecto en esta función. ¡Un defecto fatal! Usamos una lista como acumulador exactamente de la misma manera que lo hicimos para invertir nuestra lista. Si compila esta función tal como está, sublist([1,2,3,4,5,6],3) no devolverá [1,2,3], sino [3,2,1]. Lo único que podemos hacer es tomar el resultado final y revertirlo nosotros mismos. Simplemente cambie la llamada tail_sublist/2 y deje intacta toda nuestra lógica recursiva:


tail_sublist(L, N) -> reverse(tail_sublist(L, N, [])).


El resultado final estará ordenado correctamente. Podría parecer que revertir nuestra lista después de una llamada recursiva de cola es una pérdida de tiempo y estaría en parte en lo cierto (todavía ahorramos memoria al hacer esto). En listas más cortas, es posible que descubra que su código se ejecuta más rápido con llamadas recursivas normales que con llamadas recursivas de cola por este motivo, pero a medida que sus conjuntos de datos crezcan, invertir la lista será comparativamente más ligero.