¿Una función que obtiene un valor de otra función se considera pura?

9

Estoy tratando de encontrar una manera de manejar los valores de las variables predeterminadas cuando hago funciones sin efectos secundarios y terminé con lo siguiente:

function getDefaultSeparator() {
    return ':';
}

function process(input, separator) {
    var separator = separator || getDefaultSeparator();

    // Use separator in some logic

    return output;
}

El separador predeterminado se usará en otras funciones y solo quiero definirlo en un lugar.

Si esta es una función pura, ¿cuál es la diferencia de usar una constante global DEFAULT_SEPARATOR en su lugar?

agost
fuente
55
No hay ninguna diferencia material, a menos que esté planeando usar la función como marcador de posición para que se agregue algo de lógica más adelante.
Robert Harvey
3
Posible duplicado de ¿Es una función inmediatamente impura si toma una función como parámetro? . La pregunta no es un duplicado exacto, pero la respuesta debería ser la misma. ("Depende de la pureza de la otra función").
jpmc26
1
Usar una constante global no hace que una función sea impura. Usar un valor global que suponga que es constante lo hace.
chepner
Por cierto, puede curry process(con el orden de los parámetros invertidos) y luego especializar la función de curry paravar processDefault = process(":")
bob

Respuestas:

22

¿Una función que obtiene un valor de otra función se considera pura?

Eso depende de lo que hace la otra función y de lo que hace la función de llamada. La impureza es infecciosa, la pureza no lo es.

Llamar a una función pura no cambia la pureza de la función de llamada. Llamar a una función impura automáticamente hace que la función de llamada sea impura también.

Entonces, en su ejemplo, depende de la pureza de la parte que dejó fuera: si eso es puro, entonces toda la función es pura.

Si esta es una función pura, ¿cuál es la diferencia de usar una constante global DEFAULT_SEPARATOR en su lugar?

Nada. Una función que siempre devuelve el mismo valor es indistinguible de una constante. De hecho, así es exactamente como se modelan las constantes en el cálculo λ.

Jörg W Mittag
fuente
2
"Llamar a una función impura automáticamente hace que la función de llamada sea impura también" ¿Estás seguro de eso? AFAICS, llamar a una función impura no hace automáticamente que la persona que llama sea impura, aunque sí lo haga.
Deduplicador
2
@Dupuplicator: depende de cuánto análisis estático puede (molestarse) hacer. Claro, si hay una función funcque tiene efectos secundarios cuando pasas 0, pero no cuando pasas 1, entonces puedes decir razonablemente que aunque en funcsí "es impuro", una función lo llama como func(1)(e ignora el valor de retorno, vamos a decir) no es necesariamente impuro. Llamar funces suficiente para "contaminar" a la persona que llama como potencialmente impura, pero una función contaminada podría, de alguna manera, demostrarse que es pura después de todo. Al menos en javascript, donde puro / impuro no está definido dentro del lenguaje.
Steve Jessop
6

Sí, esas son funciones puras (suponiendo que la parte elidida también sea pura) porque:

  1. El resultado depende solo de los parámetros.
  2. No hay efectos secundarios.

Tenga en cuenta que si getDefaultSeparator()no fuera una función pura, tampoco lo process()sería.

En Javascript, no existe una diferencia significativa entre el uso de una función pura o una constante y ambas pueden ser utilizadas por la función pura, siempre que se evite la capacidad de Javascript para redefinir funciones o alterar los valores de las constantes.

Un concepto clave detrás de las funciones puras es que podrían reemplazarse con el valor que devuelven sin afectar los resultados del programa.

8bittree
fuente
1

Como dicen los demás, claro, sigue siendo una función pura.

Sin embargo, hablemos sobre los problemas de diseño. Tiene razón al intentar hacer algo para mantener el código SECO, colocando el valor solo una vez. Además, lo que creo que también se debe considerar es el nivel de acoplamiento apropiado.

El uso de una función le brinda más flexibilidad para cambiar la implementación, lo que significa que el enfoque de la función ofrece un acoplamiento más flexible que una variable global.

La pregunta es si uno lo necesita o no.

Si los consumidores y el proveedor están en el mismo módulo, y el proveedor es privado para el módulo, es difícil argumentar que este nivel de acoplamiento flojo es necesario, debido al hecho de que si el proveedor requiere la actualización de una variable privada a una método privado, una refactorización simple dentro del módulo se puede aplicar a los consumidores al mismo tiempo. El uso de un método / función antes de que realmente lo necesite podría incluirse en YAGNI.

Incluso si el consumidor (s) y el proveedor están en módulos diferentes, los módulos se versionan juntos (por ejemplo, utiliza un minifyer, de modo que los módulos de los consumidores y el proveedor están en el mismo archivo), YAGNI también puede aplicarse.

Por otro lado, si, por ejemplo, el productor está en un paquete o módulo de biblioteca o API que se versiona por separado de los consumidores, entonces puede ser apropiado usar la función. En ese caso, deberíamos considerar la longevidad de la API y principios como OCP.

(En otra nota, si su código es de algún tamaño significativo, recomendaría el uso de módulos con campos y métodos en lugar de variables y funciones globales).

Erik Eidt
fuente