Funciones anidadas: uso inadecuado de efectos secundarios? -- functional-programming campo con nested campo con side-effects camp Relacionados El problema

Nested functions: Improper use of side-effects?


6
vote

problema

Español

Estoy aprendiendo programación funcional, y he tratado de resolver un par de problemas en un estilo funcional. Una cosa que experimenté, al mismo tiempo que dividí mi problema en funciones, ¿parecía que tenía dos opciones: use varias funciones dispares con las listas similares de parámetros, o utilizando las funciones anidadas que, como cierres, pueden referirse a los enlaces en la función principal?

Aunque terminé con el segundo enfoque, porque hizo que las llamadas de funciones sean más pequeñas y parecía "sentirse" mejor, desde mi lectura, parece que puedo estar perdiendo uno de los puntos principales de la programación funcional, en ese sentido. Parece "efecto secundario"? Ahora, estas funciones anidadas no pueden modificar las enlaces exteriores, ya que el lenguaje que usaba evita que, pero si observa cada función interior individual, no puede decir "Dados los mismos parámetros, esta función devolverá los mismos resultados" Debido a que usan las variables del ámbito de los padres ... ¿Estoy en lo cierto?

¿Cuál es la forma deseable de proceder?

¡Gracias!

Original en ingles

I'm learning functional programming, and have tried to solve a couple problems in a functional style. One thing I experienced, while dividing up my problem into functions, was it seemed I had two options: use several disparate functions with similar parameter lists, or using nested functions which, as closures, can simply refer to bindings in the parent function.

Though I ended up going with the second approach, because it made function calls smaller and it seemed to "feel" better, from my reading it seems like I may be missing one of the main points of functional programming, in that this seems "side-effecty"? Now granted, these nested functions cannot modify the outer bindings, as the language I was using prevents that, but if you look at each individual inner function, you can't say "given the same parameters, this function will return the same results" because they do use the variables from the parent scope... am I right?

What is the desirable way to proceed?

Thanks!

        

Lista de respuestas

3
 
vote
vote
La mejor respuesta
 

Funciones de anidación es una excelente manera de dividir el trabajo en muchas funciones. No es realmente "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 a la función anidada pueden actuar como variables de inducción que acumulan valores. Un ejemplo simple:

  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, realmente no tendría sentido declarar una función como facHelper a nivel mundial, ya que los usuarios no deben tener que preocuparse por el parámetro (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)) 5 . < / p>

Sé consciente, sin embargo, que puede ser difícil probar las funciones anidadas individualmente, ya que no pueden ser referidas fuera de sus padres.

 

Nesting functions is an excellent way to divide up the labor in many functions. It's not really "side-effecty"; if it helps, think of the captured variables as implicit parameters.

One example where nested functions are useful is to replace loops. The parameters to the nested function can act as induction variables which accumulate values. A simple example:

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

In this case, it wouldn't really make sense to declare a function like facHelper globally, since users shouldn't have to worry about the p parameter.

Be aware, however, that it can be difficult to test nested functions individually, since they cannot be referred to outside of their parent.

 
 
 
 
4
 
vote

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

Aquí hay un poco de 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))   

Personalmente, iría con el primer enfoque, pero funcionará igualmente bien.

 

Functional programming isn't all-or-nothing. If nesting the functions makes more sense, I'd go with that approach. However, If you really want the internal functions to be purely functional, explicitly pass all the needed parameters into them.

Here's a little example in Scheme:

(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)) 

Personally, I'd go with the first approach, but either will work equally well.

 
 
1
 
vote

Considere el siguiente fragmento HASKELL:

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

string es un constante constante ubicado localmente. Pero, ¿no es también una función que no toma argumentos que se cierre sobre lines y, por lo tanto, es referencialmente intransparente? (¿En Haskell, las constantes y las funciones nulario son, de hecho, indistinguibles!) ¿Consideraría el código anterior "efecto secundario" o no funcional debido a esto?

 

Consider the following (contrived) Haskell snippet:

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

string is a locally bound named constant. But isn't it also a function taking no arguments that closes over lines and is therefore referentially intransparent? (In Haskell, constants and nullary functions are indeed indistinguishable!) Would you consider the above code xe2x80x9cside-effectyxe2x80x9d or non-functional because of this?

 
 

Relacionados problema

0  Seguimiento de efectos secundarios en SSA  ( Side effect tracking in ssa ) 
Estoy trabajando en un optimizador para Java Bytecode y decidí usar SSA. Sin embargo, la mayoría de las optimizaciones requieren todas las operaciones a ser p...

0  Método de clase burlado de unittest no se llama  ( Unittest mocked classs method not being called ) 
Soy nuevo para burlarse de las pruebas. Para los propósitos de aprendizaje, estoy tratando de simular el estado de estado, ya sea que la conexión de la base d...

4  ¿Cómo marca el código con efectos secundarios?  ( How do i mark code with side effects ) 
Estoy trabajando en un proyecto en un 8051 donde cada byte cuenta. Como tal, estoy usando algunas variables globales donde normalmente no lo haría. El método ...

14  Getter con efecto secundario  ( Getter with side effect ) 
creo una clase cuyos objetos se inicializan con Un montón de código XML. La clase tiene la capacidad de extraer varios parámetros de ese XML y para almacenarl...

23  Regla de efectos secundarios PSR-1 2.3  ( Psr 1 2 3 side effects rule ) 
Tengo una pregunta con respecto a los estándares de codificación básicos de PHP PSR1. PSR 1 REGLA 2.3 ESTADOS: Regla 2.3 Efectos secundarios Un archivo d...

10  Cierre de Python con efectos secundarios  ( Python closure with side effects ) 
Me pregunto si es posible que un cierre en Python manipule las variables en su espacio de nombres. Puede llamar a estos efectos secundarios porque el estado s...

4  ¿Cómo manejar las relaciones bidireccionales al construir las entidades de hibernación?  ( How to handle bidirectional relationships when constructing hibernate entities ) 
Quiero modelar la relación entre dos entidades, un grupo y una cuenta con JPA / Hibernate. Una cuenta puede tener varios grupos, pero no viceversa, por lo que...

35  ¿Cuáles son las alternativas de las mónadas para usar IO en la programación funcional pura?  ( What are the alternative of monads to use io in pure functional programming ) 
Las mónadas se describen como la solución Haskell para tratar con IO. Me preguntaba si había otras formas de lidiar con IO en lenguaje funcional puro. ...

3  ¿Por qué no puedes mapear imprimir en una lista en Haskell?  ( Why cant you map print to a list in haskell ) 
Revisé este publicado antes de hacer esto, pero esa publicación realmente no explicar por qué esto no funciona. foo :: (Num a, Show a) => a -> IO () fo...

1  Activación de efectos secundarios fuera de la tienda NGRX a través de la salida del componente  ( Triggering side effects outside the ngrx store via component output ) 
Tengo un módulo con un modal en el que hago un trabajo de formulario, el modal tiene su pequeña tienda de características. Cuando termine mi trabajo (gatill...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos