Tendências em Linguagens de Programação

Hoje, no universo das linguagens de programação, fica clara a existência de uma fricção entre três dimensões distintas: 1) entre o mundo tipado e o não tipado; 2) entre o imperativo e o funcional; 3) entre linguagens específicas e linguagens genéricas.

Como trabalhei em projetos muito grandes, tendo a usar linguagens imperativas, genéricas e fortemente tipadas (como o C#), mas fico contente com a volta das linguagens sem tipos como Ruby ou Phyton. De certa forma, vejo estas linguagens forçando as linguagens tipadas a incorporar novos mecanismos que as tornem mais ágeis. Um exemplo claro disto é a incorporação da inferência de tipos tanto em VB quanto em C#, levando a uma simplificação no código (parece que o mesmo vai acontecer com o C++).

Linguagens funcionais é um caminho interessante para procurar novas tendências. Elas foram as primeiras a incorporarem os mecanismos de inferência de tipos e de “comprehensions” (como as cláusulas where do Linq) e trazem características declarativas que podem ser úteis para que os compiladores possam achar oportunidades de paralelismo. Elas têm algo da economia de linguagens não tipadas, com a precisão de tipos das linguagens tipadas. Por isto é grande a sua influência atual no design de linguagens.

Ainda sobre as linguagens funcionais, percebo que nem todos compreendem que elas funcionam a partir de regras de reescrita, o que as torna bem diferentes das demais. Por exemplo, em F# podemos definir uma função que retorna a soma entre dois números da seguinte forma:

> let add (x, y) = x+y;;

val add : int * int -> int

Como nas linguagens imperativas, podemos chamar add passando parâmetros:

> add (3,4);;

val it : int = 7

Mas existe uma forma chamada de curried (em homenagem ao matemático Haskell Curry) que pode ser definida na própria linguagem F#. Para isto precisamos apenas de um novo operador

> let curry f x y = f (x, y);;

val curry : ('a * 'b -> 'c) -> 'a -> 'b -> 'c

Esta forma de chamada nos permite tanto tirar os parêntesis na passagem de parâmetros (como abaixo)

> curry add 3 4;;

val it : int = 7

como nos permite definir uma nova função reutilizando nosso add de uma forma muito simples:

> let succ = curry add 1;;

val succ : (int -> int)

Com esta definição, podemos chamar a nova função succ como abaixo

> succ 4;;

val it : int = 5

Creio que este exemplo já dá um gostinho do poder de reescrita de uma linguagem funcional.

Interessante também é a perspectiva das linguagens específicas de domínio (DSL’s). Penso que, de certa forma, toda biblioteca ou framework gostaria de ser uma. Este conceito influenciou Ruby on Rails e atualmente influencia o projeto Oslo para modelagem de SOA da Microsoft. Vale a pena uma checada.

Para finalizar: esta disponível os vídeos do último simpósio do Lang.Net em https://langnetsymposium.com/. Este é um simpósio bem interessante entre experts no tema. Pena não haver tradução...

Dos que vi (e vi poucos) e recomendo:

  • a do Lars Bark que fala da otimização do JScript no Chrome (V8);
  • a do Erik Meijer sobre Observers;
  • e a do David Langworthy sobre Oslo (devo fazer um WebCast sobre Oslo e vou usar o exemplo dele…);

Bom simpósio.