2008-11-22 12 views
5

Estoy aprendiendo programación funcional y he intentado resolver un par de problemas en un estilo funcional. Una cosa que experimenté, mientras dividía mi problema en funciones, era que parecía tener dos opciones: usar varias funciones dispares con listas de parámetros similares, o usar funciones anidadas que, como cierres, pueden referirse simplemente a enlaces en la función primaria.Funciones anidadas: ¿uso inapropiado de efectos secundarios?

Aunque terminé yendo con el segundo enfoque, porque hacía las llamadas de función más pequeñas y parecía "sentirse" mejor, desde mi lectura parece que me falta uno de los puntos principales de la programación funcional, en ese esto parece "efecto secundario"? Ahora bien, estas funciones anidadas no pueden modificar los enlaces externos, ya que el lenguaje que estaba usando evita eso, pero si observas cada función interna individual, no puedes decir "dados los mismos parámetros, esta función arrojará los mismos resultados" porque usan las variables del alcance principal ... ¿estoy en lo cierto?

¿Cuál es la forma deseable de proceder?

Gracias!

Respuesta

2

Las funciones de anidamiento son una forma excelente de dividir la mano de obra en muchas funciones. No es realmente "de efecto secundario"; si ayuda, piense en las variables capturadas como parámetros implícitos.

Un ejemplo donde las funciones anidadas son útiles es reemplazar los bucles. Los parámetros de la función anidada pueden actuar como variables de inducción que acumulan valores. Un ejemplo sencillo:

let factorial n = 
    let rec facHelper p n = 
     if n = 1 then p else facHelper (p*n) (n-1) 
    in 
    facHelper 1 n 

En este caso, no sería realmente tiene sentido para declarar una función como facHelper a nivel mundial, ya que los usuarios no deberían tener que preocuparse por el parámetro p.

Tenga en cuenta, sin embargo, que puede ser difícil probar funciones anidadas individualmente, ya que no se pueden hacer referencia a ellas fuera de su principal.

+0

facHelper en realidad no se refiere a ningún valor externo, sino que es puramente funcional. –

3

La programación funcional no es todo o nada. Si anidar las funciones tiene más sentido, seguiría con ese enfoque. Sin embargo, si realmente desea que las funciones internas sean puramente funcionales, pase explícitamente todos los parámetros necesarios.

He aquí un pequeño ejemplo en el esquema:

(define (foo a) 
    (define (bar b) 
    (+ a b))  ; getting a from outer scope, not purely functional 
    (bar 3)) 

(define (foo a) 
    (define (bar a b) 
    (+ a b))  ; getting a from function parameters, purely functional 
    (bar a 3)) 


(define (bar a b) ; since this is purely functional, we can remove it from its 
    (+ a b))  ; environment and it still works 

(define (foo a) 
    (bar a 3)) 

En lo personal, me gustaría ir con el primer enfoque, pero o bien a funcionar igual de bien.

1

Considere lo siguiente (artificial) Haskell fragmento:

putLines :: [String] -> IO() 
putLines lines = putStr string 
    where string = concat lines 

string es una constante llamada con destino a nivel local. ¿Pero no es también una función que no toma argumentos que cierra más de lines y por lo tanto es referencialmente intransparente? (¡En Haskell, las constantes y las funciones nulary son indistinguibles!) ¿Consideraría que el código anterior es "de efecto secundario" o no funcional debido a esto?

Cuestiones relacionadas