2010-12-08 4 views
6

Estaba trabajando en algún código F # y estaba trabajando en una función para devolver una cadena aleatoria de un conjunto de cadenas. Vamos a decir que he tenido algo como esto:¿Está devolviendo un valor aleatorio de la función A Side Effect?

open System 

let a = [|"a";"b";"c";"d"|] 

let rstring (arr:string[]) = 
    let r = new Random() 
    arr.[r.Next(0,3)] 

let resultstring = rstring a;; 

Mi pregunta es la siguiente: Mi comprensión de la noción de programación funcional es que si una función dada tiene la misma entrada cada vez que debería devolver siempre la misma salida. Entonces, ¿en este caso particular, devolver una cadena diferente cada vez es un "efecto secundario"? Tengo curiosidad.

Si esta es una pregunta duplicada, solo apúntame al original y cerraré esto. No estoy seguro de qué cadena de búsqueda utilizaría para encontrar preguntas relacionadas con esta.


EDIT: Gracias por toda la información a todos. Parece que combiné los conceptos de transparencia referencial y la falta de efectos secundarios. Entonces, gracias a todos por ponerme directamente en la diferencia y gracias por sus respuestas.

+0

Siempre devolver el mismo resultado para los mismos argumentos en realidad significa ser puro, no libre de efectos secundarios (las definiciones de los efectos secundarios ya se publicaron). – delnan

+4

Cuando comienzas a elegir liendres, los "efectos secundarios" no son un concepto interesante en el software. La transparencia y/o la pureza referencial son los conceptos interesantes/útiles, y las funciones aleatorias/no determinadas no son referencialmente transparentes, y eso es lo que importa. Entonces, en cierto sentido, el OP está haciendo la pregunta incorrecta, o al menos no es una pregunta interesante/útil. La pregunta planteada por el título selecciona liendres sobre definiciones. Lo que importa para el software es que si su función devuelve valores diferentes para las mismas entradas, entonces lo abre a toda una clase de errores. – Brian

+0

@delnan - pure por definición requiere que la función no tenga efectos secundarios. El hecho de que una función siempre devuelva los mismos resultados no la hace pura. –

Respuesta

13

Sí.

La única forma en que una función puede devolver diferentes valores de la misma entrada es a través de efectos secundarios. Otras personas pueden afirmar lo contrario, pero están equivocados.

(Puede afirmar que 'leer la hora del sistema' (que se basa claramente en los efectos) no es un efecto. Por esta definición, no es un efecto secundario. Pero esa definición no es útil, ya que el único motivo la gente "se preocupa" por los efectos secundarios porque afectan la transparencia referencial. En otras palabras, la transparencia referencial es lo único que importa, y esta función claramente no es referencialmente transparente.)

+0

Realmente, ¿qué tal un generador de números aleatorios conectado a hardware que monitorea el ruido atomosférico? ¿Por qué debería necesariamente cambiar el estado del programa? – tvanfosson

+9

El estado de la atmósfera ahora es parte del estado del programa. En una sala de aire completamente quieta, tal vez no haya un cambio de estado, pero ahora el aire de la sala es parte del cálculo que está modelando su programa de computadora. – Brian

+0

Para ampliar el punto de Brian, el estado del programa cambia en ese caso, incluso si no lo está cambiando explícitamente. (Pensar en ello de esta manera me ayudó, pensé que podría ayudar a otros) – Guvante

7

"Efecto secundario" significa que la función ha cambiado algún estado, no que el valor de retorno sea diferente. En su caso, la función está haciendo ambas cosas: está cambiando el estado del PRNG y devuelve un valor diferente.

Editar:

También voy a añadir que si una función siempre devuelve el mismo valor para una entrada dada se llama idempotente. Además, el "efecto secundario" incluye funciones que leen desde un estado externo. Por ejemplo:

int global = 0; 
int function() 
{ 
    return global; 
} 

tiene efectos secundarios.

+0

Buen punto sobre el PRNG: no había pensado en eso. –

+1

"* si una función siempre devuelve el mismo valor para una entrada determinada, se llama idempotente *" - Odio ser * esa chica *, pero lo que tienes es la definición de * puro *, no * idempotente * que se refiere a una función 'f' que satisface la propiedad' f (f (x)) == f (x) 'para todo x. 'let abs x = if x <0 then -x else x' es puro e idempotente desde' abs (abs (x)) == abs (x) '. La función 'let succ x = x + 1' es pura pero no idempotente ya que' succ (succ (x))!! = Succ (x) '. – Juliet

