O primeiro questionamento que surge quando decidimos estudar uma nova tecnologia é por quê? Por que dentre tantas tecnologias e frameworks emergentes deveríamos escolher àquela em detrimento de outra?

Vou listar alguns motivos que me fizeram escolher F# como a linguagem de entrada para o mundo funcional. O objetivo não é explicar funcionalidades ou teorias nesse momento (isso vai ficar para os artigos posteriores), mas sim apresentar alguns conceitos chaves e vantagens que o F# traz para o desenvolvimento.

multiparadigma com foco no estilo funcional

F# é uma linguaguem primariamente funcional, mas que suporta muito bem orientação à objeto e o estilo de programação imperativo. Aprender uma linguagem com um paradigma diferente da que estamos habituados faz com que olhemos para um problema de diferentes perspectivas, fornecendo melhores soluções.

O fato do F# ser uma linguagem híbrida faz com que a transição para o mundo funcional seja mais tranquila. Sempre se pode comecar com uma abordagem imperativa e evoluir gradativamente para uma abordagem funcional. Outra grande vantagem do F# suportar o estilo imperativo é que a interação com o mundo real não puro, onde se espera que ações mudem algum estado, se torna muito mais fácil.

legibilidade de código

F# não possui instruções como chaves ou ponto e vírgula tornando o código menos verboso e mais legível. Essa é uma opinião minha, existe um debate longo sobre chaves Vs. espaços para delimitar blocos de código. Acredito que um desenvolvedor consiga se focar mais no código quando não precisa se preocupar em controlar explicitamente os blocos de código. Mas ainda sim, é uma questão de preferência.

F# possui uma ótima inferência de tipos, na maioria das vezes, não será preciso anotar tipos explicitamente.

É possível controlar fluxo de chamadas para tornar uma expressão mais legível. Nosso modelo de leitura no Brasil é ocidental. Naturalmente lemos um texto de esquerda para direita, de cima para baixo. Mas se encadear diretamente chamadas de funções, teremos algo como:

var resultado = SomarValores(
        ElevarAoQuadrado(new []{1,2,3})
      )

Note que nesse trecho de código a ordem de leitura é da direita para esquerda, de baixo para cima. Pois, primeiro elevamos os valores do array ao quadrado para depois soma-los. A ordem de aplicação das funções é o oposto da ordem natural de leitura ao qual estamos acostumados. Podemos atribuir variáveis para melhorar a legibilidade, mas não é uma ótima solução.

Em F# podemos inverter o fluxo e encadear através do operador pipe:

let resultado = [|1;2;3|] 
    |> ElevarAoQuadrado 
    |> SomarValores

Falaremos em outro artigo sobre o operador pipe, o importante agora é notar que respeitamos a ordem natural de leitura ocidental, o que torna o código mais natural.

Comparado a uma linguagem imperativa, geralmente se utiliza menos linhas de código para resolver o mesmo problema. Uma análise detalhada de alguns projetos comparados à C# foi publicada aqui.

declaratividade para prevenção à erros

F# possui um poderoso sistema de tipos que permite ser explicitamente declarativo sobre as expressões desenvolvidas. Assim, é possível prevenir Null Reference Exceptions de forma mais fácil.

let resultado = LerArquivo caminho
match resultado with
  | Sucesso arquivo -> printfn "Arquivo encontrado: %A" arquivo
  | Falha -> printfn "Arquivo não encontrado"

Não se incomode caso não tenha entendido esse código 100%. O importante é entender que a função LerArquivo poderá retornar um resultado de Sucesso ou de Fracasso.

É possível codificar o domínio utilizando dos benefícios do sistema de tipos. O resultado é um domínio granular e a facilidade em tornar estados ilegais não compiláveis.

Com a facilidade em tornar estados ilegais não compiláveis, a suite de testes será menor, já que testes de regressão para verificar estados ilegais não serão necessários.

facilidade e aplicações

F# possui uma vasta gama de aplicações. Ele pode ser utilizado para scripting(Fsi), desenvolvimento web(Fable, Suave, Websharper), mobile(Xamarin) e desktop(WPF, Eto). Também pode ser utilizado em data science(FsLab). São inúmeras possibilidades.

Muitas tarefas são mais simples de desenvolver em F#, como criação de tipos complexos, comparação e igualdade, processamento de listas, modelagem de máquina de estados, etc…

concorrência

A facilidade em desenvolver sistemas concorrentes é um atributo da programção funcional. Como valores são nativamente imutáveis, compartilhar estado e evitar locks é muito mais fácil. Programação assíncrona, programação reativa, event handling também ficam mais fácil em F#.

F# também tem suporte direto para fila de mensagens:

let processarInbox inbox = 
  let rec loop() = async {
        let! msg = inbox.Receive()
        printfn "mensagem é: %s" msg
        return! loop()  
        }
  loop()

let agente = MailboxProcessor.Start processarInbox

interoperabilidade com C#/ integração com ecossistema .NET

Por F# ser considerado um superset do C# e também por ser uma linguagem híbrida integrar código C# é uma tarefa simples e totalmente víavel. Assim é possível tirar proveito das várias bibliotecas e frameworks do ecossistema .NET.

type providers

Provavelmente você já ouviu falar de type providers. É a feature mais conhecida do F#. É uma extensão que permite o compilador acessar valores externos em tempo de compilação.

use cmd = new SqlCommandProvider<"
        SELECT TOP(@topN) Nome, Sobrenome
        FROM Clientes
        WHERE Id = @id
        " , conexao>(conexao)

cmd.Execute(topN = 3L, id = 235L) |> printfn "%A"

Os valores topN e id são definidos em tempo de compilação gerados pelo type provider do SQL em SqlCommandProvider.

comunidade

A comunidade F# é bastante acolhedora, se você precisar de ajuda, certamente alguém estará disponível. F# é mantido pela F# Foundation que recomendo que você entre. Tem muita coisa bacana lá, e depois que você entrar, receberá o link para participar do slack. Lá poderá perguntar qualquer coisa, as pessoas realmente são solidárias e pacientes com iniciantes.

conclusão

Espero que tenha conseguido passar as motivações necessárias para que você comece também essa jornada. Esse post também contém algumas “promessas” que espero desvendar nos próximos artigos. Se tiver alguma dúvida é só me procurar nos comentários ou quaisquer meios, estou longe de ser proficiente em F#, mas prometo que tentarei ajudar!

Função na imagem do post criada por Lucas Cé Bertin

Abraços,
Francisco

(Cross-post de https://chicocode.io/pt-br/posts/porque-aprender-fsharp/)

Francisco Berrocal