Soy un novato completo con OCaml. Recientemente me topé con esta página que enumera una buena cantidad de críticas hacia OCaml.
Al ver que la página es bastante antigua (2007): ¿cuál de los puntos de viñetas enumerados allí todavía es cierto hoy en día? Por ejemplo: ¿sigue siendo cierto que es imposible imprimir un objeto genérico?
Quiero dejar en claro que no estoy buscando una discusión sobre las opiniones expresadas allí. Me pregunto si la información enumerada, como el hecho de que los enteros se desbordan sin advertencias, sigue siendo correcta para las versiones más recientes de OCaml
Respuestas:
Este artículo se discute en varios lugares:
Para resumir: sí, OCaml no es un Lisp, y no, no es perfecto (¿qué significa eso?). No creo que los puntos mencionados en la publicación del blog sean relevantes para los programadores del día a día de O'Caml.
Después de haber estudiado O'Caml, creo que es un lenguaje interesante que puede ayudarlo a crear programas en los que ni siquiera se atrevería a escribir, por ejemplo, C / C ++ / Java: por ejemplo, eche un vistazo a Frama-C .
Para una descripción actualizada de O'Caml, le animo a que lea sobre sus características : el lenguaje promueve fuertes técnicas de verificación de tipos estáticos que permiten que las implementaciones se centren en la producción de tiempos de ejecución performantes, pero seguros.
Importante : no soy un experto en OCaml: si eres uno de ellos y ves que escribí algo terriblemente mal, corrígeme. Editaré esta publicación en consecuencia.
Comprobación de tipo estático
Falsa sensación de seguridad
Esto es cierto, pero obvio.
La escritura estática le proporciona pruebas en las que puede confiar sobre un subconjunto de las propiedades de su programa. A menos que acepte ir todo formal, un programa promedio (que no sea de juguete) estará sujeto a errores de error de programación que solo se pueden observar en tiempo de ejecución.
Es entonces cuando se pueden aplicar técnicas de verificación dinámica: el compilador OCaml tiene marcas para generar ejecutables con información de depuración, y así sucesivamente ... O puede generar código que confía ciegamente en el programador y borra la información de tipo tanto como sea posible. Los programadores que desean programas robustos deben implementar comprobaciones dinámicas explícitamente.
Lo mismo se aplica, por ejemplo, a Common Lisp, pero se invierte: los tipos dinámicos primero, con las declaraciones de tipo opcionales y las directivas del compilador en segundo lugar.
Pocos tipos básicos
Todavía se aplica: el idioma principal no ha cambiado (o no de forma espectacular).
Desbordamiento de enteros silencioso
Esta es la norma en la mayoría de los idiomas en los que el desbordamiento de enteros se verifica manualmente. No conozco ninguna biblioteca que escriba operaciones de verificación para verificar si se puede producir un desbordamiento.
Módulo de inmutabilidad
El autor menciona a Functors pero no veo cómo no se puede implementar su ejemplo. Al leer el capítulo Módulos de primera clase de https://realworldocaml.org , parece que los módulos se pueden usar para componer y construir nuevos módulos. Por supuesto, la modificación de un módulo existente requiere la modificación del código fuente, pero nuevamente, esto no es inusual entre los lenguajes de programación.
" Semánticamente , las funciones se compilan EN LÍNEA"
El hilo de reddit anterior no está de acuerdo, diciendo que los enlaces se resuelven en el momento del enlace. Sin embargo, este es un detalle de implementación y creo que el énfasis semántico se relaciona con la forma en que se resuelven las funciones. Ejemplo:
El programa anterior se compila y, cuando se ejecuta, devuelve 5, porque
g
se define con la primera versión def
, como si la función de llamadag
incluyera la llamadaf
. Esto no es "malo", por cierto, es coherente con las reglas de sombreado del nombre de O'Caml.Para resumir : sí, los módulos son inmutables . Pero también son compostables .
El polimorfismo provoca errores de tipo en tiempo de ejecución
No puedo reproducir el error mencionado. Sospecho que es un error del compilador.
Sin macros
De hecho, no hay macros sino preprocesadores (OcamlP4, OcamlP5, ...).
Contenedores (con archivo abierto)
Sabiendo cómo UNWIND-PROTECT puede ser útil, es realmente doloroso verlo ausente en más idiomas. Aquí hay algunas opciones:
Lugares
No creo que existan referencias generalizadas en OCaml.
Suckiness de lenguaje menor
Campo de registro nombrando infierno
Es cierto, pero debe usar módulos:
Sintaxis
Todavía se aplica (pero realmente, esto es solo sintaxis).
Sin polimorfismo
Todavía se aplica, pero de alguna manera hay personas que prefieren eso en lugar de la torre numérica de Lisp (no sé por qué). Supongo que ayuda con la inferencia de tipos.
Conjuntos de funciones inconsistentes
Vea el proyecto de baterías incluidas de OCaml . En particular, BatArray , por ejemplo,
map2
para matrices.No hay variables dinámicas.
Puede ser implementado:
Los argumentos opcionales apestan
Por restricción de idioma, no puede mezclar argumentos opcionales y palabras clave en Common Lisp. ¿Significa que apesta? (por supuesto, esto se puede cambiar con macros (ver, por ejemplo, mi respuesta )). Consulte la documentación de O'Caml para ver argumentos opcionales y nombrados en O'Caml.
Inconsistencia de aplicación de argumento parcial
No creo que esto sea realmente molesto en la práctica.
Legibilidad de la aritmética
Se mantiene, pero puede usar R o Python para problemas numéricos si lo prefiere.
Nombre silencioso resolución de conflictos
Todavía se aplica, pero tenga en cuenta que esto está bien documentado.
No hay entrada / salida de objeto
Aún se aplica.
Implementación, bibliotecas
Estos siguen cambiando todos los días: no hay una respuesta definitiva.
Finalmente,
... todavía se aplica.
fuente
Falso sentido de seguridad . Esto no tiene sentido.
Pocos tipos básicos . OCaml ahora tiene bytes y matrices de bytes, pero no tiene cadenas unicode integradas, enteros de 16 bits, enteros sin signo, flotantes de 32 bits, vectores o matrices. Las bibliotecas de terceros proporcionan algunos de estos.
Desbordamiento de enteros silencioso . Sin cambios, pero nunca fue un problema.
Módulo de inmutabilidad . Su recomendación de que las funciones y los módulos deberían ser mutables es un retroceso sombrío para Lisp y una muy mala idea. Puede reemplazar módulos usando
include
si lo desea, pero no puede mutarlos, por supuesto.El polimorfismo provoca errores de tipo en tiempo de ejecución . Este es un gran problema con OCaml y no se ha solucionado. A medida que sus tipos evolucionan, la igualdad polimórfica, la comparación y el hash comenzarán a fallar cuando encuentren tipos como funciones y la depuración del problema es muy difícil. F # tiene una gran solución para este problema.
No hay macros . Irónicamente, cuando escribió este OCaml en realidad tenía soporte completo para macros, pero ahora han decidido retirar la función.
Envolturas . Este fue un problema real y no se ha solucionado. Todavía no hay una
try ... finally
construcción en el lenguaje OCaml y no hay un contenedor que la implemente en stdlib.Lugares . Sin cambios pero sin problemas.
Campo de registro nombrando el infierno . Estructura tu código correctamente usando módulos.
Sintaxis . Sin cambios pero sin problemas.
Sin polimorfismo . Esto no tenía sentido cuando lo escribió y nada ha cambiado.
Conjuntos de funciones inconsistentes . OCaml todavía no tiene una
cons
función. Esta bien. No quiero cosas de Lisp en mi idioma, gracias.No hay variables dinámicas . Fue algo bueno de OCaml. Todavía es algo bueno de OCaml.
Los argumentos opcionales apestan . Argumentos opcionales rock. Insulté a Microsoft para que agregara argumentos opcionales a F #.
Inconsistencia de aplicación de argumento parcial . Eh?
Legibilidad aritmética . Esto ha cambiado desde que dejé de usar OCaml ~ hace 8 años. Aparentemente ahora puedes hacerlo
Int64.((q * n - s * s) / (n - 1L))
.Nombre silencioso resolución de conflictos . Él estaba tratando de hacer un desarrollo de software completo en REPL como lo haría en Lisp. No hagas eso en OCaml. Utilice los archivos y la compilación por lotes recurriendo al REPL solo para probar, ejecutar código desechable y computación técnica interactiva.
Orden de evaluación . Esto estaba mal cuando lo escribió. El orden de evaluación no está definido en OCaml.
No hay entrada / salida de objeto . Citó una biblioteca de terceros que ya resolvió este "problema".
El compilador se detiene después del primer error . Eh?
No hay seguimiento de pila para ejecutables compilados de forma nativa . Fijo.
El depurador apesta . Nunca usé el depurador. La comprobación de tipo estático detecta casi todos mis errores.
GC apesta . Encontré que el GC de OCaml es excelente, excepto por un problema importante: el bloqueo global impide la programación paralela.
No hay declaraciones directas implícitas . La recursividad mutua es explícita por diseño en todos los NM. Lo único extraño es que las
type
definiciones son recursivas por defecto, mientras que loslet
enlaces no son recursivos por defecto.La ronda de funciones está ausente . OCaml todavía tiene un stdlib básico pero bibliotecas de terceros como Jane St's Core
round
y amigos.Listas .
List.map
Todavía no es recursivo de cola. Envié parches para corregir errores graves como este y tuve que esperar años antes de que aparecieran en los lanzamientos. Las listas siguen siendo inmutables, por supuesto. Y así deberían ser.Velocidad . Creo que los tiempos de compilación para grandes variantes polimórficas han sido corregidos.
Patronaje a juego . Un triunfo de la esperanza sobre la realidad. La comunidad de Lisp no ha podido hacer esto. De ahí mi décima regla: cualquier programa Lisp suficientemente complicado contiene una implementación ad hoc, especificada informalmente y llena de errores de la mitad del compilador de coincidencia de patrones de OCaml.
Cuando escribió que no podías simplemente hacer:
pero podría invocar la bonita impresora desde el nivel superior como una llamada a la biblioteca, dándole la información de tipo necesaria. Y había una macro que puedes usar para anotar estructuras de datos para tener impresoras bonitas autogeneradas.
fuente
cons
da un mal tono (el artículo original es una queja, pero no es necesario copiarlo).+
en ints, flotantes y complejos, pero también puede definir sus propios tipos y agregar una sobrecarga para+
trabajar en su tipo. Esto proporciona la brevedad y la legibilidad de Lisp o Haskell con el rendimiento previsiblemente bueno de SML u OCaml, logrando algo que ningún otro lenguaje hace.