tipos programacion paradigmas orientada objetos los lenguajes funcional evolucion ejemplos conclusion programming-languages functional-programming comparison code-size

programming languages - programacion - Si los lenguajes funcionales son realmente concisos, ¿por qué no tienen un mejor rango en el juego de enfrentamientos lingüísticos?



programacion funcional vs orientada a objetos (9)

Los ganadores parecen ser simples lenguajes dinámicos.

Lisp es un ejemplo de contador obvio, ya que es un lenguaje simple y dinámico que es extremadamente detallado. Por otro lado, APL / J / K probablemente sería mucho más conciso que cualquiera de los otros idiomas y son dinámicos. También Mathematica ...

Haskell y Common Lisp no parecen ser más concisos que los Java de pretensión verbal.

Sus datos corresponden a pequeños programas que se han optimizado para el rendimiento y la medida es el tamaño del código después de la compresión utilizando el algoritmo GZIP en una configuración particular, por lo que no puede sacar conclusiones generales solo de ellos. Tal vez una conclusión más válida sería que esté observando la gran cantidad de resultados que se obtienen con las optimizaciones de rendimiento, por lo que los idiomas más concisos de sus datos son aquellos que no pueden optimizarse porque son fundamentalmente ineficientes (Python, Ruby, Javascript, Perl, Lua, PHP). Por el contrario, Haskell puede optimizarse con el esfuerzo suficiente para crear programas rápidos pero detallados. ¿Es eso realmente una desventaja de Haskell vs Python? Otra conclusión igualmente válida es que Python, Ruby, Perl, Lua y PHP comprimen mejor usando el algoritmo GZIP en esa configuración. ¿Quizás si repite el experimento utilizando codificación de longitud de ejecución o codificación aritmética o LZ77 / 8, quizás con el preacondicionamiento BWT, u otro algoritmo, obtendría resultados completamente diferentes?

También hay una gran cantidad de cruceros sin valor en el código de ese sitio. Mire este fragmento de código de OCaml que solo es necesario si su instalación de OCaml tiene dos generaciones desactualizadas:

(* This module is a workaround for a bug in the Str library from the Ocaml * distribution used in the Computer Language Benchmarks Game. It can be removed * altogether when using OCaml 3.11 *) module Str = struct include Str let substitute_first expr repl_fun text = try let pos = Str.search_forward expr text 0 in String.concat "" [Str.string_before text pos; repl_fun text; Str.string_after text (Str.match_end())] with Not_found -> text let opt_search_forward re s pos = try Some(Str.search_forward re s pos) with Not_found -> None let global_substitute expr repl_fun text = let rec replace accu start last_was_empty = let startpos = if last_was_empty then start + 1 else start in if startpos > String.length text then Str.string_after text start :: accu else match opt_search_forward expr text startpos with | None -> Str.string_after text start :: accu | Some pos -> let end_pos = Str.match_end() in let repl_text = repl_fun text in replace (repl_text :: String.sub text start (pos-start) :: accu) end_pos (end_pos = pos) in String.concat "" (List.rev (replace [] 0 false)) let global_replace expr repl text = global_substitute expr (Str.replace_matched repl) text and replace_first expr repl text = substitute_first expr (Str.replace_matched repl) text end

Las versiones de un solo núcleo a menudo contienen mucho código para el paralelismo, por ejemplo, regex-dna en OCaml . Mire la monstruosidad que está en fasta en OCaml : ¡el programa completo se duplica dos veces y cambia el tamaño de palabra! Tengo una vieja versión OCaml de fasta en disco aquí que es menos de una quinta parte del tamaño de esa ...

Finalmente, debo señalar que he contribuido con código a este sitio solo para que sea rechazado porque era demasiado bueno. Dejando de lado la política, los árboles binarios de OCaml solían contener la declaración "des-optimizado por Isaac Gouy" (aunque se eliminó el comentario, la desoptimización sigue haciendo que el código de OCaml sea más largo y lento), por lo que puede suponer que todos los los resultados se han medido subjetivamente específicamente para introducir sesgos.

Básicamente, con datos de tan baja calidad no puede esperar sacar conclusiones interesantes. Sería mucho mejor si tratara de encontrar programas más significativos que se hayan portado entre idiomas, pero incluso así, sus resultados serán específicos del dominio. Recomiendo olvidarse por completo del tiroteo ...

Comparé los idiomas en el juego de idioma shootout solo por el tamaño de su código . Aquí hay un resumen de lo que obtuve (primero el más corto, agrupado por puntaje similar).

  1. Python, Ruby, JavaScript, Perl, Lua, PHP, Mozart / OZ
  2. OCaml, Erlang, Raqueta, Go, Scala, F #, Smalltalk
  3. Pascal, Limpio, Haskell, Common Lisp, C #, Java, C
  4. C ++, Ada, ATS

