Para pequeñas cantidades de datos, básicamente hay dos estructuras de datos que se pueden usar. La primera se llama proplist. Una proplist es cualquier lista de tuplas de la forma [{Key,Value}]. Son un tipo de estructura extraño porque no hay otra regla que esa. De hecho, las reglas son tan relajadas que la lista también puede contener valores booleanos, números enteros y lo que quieras. Sin embargo, nos interesa más la idea de una tupla con una clave y un valor en una lista. Para trabajar con proplists, puedes usar el módulo proplists. Contiene funciones como proplists: delete/2, proplists:get_value/2, proplists:get_all_values/2, proplists:lookup/2 y proplists:lookup_all/2.
Notarás que no hay ninguna función para agregar o actualizar un elemento de la lista. Esto muestra cuán vagamente definidas están las proplists como estructura de datos. Para obtener estas funcionalidades, debes construir tu elemento manualmente ([NewElement|OldList]) y usar funciones como lists:keyreplace/4. Usar dos módulos para una pequeña estructura de datos no es lo más claro, pero debido a que las proplists están definidas de manera tan vaga, a menudo se usan para tratar con listas de configuración y descripciones generales de un elemento determinado. Las proplists no son exactamente estructuras de datos completas. Son más bien un patrón común que aparece cuando se usan listas y tuplas para representar algún objeto o elemento; el módulo proplists es una especie de caja de herramientas para este patrón.
Si desea un almacén de clave-valor más completo para pequeñas cantidades de datos, el módulo orddict es lo que necesita. Los orddicts (diccionarios ordenados) son proplists con un gusto por la formalidad. Cada clave puede estar allí una vez, la lista completa está ordenada para una búsqueda promedio más rápida, etc. Las funciones comunes para el uso de CRUD incluyen orddict:store/3, orddict:find/2 (cuando no sabe si la clave está en los diccionarios), orddict:fetch/2 (cuando sabe que está allí o que debe estar allí) y orddict:erase/2.
Los orddicts son un compromiso generalmente bueno entre complejidad y eficiencia hasta aproximadamente 75 elementos. Después de esa cantidad, deberías cambiar a diferentes almacenes de clave-valor.
Básicamente, existen dos estructuras/módulos de clave-valor para manejar mayores cantidades de datos: dicts y gb_trees. Los diccionarios tienen la misma interfaz que los orddicts: dict:store/3, dict:find/2, dict:fetch/2, dict:erase/2 y todas las demás funciones, como dict:map/2 y dict:fold/2 (¡bastante útiles para trabajar en toda la estructura de datos!). Por lo tanto, los dicts son muy buenas opciones para escalar los orddicts cuando sea necesario.
Los árboles balanceados generales, por otro lado, tienen muchas más funciones que te dejan un control más directo sobre cómo se debe usar la estructura. Básicamente, existen dos modos para gb_trees: el modo en el que conoces tu estructura al dedillo (lo llamo el "modo inteligente") y el modo en el que no puedes asumir mucho sobre ella (lo llamo el "modo ingenuo"). En el modo ingenuo, las funciones son gb_trees:enter/3, gb_trees:lookup/2 y gb_trees:delete_any/2. Las funciones inteligentes relacionadas son gb_trees:insert/3, gb_trees:get/2, gb_trees:update/3 y gb_trees:delete/2. También existe gb_trees:map/2, que siempre es una buena opción cuando la necesitas.
La desventaja de las funciones "ingenuas" sobre las "inteligentes" es que, como los gb_trees son árboles equilibrados, siempre que insertes un nuevo elemento (o elimines un montón), es posible que el árbol deba equilibrarse a sí mismo. Esto puede llevar tiempo y memoria (incluso en comprobaciones inútiles solo para asegurarse). Todas las funciones "inteligentes" suponen que la clave está presente en el árbol: esto te permite omitir todas las comprobaciones de seguridad y da como resultado tiempos más rápidos.
¿Cuándo deberías usar gb_trees en lugar de diccionarios? Bueno, no es una decisión clara. Como lo mostrará el módulo de referencia que he escrito, gb_trees y dicts tienen rendimientos algo similares en muchos aspectos. Sin embargo, la referencia demuestra que dicts tienen las mejores velocidades de lectura mientras que gb_trees tienden a ser un poco más rápidos en otras operaciones. Puede juzgar en función de sus propias necesidades cuál sería el mejor.
Ah, y otra cosa a tener en cuenta que mientras que dicts tienen una función de plegado, gb_trees no: en su lugar, tienen una función de iteración, que devuelve un fragmento del árbol en el que puede llamar a gb_trees:next(Iterator) para obtener los siguientes valores en orden. Lo que esto significa es que necesita escribir sus propias funciones recursivas sobre gb_trees en lugar de usar un genric fold. Por otro lado, gb_trees te permite tener un acceso rápido a los elementos más pequeños y más grandes de la estructura con gb_trees:smallest/1 y gb_trees:largest/1.
Por lo tanto, diría que las necesidades de tu aplicación son las que deberían determinar qué almacén de clave-valor elegir. Diferentes factores, como la cantidad de datos que tienes que almacenar, lo que necesitas hacer con ellos y demás, tienen su importancia. Mide, perfila y compara para asegurarte.
Existen algunos almacenes de clave-valor especiales para manejar recursos de diferentes tamaños. Estos almacenes son las tablas ETS, las tablas DETS y la base de datos mnesia. Sin embargo, su uso está fuertemente relacionado con los conceptos de múltiples procesos y distribución.
A partir de la versión 17.0, el lenguaje admite un nuevo tipo de datos de clave-valor nativo, descrito en Postscript: Maps.