Upgrade to Pro — share decks privately, control downloads, hide ads and more …

OCaml: Aprendendo programação funcional tipada

OCaml: Aprendendo programação funcional tipada

OCaml é uma linguagem de programação multiparadigma, que tem suporte de primeira classe para os paradigmas funcional, imperativo e orientado a objetos.

É uma linguagem que é descendente e traz fortes semelhanças com ML (Metalanguage) da qual herda (assim como outras linguagens descendentes de ML) ser estaticamente e fortemente tipada.

Seu principal diferencial que tem trazido notoriedade e popularidade para a linguagem é o seu compilador que é capaz de gerar código nativo com excelente desempenho em tempo de execução e uma biblioteca padrão muito bem construída e extensível.

Nessa apresentação estou mostrando o básico da sintaxe da linguagem e como utilizá-la para construir projetos com ela.

Camilo de Azevedo

August 07, 2022
Tweet

More Decks by Camilo de Azevedo

Other Decks in Technology

Transcript

  1. O que é OCaml? • OCaml é uma linguagem de

    programação multiparadigma, que tem suporte de primeira classe para os paradigmas funcional, imperativo e orientado a objetos. • É uma linguagem que é descendente e traz fortes semelhanças com ML (Metalanguage) da qual herda (assim como outras linguagens descendentes de ML) ser estaticamente e fortemente tipada. • Seu principal diferencial que tem trazido notoriedade e popularidade para a linguagem é o seu compilador que é capaz de gerar código nativo com excelente desempenho em tempo de execução e uma biblioteca padrão muito bem construída e extensível.
  2. História 1979 ML Robin Milner Robin Milner criou a linguagem

    ML (MetaLanguage) na Universidade de Edinburgo. O objetivo era criar uma linguagem para um dos primeiros provadores matemáticos automatizados, o LCF (Logic for Computable Functions). ML foi a primeira linguagem a trazer características como pattern matching, tipos estáticos em programação funcional e inferência de tipos HM (Hindley-Milner) que também foi sua descoberta junto ao lógico Roger Hindley. Ele é o Turing Award de 1991.
  3. História 1979 1980 ML SmallTalk Alan Kay Alan Kay cria

    Orientação a Objetos com Smalltalk como implementação de referência nos laboratórios da Parc (empresa subsidiária da Xerox). Smalltalk era parte do projeto de criação da primeira interface gráfica (GUI) para computadores pessoais e se tornou rapidamente uma linguagem muito popular para a programação de Sistemas Empresariais. Ele é o Turing Award de 2003.
  4. História 1979 1980 ML SmallTalk Ascánder Suárez É criado a

    linguagem Caml (Categorical Abstract Machine Language) escrita LISP por Ascánder Suárez no Institut national de recherche en sciences et technologies du numérique (INRIA) na França. Caml era uma implementação experimental de ML voltada para a pesquisa de Tipos e Provadores de Teoremas Automáticos. Ele é atualmente professor na Universidade Símon Bolívar na Venezuela. Caml 1987
  5. História 1979 1980 ML SmallTalk Xavier Leroy Xavier Leroy e

    Damien Doligez reescrevem Caml em C. Essa implementação foi chamada como Caml Light e passou a trazer novas features à linguagem em cada nova versão. Xavier é em eficiência de compiladores, com experiência prévia na otimização do compilador de C e Damien é especialista na otimização de algoritmos de Garbage Collection trazendo grandes otimizações para a linguagem. Caml Light tem o site original ainda ativo, onde se encontra a documentação e download de binários: https://caml.inria.fr/caml-light/ Caml 1987 1989 Caml Light Damien Doligez
  6. História 1979 1980 ML SmallTalk Didier Rémy Em 1996 Didier

    Rémy e Jérôme Vouillon adicionam Orientação a Objetos a Caml Light passando a chamar então a linguagem de OCaml (Obejective Caml). Essa adição foi resultado de uma extensa pesquisa sobre interoperabilidade segura e eficiente entre diferentes paradigmas em linguagens estáticas. Caml 1987 1989 Caml Light Jérôme Vouillon 1996 OCaml
  7. História 1979 1980 ML SmallTalk Jacques Garrigue No ano de

    2000, OCaml recebeu seu maior update feito por Jacques Garrigue que adicionou muitas novas funcionalidades e remodelou a sintaxe da linguagem para como é hoje. A partir de então, OCaml cresceu, com a ajuda da contribuição da Indústria, Comunidade e centros de pesquisa e que continua evoluindo e trazendo novidades. Caml 1987 1989 Caml Light 1996 OCaml 2000
  8. Instalando o OPAM • OPAM (OCaml Package Manager) é o

    gerenciador de dependências padrão de OCaml. A melhor forma de instalar a linguagem é primeiro instalá-lo e então usá-lo para instalar a linguagem. • Para isso basta usar o instalador de seu sistema operacional. $ sudo apt install opam • Após a instalação ser completada vamos dar init para inicializar as variáveis de ambiente e eval para carregá-las na nossa sessão atual. $ opam init $ eval $(opam env)
  9. Instalando OCaml • Após instalar o OPAM já vamos ter

    OCaml instalado podemos checar isso usando o comando: $ ocaml -version • Isso instalou também para nós as ferramentas ocaml, ocamlopt, ocamlrun, ocamlfind e ocamlc que vamos usar para compilar e executar nosso código. • Podemos usar o OPAM para mudar a versão de OCaml que estamos usando com o comando switch: $ opam switch create 4.11.1
  10. Instalando Dune • Vamos instalar também o Dune que é

    a ferramenta de build de OCaml. Ele vai ser responsável por compilar nossos projetos sem que tenhamos que ficar nos preocupando com vários detalhes de como fazer isso. • Podemos também fazer sua instalação pelo OPAM. $ opam install dune
  11. rlwrap • Para facilitar nossa vida, podemos usar o utilitário

    rlwrap para termos uma experiência melhor com OCaml. $ sudo apt install rlwrap • E então configurar um alias no nosso .bashrc para quando chamarmos o REPL de OCaml ele seja chamado antes. alias ocaml=”rlwrap ocaml”
  12. IDE

  13. Configurando o VS Code • A configuração do VS Code

    é bem simples você só precisa de um LSP (Language Server Protocol) de OCaml que você pode instalar pelo OPAM. $ opam install ocaml-lsp-server • E a extensão OCaml Platform.
  14. Iniciando o projeto • Para começar vamos iniciar um projeto

    com o Dune, isso já vai configurar os arquivos necessários para que possamos compilar e executar o projeto. $ mkdir helloworld && cd $_ $ dune init exe helloworld • Isso vai iniciar um projeto, com um arquivo “helloworld.ml” já com o códgio que imprime “Hello World” na tela, isso acontece porque o template básico de projeto do dune já vem preparado com Hello World. • Podemos ver o código com: $ cat helloworld.ml
  15. (Temporário) • O Dune atualmente está passando por algumas mudanças

    e atualmente ele não cria mais um arquivo de configuração necessário para compilar, isso será corrigido nas versões futuras. • O arquivo que falta é o “dune-project” caso ele não esteja na raiz do seu projeto basta criá-lo: $ echo "(lang dune 2.9)" >> dune-project
  16. Compilando e executando • Então executamos o comando de build

    que vai compilar o projeto e gerar um executável. $ dune build • E então executamos o projeto. $ dune exec ./helloworld.exe OBS: O executável criado mesmo em ambientes UNIX tem a extensão .exe
  17. Tipo Escrita Literal da Sintaxe int 314 float 3.14 ou

    6. char 'B' ou '\u0042' string "Foo" bool true ou false unit () 'a list [1; 2] 'a array [| 1; 2 |] tuple ("Capítulos", 3) records { x = 5; y = 9 } union type Dia = Segunda_Feira | Terca_Feira
  18. Função • Uma função é de uma forma simples, é

    um transformador (ou se prefirir: operação) que recebe um valor de entrada e devolve um valor de saída. • Típicamente existe um conjunto de possíveis entradas que são convertidos em seus respectivos valores de saída.
  19. Função • Uma função é como uma caixa preta (ou

    algoritmo) que recebe uma entrada (do conjunto de Domínio) e devolve uma saída (do Contra Domínio). • Uma função recebe um x (valor qualquer) e devolve um y. Essa função pode estar fazendo qualquer coisa, desde multiplicar o valor, elevar ao quadrado e etc… Função X -> -> f(x) || y
  20. Definição de uma função • Uma função é uma relação

    (lei de formação) de um conjunto A (chamado de Domínio) em um conjunto B (chamado de Contra-Domínio) que a associa todo elemento de A a um único elemento de B. • A imagem é o conjunto formado por todos os elementos de B ligados a um elemento de A. Ou seja, em Programês, Domínio são as entradas e o Contra-Domínio são as saídas.
  21. Função P • Nesse exemplo P é uma função de

    F-> C que recebe um elemento de F e devolve um elemento de C. • Para todo x pertecente ao A (Dom.) existe um elemento Y (CDom.) tal que P levao o X ao Y. (∀x∈A,∃!y∈B/P(x)=y).
  22. Função Pura • Função pura é uma função que utiliza

    apenas os dados recebidos para operar sua saída. • Uma vez dado uma entrada, sempre será retornado a mesma saída.
  23. Função Pura • Função pura é uma função que utiliza

    apenas os dados recebidos para operar sua saída. • Uma vez dado uma entrada, sempre será retornado a mesma saída.
  24. Aplicação de funções • A aplicação de função é o

    ato de aplicar as operações contidas em uma função sobre os argumentos com o objetivo de receber sua saída (resultado).
  25. Associatividade • Em OCaml as expressões sempre são associadas à

    esquerda, ou seja no nosso exemplo anterior temos (adiciona1 3) * 2 ao invés de adiciona1 (3 * 2). • A maioria das linguagens populares requerem parênteses e nesses casos isso pode não parecer importante, mas para linguagens que tem parênteses implícitos é necessário entendermos sua associatividade.
  26. Funções com múltiplos argumentos. • Quando uma função recebe múltiplos

    argumentos eles são colocados separados por espaço na definição da função. • Para chamar uma função com múltiplos argumentos apenas precisamos digitar seu nome seguido dos valores correspondentes ao seu número de argumentos separados por espaços.
  27. Assinatura de função • A assinatura da função nos diz

    os tipos de entrada e saída de uma função. • Na matemática a assinatura tem a forma de f: A -> B.
  28. Assinatura de função • Em OCaml a assinatura é na

    notação let nome : a -> b • Quando temos múltiplos argumentos usamos a aplicação de um a outro (assim como na matemática) ou seja let nome : a -> a -> b • Quando começamos a ler uma assinatura de função o primeiro valor que nos importa é o tipo após a última flecha que é o tipo de retorno da função e então todos os valores anteriores a última flecha são os tipos dos parâmetros que a função recebe. • Quando criamos uma função no REPL ele nos devolve a assinatura da função.
  29. Canalização de Funções • A canalização serve para passar um

    valor (que pode ser a saída de uma função) para outra. • Isso é feito usando o pipe operator que em OCaml é |> Função X -> Função -> f(x) || y
  30. Canalização de Funções • Simplifica as chamadas de função. •

    Faz uma sequência de chamadas de função uma após a outra recebendo o valor de saída da anterior. • Remove a necessidade dos parênteses de uma operação.
  31. Composição de Funções • A composição é quando conectamos a

    saída de uma de nossas funções a entrada de outra e armazenamos isso em uma nova função. Função X -> Função -> f(x) || y
  32. Como funcionam módulos • Você pode chamar o código de

    um arquivo OCaml que esteja na mesma pasta em outro usando a palavra open, OCaml irá tratar o nome do arquivo como um módulo. • Cada módulo separa expressões, funções e atriuições dentro de um “namespace”.
  33. Submódulos • Módulos podem também conter módulos, quando temos um

    módulo dentro de outro chamamos essa estrutura de submódulos (submodules) ou módulos aninhados (nested modules). Quando declaramos um módulo em um arquivo, este por sua vez automaticamente torna-se um submódulo do mesmo.
  34. Módulos e assinaturas • Podemos restringir a interface de um

    determinado submodulo declarado em nosso arquivo. • Isso é normalmente chamado de tipo de módulo (module type).
  35. Escrita separada • Podemos separar as assinaturas dos nossos módulos

    e funções. • Escrever isso em um único bloco de código nem sempre é elegante, é possível escrever a assinatura e as definições em blocos separados.
  36. Arquivos .mli • Podemos separar as assinaturas dos nossos módulos

    e funções. • No caso teriamos um arquivo eduardo.ml e outro eduardo.mli na mesma pasta com as assinaturas dos nossos módulos e funções. • O Dune facilita muito fazendo o binding automaticamente caso os arquivos tenham o mesmo nome, mas caso vá compilar usando ocamlc ou ocamlopt é preciso passar o nome da interface antes do arquivos com as definições e todas elas tem que ser passadas como argumento.