Me pregunto porque. Los ganadores parecen ser simples lenguajes dinámicos. Erlang, Racket (née PLT Scheme) y F # están funcionando bien. Haskell y Common Lisp no parecen ser más concisos que los Java de pretensión verbal.

ACTUALIZAR:

He encontrado una publicación perspicaz sobre este tema con gráficos. También encontré una comparación similar de idiomas para un programa más grande (un trazador de rayos simple). En conjunto, no diría que obtuve "la" respuesta, pero sí algo para pensar.


Si los lenguajes funcionales son realmente concisos ...

1 - La programación en grande es diferente a la programación en pequeño .

Nada de esos pequeños programas de juegos de referencia debe tomarse como un ejemplo de cómo las abstracciones y la modularización provistas por cada lenguaje se aplicarían a la programación en general.

2 - La mayoría de lo que ve en las páginas de resumen del juego de referencia solo se refiere a los programas más rápidos que se aportan para cada implementación de idioma (los programas más lentos generalmente se eliminan del sitio web después de un tiempo: cuándo y qué programas más lentos se eliminan es principalmente arbitrario).

{edit: Adam, ya que no deseas tomar mi palabra de que las páginas de resumen solo se refieren a los programas más rápidos, mira el script que filtra las filas de datos para el "¿Qué lenguaje de programación es mejor?" página. Mire la línea 80 y la línea 82 en la función ValidRowsAndMins en lib_scorecard.php : Alioth emite su propio certificado de seguridad para que su navegador se queje.}

Entonces, para tomar Haskell como ejemplo, está viendo el tamaño del código de los programas Haskell más rápidos que se han contribuido.

3 - Ninguno de los programas de competencia de meteoros ha sido eliminado, y la competencia de meteoros es una competencia de programación sin restricciones: el programa Haskell más pequeño de la competencia de meteoros es el programa Haskell más lento de la competencia de meteoros .


  1. Ningún idioma es siempre superior a otro (bueno, hay algunas excepciones ...;), así que lo mismo se aplica a un grupo de idiomas ampliamente categorizados. Los puntos de referencia cubren una amplia gama de temas, y X puede ser menos adecuado para uno que Y.
  2. El código fuente está comprimido, no sabemos realmente cuántas líneas de qué longitud fueron los programas (sí, es un indicador)
  3. Un número considerable de lenguajes funcionales aún funciona mucho mejor que el imperativo generalizado, los lenguajes estáticos: no es que los lenguajes de programación funcionales no sean sucintos, pero los lenguajes dinámicos permiten programas aún más sucintos.
  4. Al menos en Haskell, gran parte del potencial de concisión proviene de las abstracciones que puedes construir tú mismo, pero tienes que construirlas tú mismo e incluirlas en tu solución. Un pirata informático inteligente de Haskell puede implementar una mónada en 20 líneas que permite resolver un problema pequeño en 20 líneas en lugar de 30; la abstracción no es rentable para un programa pequeño, pero puede ahorrar muchas líneas en un tamaño mayor (por ejemplo, 200 líneas) de 300) programa. Supongo que lo mismo se aplica a Lisps (solo macro en lugar de mónada)
  5. No te tomes demasiado en serio a los fanboys. FP es impresionante y vale la pena investigarlo, pero no cura el cáncer y no reduce mágicamente ningún código en un 25%
  6. Aún pueden vencer a los idiomas dinámicos en algunas áreas: por ejemplo, las estructuras de datos en forma de árbol y su procesamiento se expresan de forma extremadamente natural en muchos lenguajes funcionales, gracias a los tipos de datos algebraicos y la comparación de patrones.

Debe tener algo que ver con las extensas bibliotecas OOP disponibles para la mayoría de los idiomas en su nivel 1 y simplemente hacks antiguos como backticks para las llamadas de shell y la sintaxis de expresiones regulares de Perl. Saliendo de pitón

pw = file("/etc/passwd") for l in pw: print l.split('':'')[0]

Imprimir todos los nombres de usuario en un sistema, tomaría mucho más código si no fuera por las abstracciones con las que están llenos los idiomas OO. No estoy diciendo que no se pueda hacer en otros paradigmas, pero la tendencia es que cada tipo tiene muchas funciones miembro que simplifican las tareas tediosas. Personalmente, los lenguajes puramente funcionales solo son útiles para fines académicos (pero, de nuevo, lo que sé).


Debe tener en cuenta el hecho de que los lenguajes de su grupo 1 (scripting) son de 30 a 100 veces más lentos que C / C ++, ya que los lenguajes funcionales son de 2 a 7 veces. Los programas de la lista están optimizados para la velocidad y la medición de cualquier otra cosa es un problema secundario que no es realmente un buen indicador del estado real del idioma.
Es más interesante mirar la table donde el tamaño del código y el tiempo de ejecución tienen cada uno el peso 1. De esta manera, se obtiene una comparación de la relación velocidad / mantenibilidad, que parece una métrica mejor que solo el tamaño del código.


Debido a que algunos algoritmos son más concisos cuando se expresan funcionalmente y otros algoritmos son más concisos cuando se expresan de manera iterativa. En general, depende de cuánto se preocupe por las relaciones entre los datos y el estado actual de los datos.

También tenga en cuenta que puede realizar programación funcional en lenguajes como Python, y los programadores usarán FP en esos lenguajes para partes de su programa donde sea más conciso o eficiente hacerlo, a menudo sin saber que están haciendo FP. Mientras que con los lenguajes puramente funcionales, no tiene la opción de hacer programación iterativa en los casos en que sea más concisa o eficiente.


Esto parece una oportunidad para salir:

¿Hay estudios estadísticos que indiquen que Python es "más productivo"?

El punto es que la pregunta original es tratar de usar algunos datos (insignificantes, inapropiados) para hacer una generalización acerca de las comparaciones entre lenguajes de programación. Pero, de hecho, es casi imposible utilizar cualquier información para hacer cualquier tipo de comparaciones cuantitativas generales razonables sobre los lenguajes de programación.

Aquí hay algo para pensar, sin embargo:

  • En igualdad de condiciones, es probable que los lenguajes de tipo dinámico sean más concisos, ya que no necesitan dedicar tiempo a describir los tipos de datos
  • En igualdad de condiciones, entre los lenguajes de tipo estático, los lenguajes de tipo inferido son probablemente más concisos, ya que no necesitan declarar tipos por todos lados
  • En igualdad de condiciones, entre los lenguajes de tipo estático, es más probable que los que tienen genéricos / plantillas sean concisos, ya que los lenguajes sin ellos requieren código o conversión repetidos e indirección
  • En igualdad de condiciones, es probable que los lenguajes con una sintaxis lambda concisa sean más concisos, ya que lambda es quizás la abstracción más importante en la programación para evitar repeticiones y repeticiones.

Dicho esto, todas las cosas no son iguales, ni mucho menos.


Los programas en el juego Alioth no son realmente representativos de programas en esos idiomas en general. Por un lado, las implementaciones allí están altamente optimizadas para la infraestructura específica de Shootout, lo que puede llevar a un código menos idiomático e inflado en un lenguaje funcional. Es similar a cómo algunas bibliotecas de Ruby escribirán código crítico para el rendimiento en C: para ver ese código C y declarar que Ruby está inflado y el bajo nivel realmente no estaría dando una sacudida justa al lenguaje.

Por otro lado, una gran parte de por qué los lenguajes funcionales se consideran tan tersos es que son buenos para hacer abstracciones. Esto tiende a ayudar más en los programas grandes que en las funciones de una sola función, por lo que los lenguajes específicamente diseñados para facilitar la brevedad ganan mucho allí. Python, Perl y Ruby están diseñados específicamente para acortar los programas cortos, mientras que la mayoría de los lenguajes funcionales tienen otros objetivos (aunque eso no quiere decir que simplemente ignoren el tamaño del código).


Recientemente he portado un programa Java relativamente corto a OCaml. He incursionado en SML y Haskell en el pasado, además de una amplia experiencia con C.

En esta respuesta, abordo una comparación de código imperativo a puramente funcional (es decir, sin mutaciones). Si permites que el código imperativo se introduzca en programas funcionales, ¿qué estás comparando?

En mi experiencia, la programación puramente funcional (PFP) es elegante, pero no más concisa que imperativa. Hay menos "declaraciones" repetidas en PFP pero más "conversión" repetidas; por ejemplo, desempaquetar de tuplas, funciones auxiliares recursivas de la cola, etc. Por lo tanto, ninguno de los dos paradigmas permite la expresión libre de la "carne" pura de un programa.

PFP tiene costos más bajos para hacer funcionar algo, y escribir un programa para demostrar que un algoritmo dado funciona, en principio, funciona bien en PFP. Sin embargo, aumentarlo para que sea "real", hacer que se ocupe de las condiciones de error y los diagnósticos de entrada e impresión ilegales agrega una gran cantidad de información que se habría superado más fácilmente en un lenguaje imperativo.