Eu sou um novato completo com OCaml. Recentemente, deparei com esta página listando uma boa quantidade de críticas ao OCaml.
Visto que a página é bastante antiga (2007): quais dos pontos de bala listados ainda são verdadeiros hoje? Por exemplo: ainda é verdade que é impossível imprimir um objeto genérico?
Quero deixar claro que não estou buscando uma discussão das opiniões expressas nela. Estou perguntando se as informações listadas, como o fato de números inteiros excederem sem avisos, ainda estão corretas para versões mais recentes do OCaml
Respostas:
Este artigo é discutido em vários locais:
Para resumir: sim, o OCaml não é um Lisp e não, não é perfeito (o que isso significa?). Não acho que os pontos mencionados na postagem do blog sejam relevantes para os programadores do dia-a-dia do O'Caml.
Tendo estudado O'Caml, acho que é uma linguagem interessante que pode ajudá-lo a criar programas nos quais você nem ousaria escrever, digamos, C / C ++ / Java: por exemplo, dê uma olhada no Frama-C .
Para obter uma descrição atualizada de O'Caml, encorajo você a ler sobre seus recursos : a linguagem promove fortes técnicas de verificação de tipo estático que permitem que as implementações se concentrem na produção de tempos de execução com desempenho, ainda que seguros.
Importante : Não sou especialista em OCaml: se você é um deles e vê que escrevi algo terrivelmente errado, corrija-me. Vou editar este post de acordo.
Verificação de tipo estático
Falso senso de segurança
Isso é verdade, mas óbvio.
A digitação estática fornece provas em que você pode confiar em um subconjunto das propriedades do seu programa. A menos que você aceite ser formal, um programa médio (sem brinquedos) estará sujeito a erros de programação que podem ser testemunhados apenas em tempo de execução.
É quando as técnicas de verificação dinâmica podem ser aplicadas: o compilador OCaml possui sinalizadores para gerar executáveis com informações de depuração e assim por diante ... Ou pode gerar código que confia cegamente no programador e apaga as informações de tipo o máximo possível. Programadores que desejam programas robustos devem implementar verificações dinâmicas explicitamente.
O mesmo se aplica a, por exemplo, Common Lisp, mas invertido: tipos dinâmicos primeiro, com declarações de tipo opcionais e diretivas de compilador em segundo.
Alguns tipos básicos
Ainda se aplica: o idioma principal não mudou (ou não drasticamente).
Estouro de número inteiro silencioso
Essa é a norma na maioria dos idiomas em que o excesso de número inteiro é verificado manualmente. Não conheço nenhuma biblioteca que verifique operações de tipo para verificar se o estouro pode ocorrer.
Imutabilidade do módulo
O autor menciona Functors, mas não vejo como o exemplo dele não pode ser implementado. Lendo o capítulo Módulos da Primeira Classe de https://realworldocaml.org , parece que os módulos podem ser usados para compor e construir novos módulos. Obviamente, modificar um módulo existente requer modificação do código-fonte, mas, novamente, isso não é incomum entre linguagens de programação.
" Semântica , funções são compiladas INLINE"
O tópico do reddit acima discorda, dizendo que a ligação é resolvida no momento do link. No entanto, esse é um detalhe de implementação e acho que o enfatizado Semanticamente se relaciona à maneira como as funções são resolvidas. Exemplo:
O programa acima compila e, quando executado, retorna 5, porque
g
é definido com a primeira versão dof
, exatamente como se a função de chamadag
incluísse a chamadaf
. Isso não é "ruim", a propósito, é apenas consistente com as regras de sombreamento do nome de O'Caml.Resumindo : sim, os módulos são imutáveis . Mas eles também são compostáveis .
Polimorfismo causa erros de tipo em tempo de execução
Não consigo reproduzir o erro mencionado. Eu suspeito que seja um erro do compilador.
Sem macros
De fato, não há macros, mas pré-processadores (OcamlP4, OcamlP5, ...).
Wrappers (com arquivo aberto)
Saber como UNWIND-PROTECT pode ser útil, é realmente doloroso vê-lo ausente em mais idiomas. Aqui estão algumas opções:
Locais
Eu não acho que existam referências generalizadas no OCaml.
Suckiness menor da língua
Campo de registro nomeando o inferno
Verdadeiro, mas você deve usar os módulos:
Sintaxe
Ainda se aplica (mas, na verdade, isso é apenas sintaxe).
Sem polimorfismo
Ainda se aplica, mas de alguma forma existem pessoas que preferem isso em vez da torre numérica de Lisp (não sei por que). Suponho que ajude com inferência de tipo.
Conjuntos de funções inconsistentes
Veja o projeto de baterias incluídas do OCaml . Em particular, BatArray , por exemplo, de
map2
matrizes.Nenhuma variável dinâmica
Pode ser implementado:
Argumentos ~ opcionais são péssimos
Por restrição de idioma, você não pode misturar argumentos opcionais e de palavras-chave no Common Lisp. Isso significa que é uma merda? (claro, isso pode ser alterado com macros (veja, por exemplo, minha resposta )). Consulte a documentação de O'Caml para argumentos opcionais e nomeados em O'Caml.
Inconsistência de aplicativo de argumento parcial
Não acho que isso seja realmente irritante na prática.
Legibilidade da aritmética
É válido, mas você pode usar R ou Python para problemas numéricos, se preferir.
Resolução de conflitos de nomes silenciosos
Ainda se aplica, mas observe que isso está bem documentado.
Nenhum objeto de entrada / saída
Ainda se aplica.
Implementação, bibliotecas
Eles continuam mudando todos os dias: não há resposta definitiva.
Finalmente,
... ainda se aplica.
fonte
Falso senso de segurança . Isso não faz sentido.
Alguns tipos básicos . O OCaml agora possui matrizes de bytes e bytes, mas não possui cadeias unicode internas, números inteiros de 16 bits, números inteiros não assinados, flutuações de 32 bits, vetores ou matrizes. Bibliotecas de terceiros fornecem algumas delas.
Estouro Inteiro Silencioso . Inalterado, mas nunca foi um problema.
Imutabilidade do módulo . Sua recomendação de que funções e módulos devem ser mutáveis é um retrocesso sombrio para o Lisp e uma péssima idéia. Você pode substituir os módulos usando,
include
se quiser, mas não pode modificá-los, é claro.Polimorfismo causa erros de tipo em tempo de execução . Este é um grande problema com o OCaml e não foi corrigido. À medida que seus tipos evoluem igualdade polimórfica, a comparação e o hash começam a falhar quando encontram tipos como funções e a depuração do problema é muito difícil. O F # tem uma ótima solução para esse problema.
Sem macros . Ironicamente, quando ele escreveu isso, o OCaml realmente tinha suporte total para macros, mas agora eles decidiram retirar o recurso.
Wrappers . Este foi um problema real e não foi corrigido. Ainda não há
try ... finally
construção na linguagem OCaml e nenhum wrapper implementando-a no stdlib.Locais . Inalterado, mas sem problemas.
Campo de registro nomeando o inferno . Estruture seu código corretamente usando módulos.
Sintaxe . Inalterado, mas sem problemas.
Sem polimorfismo . Isso não fazia sentido quando ele escreveu e nada mudou.
Conjuntos de funções inconsistentes . O OCaml ainda não tem uma
cons
função. Isso é bom. Não quero coisas de Lisp no meu idioma, obrigado.Sem variáveis dinâmicas . Foi uma coisa boa sobre o OCaml. Ainda é uma coisa boa sobre o OCaml.
Argumentos ~ opcionais são péssimos . Argumentos opcionais. Instalei a Microsoft a fazê-los adicionar argumentos opcionais ao F #.
Inconsistência de aplicativo de argumento parcial . Eh?
Legibilidade da aritmética . Isso mudou desde que parei de usar o OCaml ~ 8 anos atrás. Aparentemente agora você pode fazer
Int64.((q * n - s * s) / (n - 1L))
.Resolução de conflito de nome silencioso . Ele estava tentando fazer um desenvolvimento de software completo no REPL, como você faria no Lisp. Não faça isso no OCaml. Use arquivos e compilação em lote recorrendo ao REPL apenas para teste, execução de código descartável e computação técnica interativa.
Ordem de avaliação . Isso estava errado quando ele escreveu. A ordem da avaliação é indefinida no OCaml.
Nenhum objeto de entrada / saída . Ele citou uma biblioteca de terceiros que já resolveu esse "problema".
O compilador para após o primeiro erro . Eh?
Nenhum rastreamento de pilha para executáveis compilados nativamente . Fixo.
Depurador é uma merda . Eu nunca usei o depurador. A verificação de tipo estático captura quase todos os meus erros.
GC é uma merda . Eu achei o GC do OCaml excelente, exceto por um grande problema: o bloqueio global impede a programação paralela.
Nenhuma declaração direta implícita . A recursão mútua é explícita por design em todos os MLs. A única estranheza é que as
type
definições são recursivas por padrão, enquanto aslet
ligações não são recursivas por padrão.A rodada de funções está ausente . O OCaml ainda tem um stdlib básico, mas bibliotecas de terceiros como o Core de Jane St fornecem
round
e amigos.Listas .
List.map
ainda não é recursivo da cauda. Enviei patches para corrigir erros graves como esse e tive que esperar anos antes de aparecerem nos lançamentos. As listas ainda são imutáveis, é claro. E assim deveriam ser.Velocidade . Acredito que os tempos de compilação para grandes variantes polimórficas foram corrigidos.
Correspondência de padrões . Um triunfo da esperança sobre a realidade. A comunidade Lisp falhou ao fazer isso. Daí a minha décima regra: qualquer programa Lisp suficientemente complicado contém uma implementação ad-hoc, especificada informalmente e cheia de erros, de metade do compilador de correspondência de padrões do OCaml.
Quando ele escreveu que você não podia simplesmente fazer:
mas você pode chamar a impressora bonita do nível superior como uma chamada de biblioteca, fornecendo as informações de tipo necessárias. E havia uma macro que você pode usar para anotar estruturas de dados, a fim de ter lindas impressoras geradas automaticamente.
fonte
cons
dá um tom ruim (o artigo original é um discurso retórico, mas você não precisa copiar isso).+
ints, floats e complexos, mas também pode definir seus próprios tipos e adicionar uma sobrecarga para+
trabalhar no seu tipo. Isso fornece à brevidade e legibilidade do Lisp ou Haskell o desempenho previsivelmente bom do SML ou OCaml, alcançando algo que nenhuma outra linguagem faz.