En pocas palabras, las restricciones significan que hay menos formas correctas de poner las cosas juntas, y las funciones de primera clase facilitan la factorización de elementos como las estructuras de bucle. Tome el ciclo de esta respuesta , por ejemplo:
for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
String string = iterator.next();
if (string.isEmpty()) {
iterator.remove();
}
}
Esta es la única forma segura e imperativa en Java de eliminar un elemento de una colección mientras está iterando a través de él. Hay muchas formas en que se ven muy cerca, pero están equivocadas. Las personas que no conocen este método a veces recurren a formas complicadas para evitar el problema, como iterar a través de una copia.
No es terriblemente difícil hacer este genérico, por lo que funcionará en más que solo colecciones de Strings, pero sin funciones de primera clase, no puede reemplazar el predicado (la condición dentro del if), por lo que este código tiende a copiarse y pegarse y modificado ligeramente.
Combine funciones de primera clase que le brinden la capacidad de pasar el predicado como parámetro, con la restricción de inmutabilidad que lo hace muy molesto si no lo hace, y se le ocurren bloques de construcción simples como filter, como en este código Scala eso hace lo mismo:
list filter (!_.isEmpty)
Ahora piense en lo que el sistema de tipos comprueba por usted, en el momento de la compilación en el caso de Scala, pero estas comprobaciones también las realizan los sistemas de tipos dinámicos la primera vez que lo ejecuta:
listdebe ser algún tipo de tipo que admita el filtermétodo, es decir, una colección.
- Los elementos de
listdeben tener un isEmptymétodo que devuelva un valor booleano.
- La salida será una colección (potencialmente) más pequeña con el mismo tipo de elementos.
Una vez que se han verificado esas cosas, ¿qué otras formas le quedan al programador para arruinar? Accidentalmente olvidé el !, lo que causó una falla de caso de prueba extremadamente obvia. Ese es prácticamente el único error disponible para cometer, y solo lo cometí porque estaba traduciendo directamente del código que probó la condición inversa.
Este patrón se repite una y otra vez. Las funciones de primera clase le permiten refactorizar las cosas en pequeñas utilidades reutilizables con una semántica precisa, las restricciones como la inmutabilidad le dan el impulso para hacerlo, y la comprobación de tipo de los parámetros de esas utilidades deja poco espacio para arruinarlas.
Por supuesto, todo esto depende de que el programador sepa que la función de simplificación filterya existe, y que sea capaz de encontrarla o de reconocer el beneficio de crearla usted mismo. Intente implementar esto usted mismo en todas partes usando solo la recursión de cola, y estará de vuelta en el mismo barco de complejidad que la versión imperativa, solo que peor. El hecho de que pueda escribirlo de manera muy simple no significa que la versión simple sea obvia.