¿Ruby es un lenguaje funcional?

88

Wikipedia dice que Ruby es un lenguaje funcional, pero no estoy convencido. ¿Por qué o por qué no?

Esteban Araya
fuente
4
Probablemente porque tu pregunta es muy corta, ¡aunque personalmente no tengo ningún problema con ella!
ljs
Ya hay buenas respuestas, así que solo para complementarlas, un par de contenidos que hablan de FP y Ruby: code.google.com/p/tokland/wiki/RubyFunctionalProgramming slideshare.net/tokland/functional-programming-with-ruby-9975242
tokland
1
Si alguien está interesado en este tema, mire esto y aprenderá cómo se puede usar ruby ​​de manera funcional, cuáles son las raíces de la programación funcional, por qué ruby ​​no es un lenguaje funcional incluso si es capaz de programar funcionalmente: youtube .com / watch? v = 5ZjwEPupybw
maddin2code

Respuestas:

29

Definitivamente creo que puedes usar un estilo funcional en Ruby.

Uno de los aspectos más críticos para poder programar en un estilo funcional es si el lenguaje admite funciones de orden superior ... lo que hace Ruby.

Dicho esto, también es fácil programar en Ruby en un estilo no funcional. Otro aspecto clave del estilo funcional es no tener estado y tener funciones matemáticas reales que siempre devuelvan el mismo valor para un conjunto dado de entradas. Esto se puede hacer en Ruby, pero no se aplica en el lenguaje como algo más estrictamente funcional como Haskell.

Entonces, sí, admite el estilo funcional, pero también te permitirá programar en un estilo no funcional.

Mike Stone
fuente
4
Usando este criterio, ¿diría que Smalltalk es funcional porque tiene bloques?
OscarRyz
Buena respuesta, pero un detalle: las funciones de orden superior no son estrictamente necesarias para un estilo funcional. Por ejemplo, puede lograr un estilo funcional en Java (que no tiene funciones de primera clase / orden superior) definiendo objetos de función y componiéndolos para obtener el mismo efecto que una función de orden superior.
mikera
2
Solo quiero decir que @peter preguntó Is ruby a functional language?y en una respuesta directa es un simple no. Ruby es un lenguaje orientado a objetos con algunas características funcionales.
Elias Perez
58

No importa si un idioma es o no un idioma funcional. La programación funcional es una tesis, mejor explicada por Philip Wadler (La esencia de la programación funcional) y John Hughes (Por qué importa la programación funcional).

Una pregunta significativa es: "¿Cuán dispuesto es Ruby a lograr la tesis de la programación funcional?" La respuesta es "muy mal".

Recientemente di una charla sobre esto. Aquí están las diapositivas.

Tony Morris
fuente
3
Las diapositivas que dio no mencionaron por qué Ruby es "muy poco susceptible de lograr la tesis de FP". ¿Por qué C # es más accesible que Java (OK, funciones anónimas más fáciles?)? ¿Es porque puedes tener variables globales en Ruby?
kizzx2
7
No, las diapositivas no entran en este detalle, ya que este es un tema bastante extenso. A riesgo de una simplificación excesiva, por ejemplo, Ruby aplica un modelo de evaluación (llamada por valor) que garantiza la no composicionalidad de los programas. Las implicaciones de esto pueden subestimarse fácilmente. Ruby también está casado con la idea de que un programa es una secuencia de efectos. Es decir, Ruby hace todo lo posible para que sea difícil / imposible utilizar cualquier otro modelo computacional. Espero que este breve comentario ayude.
Tony Morris
2
+1 por señalar la ambigüedad en la clasificación de idiomas como funcionales. Demonios, he escrito C funcional!
Eli
1
¿Por qué C # es más dócil que Ruby?
dan_l
1
Efectivamente, una respuesta de solo enlace, ya que subcontrata la parte crítica de la explicación (la explicación completa, de hecho) a un enlace externo. Ahora que el enlace murió, la respuesta se ha vuelto inútil.
ivan_pozdeev
34