+0

@Juliet - matemáticamente hablando, eso es correcto. En ciencias de la computación he escuchado que el término "idempotente" significa tanto 'f (f (x)) == f (x)' AND que significa "siempre devuelve el mismo valor para una entrada dada". Quizás el término se esté usando incorrectamente. Además, pure tiene un significado mucho más estricto: una función siempre puede devolver el mismo valor para una entrada dada pero también causa efectos secundarios, lo que lo hace impuro. –

1

No creo que su ejemplo se considere un efecto secundario.

http://en.wikipedia.org/wiki/Side_effect_(computer_science)

+1

'Random()' causa efectos secundarios, por lo que rstring causa efectos secundarios. –

+0

@Niki: eso puede ser cierto en este caso específico, pero en general el simple hecho de devolver un valor indeterminado no es en sí mismo un efecto secundario. – tvanfosson

+0

@Niki ¿Cuáles son los efectos secundarios de Random()? –

3

Está bien para una función que no sea determinada. Eso no es un efecto secundario. Un efecto secundario sería si de alguna manera cambia el estado del programa además de devolver un valor. Diría que tanto los efectos secundarios como el no determinismo son formas en que las funciones en la programación funcional difieren de las funciones matemáticas.

+0

Bueno, sí cambia el estado del RNG. Aunque ese efecto secundario por sí solo no afecta la pureza (la incorporación del número aleatorio no puro en el resultado sí lo hace). – delnan

+0

@delnan - no confundas el ejemplo con la pregunta. La pregunta es si el no determinismo equivale a un efecto secundario. El hecho de que el ejemplo sea a la vez no determinado y tenga un efecto secundario no implica que el no determinismo sea un efecto secundario. – tvanfosson

+0

se hacen dos preguntas aquí. La pregunta del título: "¿Devolver un valor aleatorio de la función es un efecto secundario?" tiene una respuesta específica de "Sí". La pregunta más general: "¿El no determinismo es un efecto secundario?" tiene una respuesta diferente como usted señaló. Aunque no puedo pensar en un ejemplo de una función no determinista que no tenga efectos secundarios. –

2

Ignorando los detalles de implementación del generador aleatorio (que en la práctica requiere efectos secundarios, y en teoría no es necesario), esta función es libre de efectos secundarios pero no pura.

Básicamente imagine que la función de llamada es una máquina de oráculos que devuelve números aleatorios basados ​​totalmente en nada. Hay una prueba en alguna parte que dice que no puedes hacer esto, pero de momento solo imaginas que sea así.

Si trata una función de PRNG como esta máquina de oráculos que le da un número aleatorio cada vez que la solicita, es libre de efectos secundarios e impura, y la función hereda eso.

El tipo de efecto secundario que no viola la transparencia referencial a veces se denomina efecto secundario suave, ya que no altera el comportamiento del programa (nota: antes de decirme que la lectura del tiempo cambia el comportamiento del número generado, la especificación de la llamada de función dice que la función devuelve un número aleatorio. Leer el reloj de tiempo es un detalle de implementación para lograr que esa especificación funcione. Cambiar el reloj de tiempo (excepto en circunstancias extremadamente degeneradas) no altere el hecho de que la función devuelve un número aleatorio de psuedo, ya que la especificación no detalla cuál es ese número.

El ejemplo clásico de un efecto secundario suave es el registro, ya que los programas generalmente no inspeccionan sus registros y alteran comportamiento basado en eso.

Si quisiera hacer esto de una manera funcionalmente pura, tendría que implementar una mónada de estado.

http://fsharpcode.blogspot.com/2008/12/f-state-monad-type-state-state-state-of.html

Básicamente tener que hacer usted indica un generador de números aleatorios y la 'a un int, y entonces su flujo de control va a aislar la impureza a una sola función y crea un orden duro en la secuenciación.

Realmente no tiene sentido hacer esto en F #, ya que tener funciones impuras realmente no causa problemas (tener funciones con efectos secundarios, por otro lado, sí lo tiene).

Por supuesto que la mónada es impura, pero aísla muy bien la impureza.

Cuestiones relacionadas