Na programação funcional, já que quase toda estrutura de dados é imutável, quando o estado precisa mudar, uma nova estrutura é criada. Isso significa muito mais uso de memória?
Isso depende da estrutura dos dados, das mudanças exatas que você executou e, em alguns casos, do otimizador. Como um exemplo, vamos considerar anexar a uma lista:
list2 = prepend(42, list1) // list2 is now a list that contains 42 followed
// by the elements of list1. list1 is unchanged
Aqui, o requisito adicional de memória é constante - assim como o custo de tempo de execução da chamada prepend
. Por quê? Porque prepend
simplesmente cria uma nova célula que tem 42
como cabeça e list1
cauda. Não é necessário copiar ou iterar list2
para conseguir isso. Ou seja, exceto a memória necessária para armazenar 42
, list2
reutiliza a mesma memória usada por list1
. Como as duas listas são imutáveis, esse compartilhamento é perfeitamente seguro.
Da mesma forma, ao trabalhar com estruturas de árvore balanceadas, a maioria das operações requer apenas uma quantidade logarítmica de espaço adicional, pois tudo, exceto um caminho da árvore, pode ser compartilhado.
Para matrizes, a situação é um pouco diferente. É por isso que, em muitas linguagens FP, matrizes não são tão comumente usadas. No entanto, se você fizer algo parecido arr2 = map(f, arr1)
e arr1
nunca for usado novamente após essa linha, um otimizador inteligente pode realmente criar código que sofre mutação em arr1
vez de criar uma nova matriz (sem afetar o comportamento do programa). Nesse caso, o desempenho será como em uma linguagem imperativa, é claro.