Ruby admite funciones de nivel superior (consulte Array # map, inject, & select), pero sigue siendo un lenguaje imperativo orientado a objetos.

Una de las características clave de un lenguaje funcional es que evita el estado mutable. Los lenguajes funcionales no tienen el concepto de variable como lo tendrías en Ruby, C, Java o cualquier otro lenguaje imperativo.

Otra característica clave de un lenguaje funcional es que se centra en definir un programa en términos de "qué", en lugar de "cómo". Al programar en un lenguaje OO, escribimos clases y métodos para ocultar la implementación (el "cómo") del "qué" (el nombre de la clase / método), pero al final estos métodos todavía se escriben usando una secuencia de declaraciones. En un lenguaje funcional, no especifica una secuencia de ejecución, incluso en el nivel más bajo.

Miguel
fuente
3
Estoy de acuerdo con la mayor parte de su declaración, sin embargo, no estoy de acuerdo con "Los lenguajes funcionales no tienen el concepto de variables como lo tendría en Java, etc." En haskell puedes usar variables en funciones puras, incluso puedes asignar una función a una variable, la mayor diferencia es que una vez asignada una variable no se puede modificar posteriormente.
HHC
6
HHC, por definición, una variable es un valor que puede cambiar . De lo que estás hablando son de valores.
Scala Newb
De hecho, las "variables no modificables" de Haskell son solo funciones constantes sin parámetros (definiciones).
raindev
16

Presento que el apoyo o la capacidad de programar en un idioma con un estilo funcional no lo hace un lenguaje funcional.

Incluso puedo escribir código Java en un estilo funcional si quiero lastimar a mis colegas y a mí mismo durante unos meses. .

Tener un lenguaje funcional no se trata solo de lo que puede hacer, como funciones de orden superior, funciones de primera clase y currying. También se trata de lo que no puedes hacer, como los efectos secundarios en funciones puras.

Esto es importante porque es una gran parte de la razón por la que los programas funcionales, o el código funcional en general, es más fácil de razonar. Y cuando el código es más fácil de razonar, los errores se vuelven menos profundos y flotan hacia la superficie conceptual donde se pueden corregir, lo que a su vez genera menos errores en el código.

Ruby está orientado a objetos en su esencia, por lo que aunque tiene un soporte razonablemente bueno para un estilo funcional, no es en sí mismo un lenguaje funcional.

De todos modos, esa es mi opinión no científica.

Editar: En retrospectiva y teniendo en cuenta los excelentes comentarios que he recibido hasta ahora a esta respuesta, creo que la comparación entre la orientación a objetos y la funcional es una de manzanas y naranjas.

El verdadero diferenciador es el de ser impacientes en la ejecución, o no. Los lenguajes funcionales tienen la expresión como su construcción lingüística principal y el orden de ejecución a menudo no está definido o se define como perezoso. La ejecución estricta es posible, pero solo se usa cuando es necesario. En un lenguaje imparativo, la ejecución estricta es la predeterminada y, si bien la ejecución diferida es posible, a menudo es torpe y puede tener resultados impredecibles en muchos casos extremos.

Ahora, esa es mi opinión no científica.

Chris chaleco
fuente
Creo que puedes argumentar mucho mejor para llamar funcional a Ruby que a Java ... no, Ruby no es estrictamente funcional, pero es bastante fácil usar un estilo funcional en él ... y un colega de estilo no funcional puede cambiarlo fácilmente a no funcional
Mike Stone
1
Sí, Mike, si quieres codificar con un estilo funcional, Ruby es una gran mejora sobre Java. Solo estaba usando Java para exagerar y recalcar el punto.
Chris Vest
Entonces, dado que D tiene funciones puras, ¿llamarías a D un lenguaje funcional? digitalmars.com/d/2.0/function.html#pure-functions
Peter Burns
3
Mucha gente considera los lenguajes funcionales Lisp y Scheme, en gran parte debido al uso generalizado de funciones anónimas. Y, sin embargo, carecen de funciones puras garantizadas. Limitar el término a lenguajes que admiten funciones puras parece demasiado restrictivo.
skymt
13

Ruby tendrá que cumplir con los siguientes requisitos para ser funcional "REALMENTE".

Valores inmutables: una vez que se establece una "variable", no se puede cambiar. En Ruby, esto significa que efectivamente debe tratar las variables como constantes. No es totalmente compatible con el idioma, tendrá que congelar cada variable manualmente.

Sin efectos secundarios: cuando se le pasa un valor dado, una función siempre debe devolver el mismo resultado. Esto va de la mano con tener valores inmutables; una función nunca puede tomar un valor y cambiarlo, ya que esto causaría un efecto secundario que es tangencial a devolver un resultado.

Funciones de orden superior: son funciones que permiten funciones como argumentos o utilizan funciones como valor de retorno. Esta es, posiblemente, una de las características más críticas de cualquier lenguaje funcional.

Currying: habilitado por funciones de orden superior, currying es transformar una función que toma múltiples argumentos en una función que toma un argumento. Esto va de la mano con la aplicación de función parcial, que está transformando una función de múltiples argumentos en una función que toma menos argumentos de los que tenía originalmente.

Recursión: bucle llamando a una función desde su interior. Cuando no tiene acceso a datos mutables, la recursividad se usa para construir y encadenar la construcción de datos. Esto se debe a que el bucle no es un concepto funcional, ya que requiere que se pasen variables para almacenar el estado del bucle en un momento dado.

Evaluación perezosa o evaluación retardada: retrasar el procesamiento de valores hasta el momento en que realmente se necesita. Si, por ejemplo, tiene algún código que generó una lista de números de Fibonacci con la evaluación diferida habilitada, esto en realidad no se procesará ni calculará hasta que otra función requiera uno de los valores del resultado, como por ejemplo, put.

Propuesta (Solo un pensamiento) Sería genial tener algún tipo de definición para tener una modedirectiva para declarar archivos con paradigma funcional, ejemplo

modo 'funcional'

Elias Perez
fuente
2
De nada. Me gustaría invitarlos a leer sobre lenguajes funcionales. Lisp es el abuelo de todos los lenguajes funcionales, ML (CAML) y Erlang / Elixir. Realmente cambia tu perspectiva de las cosas. No soy un experto, pero soy un estudiante constante de informática que disfruta leyendo y aprendiendo cosas nuevas.
Elias Perez
Respuesta bien organizada. Me hubiera encantado una exploración adicional de lo bien que ruby ​​soporta estas cosas. Creo que las funciones de orden superior, el curry y la recursividad son compatibles / posibles en ruby, corríjame si me equivoco.
Michael Dorst
9

Ruby es un lenguaje de múltiples paradigmas que admite un estilo funcional de programación.

skymt
fuente
8
proporcionar evidencia
Mirzhan Irkegulov
4

Ruby es un lenguaje orientado a objetos, que puede soportar otros paradigmas (funcional, imperativo, etc.). Sin embargo, dado que todo en Ruby es un objeto, es principalmente un lenguaje OO.

ejemplo:

"hola" .reverse () = "olleh", cada cadena es una instancia de objeto de cadena y así sucesivamente.

Leer aquí o aquí

camflan
fuente
Nunca he entendido realmente cómo "todo es un objeto" hace que Ruby sea más orientado a objetos. Estoy de acuerdo en que Ruby es principalmente OO, pero "todo es un objeto" en realidad solo significa que no hay tipos "primitivos", lo que tiene muy poca relación con la capacidad del desarrollador para escribir programas en estilo OO, dado que la existencia de primitivos tipos generalmente solo significa que hay cuatro o cinco tipos que no tienen ningún método.
Michael Dorst
4

Depende de su definición de "lenguaje funcional". Personalmente, creo que el término en sí mismo es bastante problemático cuando se usa como un absoluto. Hay más aspectos de ser un "lenguaje funcional" que meras características del lenguaje y la mayoría depende de dónde se mire. Por ejemplo, la cultura que rodea al idioma es bastante importante a este respecto. ¿Fomenta un estilo funcional? ¿Qué pasa con las bibliotecas disponibles? ¿Te animan a utilizarlos de forma funcional?

La mayoría de la gente llamaría a Scheme un lenguaje funcional, por ejemplo. Pero, ¿qué pasa con Common Lisp? Aparte del problema del espacio de nombres único / múltiple y la eliminación garantizada de la llamada final (que también admiten algunas implementaciones de CL, según la configuración del compilador), no hay mucho que haga que Scheme sea un lenguaje más adecuado para la programación funcional que Common Lisp, y aún así, la mayoría de los Lispers no llamarían a CL un lenguaje funcional. ¿Por qué? Porque la cultura que lo rodea depende en gran medida de las características imperativas de CL (como la macro LOOP, por ejemplo, que la mayoría de los Schemers probablemente desaprobarían).

Por otro lado, un programador en C puede considerar CL como un lenguaje funcional. La mayoría del código escrito en cualquier dialecto Lisp es ciertamente mucho más funcional en estilo que su bloque habitual de código C, después de todo. Asimismo, Scheme es un lenguaje imperativo en comparación con Haskell. Por lo tanto, no creo que pueda haber una respuesta definitiva de sí o no. El hecho de llamar funcional o no a un lenguaje depende en gran medida de su punto de vista.

Matthias Benkard
fuente
¿De qué manera Haskell no es un lenguaje puramente funcional? ¿O qué tal Miranda (un lenguaje de programación funcional menos conocido)? course.cs.washington.edu/courses/cse505/99au/functional/… "Haskell es un lenguaje funcional puro estándar,"
barlop
2

Ruby tampoco es un lenguaje de paradigmas múltiples, creo. El multi-paradigma tiende a ser utilizado por personas que desean etiquetar su idioma favorito como algo útil en muchas áreas diferentes.

Describiría que Ruby es un lenguaje de secuencias de comandos orientado a objetos. Sí, las funciones son objetos de primera clase (más o menos), pero eso realmente no lo convierte en un lenguaje funcional. En mi opinión, podría agregar.

JesperE
fuente
4
El tipo de lenguaje se define por los estilos de programación que admite; eso, a su vez, se decide por las características que tiene. Funciones anónimas y de primera clase = programación funcional mínima. Ruby es compatible con la programación OO pero no la requiere: nunca es necesario definir una clase. Por lo tanto, multi-paradigma.
skymt
2

La recursividad es común en la programación funcional. Casi todos los lenguajes admiten la recursividad, pero los algoritmos recursivos suelen ser ineficaces si no hay optimización de llamadas finales (TCO).

Los lenguajes de programación funcional son capaces de optimizar la recursividad de la cola y pueden ejecutar dicho código en un espacio constante. Algunas implementaciones de Ruby optimizan la recursividad de la cola, las otras no, pero en general las implementaciones de Ruby no son necesarias para hacer TCO. Consulte ¿Ruby realiza la optimización de llamadas finales?

Por lo tanto, si escribe un estilo funcional de Ruby y confía en el TCO de alguna implementación en particular, su código puede ser muy ineficaz en otro intérprete de Ruby. Creo que esta es la razón por la que Ruby no es un lenguaje funcional (tampoco lo es Python).

Sastanin
fuente
El TCO es interesante porque esencialmente cambia el comportamiento del programa. En ciertos casos, esto no es visible para el programa, pero en otros casos, lo es, por ejemplo, trazas de excepción. Por lo tanto, no siempre es una optimización adecuada.
ioquatix
2

Estrictamente hablando, no tiene sentido describir un lenguaje como "funcional"; la mayoría de los lenguajes son capaces de programación funcional. Incluso C ++ lo es.

El estilo funcional es más o menos un subconjunto de características imperativas del lenguaje, compatible con azúcar sintáctico y algunas optimizaciones del compilador como la inmutabilidad y el aplanamiento de recursividad de cola,

Podría decirse que este último es un pequeño tecnicismo específico de la implementación y no tiene nada que ver con el lenguaje real. El compilador x64 C # 4.0 hace una optimización de recursividad de cola, mientras que el x86 no lo hace por alguna estúpida razón.

El azúcar sintáctico generalmente se puede trabajar en un grado u otro, especialmente si el lenguaje tiene un precompilador programable (es decir, #define de C).

Podría ser un poco más significativo preguntar "¿el lenguaje __ admite la programación imperativa?", Y la respuesta, por ejemplo con Lisp, es "no".

Rei Miyasaka
fuente
1

Por favor, eche un vistazo al principio del libro: "A-Great-Ruby-eBook" . Discute el tema muy específico que está preguntando. Puedes hacer diferentes tipos de programación en Ruby. Si desea programar como funcionalmente, puede hacerlo. Si desea programar como imperativamente, puede hacerlo. Es una pregunta de definición qué tan funcional es Ruby al final. Por favor, vea la respuesta del usuario camflan.

Léo Léopold Hertz 준영
fuente