A linguagem de programação Clojure

Tire proveito do plug-in Clojure do Eclipse

Lisp é uma linguagem de programação conhecida por sua capacidade de expressão e poder, mas muitas vezes ela foi considerada como não adequada para uso geral. Isso tudo mudou com o Clojure, um dialeto derivado do Lisp que é executado na plataforma Java™. Agora você pode usufruir do poder do Lisp em qualquer lugar que você tenha uma Java Virtual Machine disponível. Neste artigo, você verá como começar a usar o Clojure e aprenderá um pouco sobre sua sintaxe enquanto tira proveito do plug-in Clojure do Eclipse para ajudá-lo nessa jornada.

Michael Galpin, Software architect, eBay

Michael_GalpinMichael Galpin é uma arquiteto do eBay e contribui com frequência para o developerWorks. Ele foi o palestrante em várias conferências técnicas, incluindo JavaOne, EclipseCon e AjaxWorld. Para uma pré-visualização do seu trabalho atual, siga @michaelg no Twitter.



26/Out/2009

Este artigo aborda a linguagem de programação Clojure. Clojure é um dialeto derivado do Lisp. Não se parte do princípio que você já conheça o Lisp. Ao invés disso, considera-se que você tenha conhecimento da tecnologia Java. Para escrever programas usando Clojure, você precisa de um Java Development Kit V5 ou mais recente e da biblioteca Clojure. Para este artigo, foram usados JDK V1.6.0_13 e Clojure V1. Você também deve tirar proveito do plug-in Clojure do Eclipse (clojure-dev) e precisará do Eclipse para isso. Para este artigo, foi usado o Eclipse V3.5 com clojure-dev 0.0.34. Consulte Recursos para obter os links.

O que é Clojure?

Não passou muito tempo desde que executar programas na Java Virtual Machine (JVM) significava escrever seu programa usando a linguagem de programação Java. Esses dias já se foram porque agora você tem muitas opções. Muitas opções populares como Groovy, Ruby (via JRuby) e Python (via Jython) permitem um estilo de programação com scripts mais processual ou eles têm sua própria forma de programação orientada a objetos. Esses são paradigmas familiares aos programadores em Java. Alguém poderia afirmar que, com essas linguagens, você escreve programas semelhantes aos que você escreveria na linguagem Java; você só teria que usar uma sintaxe diferente.

Clojure é outra linguagem de programação para JVM. No entanto, é bem diferente da tecnologia Java ou de qualquer outra linguagem para JVM mencionada. Ele é um dialeto derivado do Lisp. A família Lisp de linguagens de programação existe há muito tempo — desde os anos 50, na verdade. O Lisp usa as expressões S distintas ou a notação prefixo. Essa notação pode ser resumida como (argumentos de função...). Você sempre começa com o nome de uma função e liste zero ou mais argumentos a serem transmitidos para essa função. A função e seus argumentos estão organizados juntos, colocando-os entre parênteses. Isso leva a uma das marcas registradas da Lisp: muitos parênteses.

Como você pode supor, o Clojure é uma linguagem de programação funcional. Os acadêmicos podem debater sua "pureza", mas eles adotam definitivamente os pilares da programação funcional: evitam o estado mutável, recursão, funções de ordem mais alta, etc. Clojure também é uma linguagem digitada dinamicamente, embora você possa adicionar opcionalmente as informações de tipo para melhorar o desempenho para caminhos críticos em seu código. Clojure não só é executado na JVM, mas foi projetado com a interoperabilidade Java em mente. Finalmente, Clojure é uma linguagem projetada tendo a coincidência em mente e tem alguns recursos exclusivos relacionados à programação simultânea.


Exemplo de Clojure

Para muitos, a melhor maneira de aprender uma nova linguagem é iniciar o código de gravação. Neste sentido, assumiremos alguns problemas de programação simples e iremos solucioná-los usando Clojure. Percorremos as soluções em detalhes para obter uma compreensão melhor de como o Clojure funciona, como você pode usá-lo e que tipo de coisas que ele faz bem. No entanto, como qualquer outra linguagem, precisamos configurar um ambiente de desenvolvimento para trabalhar com ele. Felizmente isso é muito fácil com o Clojure.

Configuração mínima

Tudo que você precisa para trabalhar com o Clojure é um JDK e a biblioteca Clojure, que é um único arquivo JAR. Há duas maneiras comuns de desenvolver e executar os programas Clojure. O mais comum é usar read-eval-print-loop (REPL).

Listagem 1. REPL do Clojure
$ java -cp clojure-1.0.0.jar clojure.lang.Repl
Clojure 1.0.0-
user=>

O comando foi executado do diretório no qual o JAR do Clojure estava localizado. Ajuste o caminho ao JAR, conforme necessário. Você também pode criar um script e executá-lo. Para isso, você precisa executar uma classe Java chamada clojure.main.

Listagem 2. Clojure principal
$ java -cp clojure-1.0.0.jar clojure.main /some/path/to/Euler1.clj 
233168

Novamente, você precisa ajustar o caminho ao JAR do Clojure e seus scripts. Finalmente, há suporte IDE para Clojure. Os usuários do Eclipse podem instalar o plug-in clojure-dev usando o site de atualização do Eclipse. Depois de instalado, certifique-se de estar na perspectiva Java e, em seguida, você poderá criar um novo projeto Clojure e novos arquivos Clojure, como pode ser visto a seguir.

Figura 1. Usando clojure-dev, o plug-in Clojure do Eclipse
Using clojure-dev, the Clojure plug-in for Eclipse

Com o clojure-dev, você obtém alguns destaques de sintaxe básicos, incluindo coincidência de parênteses (primordial para qualquer Lisp). Você também pode iniciar qualquer script em um REPL que esteja incorporado diretamente no Eclipse. O plug-in ainda era muito novo no momento da publicação deste artigo e seus recursos estão avançando rapidamente. Agora que temos uma configuração básica fora do comum, vamos explorar a linguagem escrevendo alguns programas Clojure.


Exemplo 1: Trabalhando com sequências

O nome Lisp vem de "processamento em lista" e geralmente se diz que tudo no Lisp é uma lista. No Clojure, isso é generalizado como sequências. Para o primeiro exemplo, teremos o seguinte problema de programação.

Se nós listarmos todos os números naturais abaixo de 10 que são múltiplos de 3 ou 5, obteremos 3, 5, 6 e 9. A soma desses múltiplos é 23. Localize a soma de todos os múltiplos de 3 ou 5 abaixo de 1.000.

Esse problema é tirado do Projeto Euler, uma coleção de problemas matemáticos que podem ser resolvidos usando uma programação de computador inteligente (ou algumas vezes nem tão inteligente). Na verdade, esse é o Problema No. 1. A Listagem 3 mostra uma solução para ele usando o Clojure.

Listagem 3. Exemplo 1 do Projeto Euler
(defn divisible-by-3-or-5? [num] (or (== (mod num 3) 0)(== (mod num 5) 0))) 

(println (reduce + (filter divisible-by-3-or-5? (range 1000))))

A primeira linha define uma função. Lembre-se: as funções são os blocos de construção principais de programas em Clojure. A maioria dos programadores em Java está acostumada a objetos sendo blocos de construção de seus programas, portanto usar funções pode ser conveniente para alguns deles. Você pode pensar que defn é uma palavra-chave da linguagem, mas na verdade é uma macro. Uma macro permite que você amplie o compilador do Clojure para adicionar essencialmente novas palavras-chave à linguagem. Assim, defn não é parte da especificação da linguagem, mas é adicionada à biblioteca principal dela.

Nesse caso, ela está criando uma função chamada divisible-by-3-or-5?. Isso segue as convenções de nomeação do Clojure. As palavras são separadas por hífens, e o nome da função termina com um ponto de interrogação, indicando que ele é um predicado que retorna verdadeiro ou falso. A função assume um único parâmetro chamado num. Se houver outros parâmetros de entrada, eles aparecerão dentro de colchetes, separados por espaços.

Em seguida, vem o corpo da função. Primeiro, chamamos a função or. Esse é o or lógico normal com o qual estamos acostumados; é apenas uma função, não um operador. Nós a transmitimos aos parâmetros. Cada um desses também são expressões. A primeira expressão começa com a função ==. Isso faz uma comparação baseada em valor dos parâmetros transmitidos a ela. Há dois parâmetros transmitidos a ela. O primeiro é outra expressão; ela chama a função mod. Este é o operador de módulo da matemática ou o operador % na linguagem Java. Ele retorna o restante; neste caso, o restante quando num é dividido por 3. Esse restante é comparado a 0 (ele é o zero restante e, assim, num pode ser dividido por 3). Da mesma forma, verificamos que o restante quando num é dividido por 5 é 0. Se esses restantes forem 0, a função retornará verdadeira.

Na próxima linha, criaremos uma expressão e a imprimiremos. Vamos começar do conjunto de parênteses mais interno. Aqui, chamamos a função de intervalo e passamos o número 1.000. Isso criará uma sequência, começando com 0, de todos os números menores de 1.000. Este é exatamente o conjunto de números que queremos verificar se eles são divisíveis por 3 ou 5. Em seguida, chamaremos a função filter. Isso leva dois parâmetros: o primeiro é outra função que deve ser um predicado no qual ele deve retornar verdadeiro ou falso; o segundo parâmetro é uma sequência — nesse caso, a sequência (0, 1, 2, ... 999). A função filter se aplica ao predicado e, se for verdadeira, o elemento no sequência será adicionado ao resultado. O predicado é apenas a função divisible-by-3-or-5? definida na linha acima.

Portanto, a expressão filter resultará em uma sequência de números inteiros na qual cada um é menor do que 1.000 e divisível por 3 ou 5. É exatamente o conjunto de números inteiros no qual estamos interessados, portanto agora só precisamos adicioná-los. Para fazer isso, usaremos a função reduce. Essa função leva dois parâmetros: uma função e uma sequência. Ela aplica a função aos dois primeiros elementos na sequência. Em seguida, ela aplica a função ao resultado anterior e ao próximo elemento na sequência. Nesse caso, a função é a função + ou adição. Assim, ela adicionará todos os elementos na sequência.

Analisando a Listagem 3, muitas coisas acontecem em um pequeno código. Esse é um dos recursos do Clojure. Muitas coisas acontecem, mas depois que você se acostuma a usar a notação, o código é auto-explicativo. Certamente, serão necessários muito mais códigos Java para fazer a mesma coisa. Vamos ver outro exemplo.


Exemplo 2: Ociosidade é uma virtude

Para este exemplo, analisaremos a recursão e a ociosidade no Clojure. Este é outro conceito novo para muitos programadores Java. O Clojure permite que você defina as sequências que estão "ociosas" porque seus elementos não são calculados até que eles sejam necessários. Isso permite que você defina sequências infinitas e você definitivamente não as verá na linguagem Java. Para ver um exemplo de quando isso é especialmente útil, vamos analisar um exemplo que envolva outro aspecto importante da programação funcional: recursão. Novamente, usaremos um problema de programação do Projeto Euler, mas dessa vez será o Problema No. 2.

Cada novo termo na sequência Fibonacci é gerado, adicionando os dois termos anteriores. Começando com 1 e 2, os primeiros 10 termos serão: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

Localize a soma de todos os termos com valores pares na sequência para que não exceda 4 milhões. Para resolver este problema, um programador java pode tentar definir uma função que dê a ele o enésimo número Fibonacci. Uma implementação simplista disso é mostrada a seguir.

Listagem 4. Uma função Fibonacci simplista
(defn fib [n] 
    (if (= n 0) 0
        (if (= n 1) 1
            (+ (fib (- n 1)) (fib (- n 2))))))

Isso verifica se n é 0; se for, retornará 0. Em seguida, verifica se n é 1. Se for, retornará 1. Caso contrário, calculará o (enésimo-1) número Fibonacci e o (enésimo-2) número Fibonacci e os adicionará juntos. Isso está absolutamente correto, mas se você fez muita programação Java, verá o problema. Uma definição recursiva como essa preencherá a pilha rapidamente e levará a um estouro de pilha. Os números Fibonacci formam uma sequência infinita de forma que ela deveria ser descrita como sequências ociosas infinitas do Clojure. Isso é mostrado na Listagem 5. Observe que embora o Clojure tenha uma implementação Fibonacci mais eficiente que é parte da biblioteca padrão (clojure-contrib), ele é mais complexo, portanto a sequência Fibonacci mostrada aqui vem do livro de Stuart Halloway (consulte Recursos para obter mais informações).

Listagem 5. Uma sequência ociosa para números Fibonacci
(defn lazy-seq-fibo 
    ([] 
        (concat [0 1] (lazy-seq-fibo 0 1))) 
    ([a b] 
        (let [n (+ a b)] 
            (lazy-seq 
                (cons n (lazy-seq-fibo b n))))))

Na Listagem 5, a função lazy-seq-fibo tem duas definições. A primeira definição não tem argumentos, portanto há colchetes vazios. A segunda definição leva dois argumentos [a b]. Para o caso sem argumentos, obteremos a sequência [0 1] e a concatenaremos em uma expressão. Essa expressão é uma chamada recursiva para lazy-seq-fibo, mas dessa vez está chamando o caso com dois argumentos, transmitindo 0 e 1.

O caso com dois argumentos começa com uma expressão let. Essa é uma atribuição de variável no Clojure. A expressão [n (+ a b)] está definindo uma variável n e configurando-a igual a a+b. Portanto, ela está usando a macro lazy-seq. Como o nome sugere, a macro lazy-seq é usada para criar uma sequência ociosa. Seu corpo é uma expressão. Nesse caso, está usando a função cons. Essa é uma função clássica no Lisp. Ela leva um elemento e um sequência e retorna uma nova sequência, acrescentando o elemento ao início da sequência. Nesse caso, a sequência é o resultado de chamar novamente a função lazy-seq-fibo. Se essa sequência não estiver ociosa, a função lazy-seq-fibo será chamada repetidas vezes. No entanto, a macro lazy-seq garante que a função só será chamada quando os elementos forem acessados. Para ver essa sequência em ação, você poderá usar o REPL, como pode ser visto na Listagem 6.

Listagem 6. Gerando números Fibonacci
1:1 user=> (defn lazy-seq-fibo 
    ([] 
        (concat [0 1] (lazy-seq-fibo 0 1))) 
    ([a b] 
        (let [n (+ a b)] 
            (lazy-seq 
                (cons n (lazy-seq-fibo b n))))))
#'user/lazy-seq-fibo
1:8 user=> (take 10 (lazy-seq-fibo))
(0 1 1 2 3 5 8 13 21 34)

A função take é usada para obter um determinado número (neste caso, 10) de elementos de uma sequência. Agora que temos uma boa maneira de gerar números Fibonacci, vamos resolver o problema.

Listagem 7. Exemplo 2
(defn less-than-four-million? [n] (< n 4000000))

(println (reduce + 
    (filter even? 
        (take-while less-than-four-million? (lazy-seq-fibo)))))

Na Listagem 7, definimos uma função chamada less-than-four-million?. Isso simplesmente testa se sua entrada é menor do que 4 milhões. Na próxima expressão, é útil para iniciar a expressão mais interna. Primeiro obtemos a sequência Fibonacci infinita. Depois usamos a função take-while. Isso é como a função take, mas ela obtém um predicado. Assim que o predicado retorna falso, ele para de tirar da sequência. Portanto, nesse caso, assim que obtivermos um número Fibonacci maior do que 4 milhões, pararemos. Obtemos esse resultado e aplicaremos um filtro. O filtro usa a função even? interna. Essa função faz exatamente o que você está pensando: Ela testa se um número é par. O resultado é o total dos números Fibonacci inferiores a 4 milhões e que sejam pares. Agora calcularemos o total geral usando reduce, assim como fizemos no primeiro exemplo.

A Listagem 7 resolve o próximo problema, mas isso não é totalmente satisfatório. Para usar a função take-while, tivemos que definir uma função muito simples chamada less-than-four-million?. Ficou constatado que isso não é necessário. Não é surpresa que o Clojure não oferece suporte a fechamentos. Isso pode simplificar o código como o que pode ser visto na Listagem 8.


Fechamentos no Clojure

Os fechamentos são comuns em muitas linguagens de programação, especialmente em linguagens funcionais, como Clojure. Não apenas são funções especiais que podem ser transmitidas como argumentos a outras funções, mas também podem ser definidas em linha ou anonimamente. A Listagem 8 mostra uma simplificação da Listagem 7, usando um fechamento.

Listagem 8. Solução simples
(println (reduce + 
    (filter even? 
        (take-while (fn [n] (< n 4000000)) (lazy-seq-fibo)))))

Na Listagem 8, usamos a macro fn. Isso cria uma função anônima e a retorna. As funções de predicado geralmente são muito simples e melhor de serem definidas usando um fechamento. Quando ela é produzida, o Clojure tem uma maneira ainda mais abreviada de definir os fechamentos.

Listagem 9. Fechamento abreviado
(println (reduce + 
    (filter even? 
        (take-while #(< % 4000000) (lazy-seq-fibo)))))

Usamos # para criar o fechamento em vez da macro fn. Também usamos o símbolo % para o primeiro parâmetro transmitido para a função. Também seria possível usar %1 para o primeiro parâmetro e, da mesma forma, %2, %3, etc. se a função aceitar vários parâmetros.

Com apenas esses dois exemplos simples, vimos muitos recursos do Clojure. Um outro aspecto importante do Clojure é sua integração rígida com a linguagem Java. Vamos analisar outro exemplo no qual a otimização de Java a partir do Clojure é útil.


Exemplo 3: Usando a tecnologia Java

A plataforma Java tem muito a oferecer. O desempenho da JVM e a riqueza das APIs de núcleo junto com as diversas bibliotecas de terceiros escritas na linguagem Java são todas ferramentas poderosas que podem ajudá-lo a não ter que fazer muitas outras reinvenções. O Clojure foi criado com base nessas ideias. É fácil chamar os métodos Java, criar objetos Java, implementar interfaces Java e ampliar as classes Java. Para ver alguns exemplos disso, vamos analisar outro problema do Projeto Euler.

Listagem 10. Problema No. 8 do Projeto Euler
 Localize o maior produto de cinco dígitos consecutivos no número de 1.000 dígitos. 
73167176531330624919225119674426574742355349194934 
96983520312774506326239578318016984801869478851843 
85861560789112949495459501737958331952853208805511 
12540698747158523863050715693290963295227443043557 
66896648950445244523161731856403098711121722383113 
62229893423380308135336276614282806444486645238749 
30358907296290491560440772390713810515859307960866 
70172427121883998797908792274921901699720888093776 
65727333001053367881220235421809751254540594752243 
52584907711670556013604839586446706324415722155397 
53697817977846174064955149290862569321978468622482 
83972241375657056057490261407972968652414535100474 
82166370484403199890008895243450658541227588666881 
16427171479924442928230863465674813919123162824586 
17866458359124566529476545682848912883142607690042 
24219022671055626321111109370544217506941658960408 
07198403850962455444362981230987879927244284909188 
84580156166097919133875499200524063689912560717606 
05886116467109405077541002256983155200055935729725 
71636269561882670428252483600823257530420752963450

Neste problema, temos um número de 1.000 dígitos. Isso poderia ser representado numericamente na tecnologia Java usando BigInteger. No entanto, não precisamos fazer cálculos no número inteiro — somente cinco dígitos por vez. Assim é mais fácil tratá-lo como uma string. No entanto, para fazer cálculos, precisamos tratar os dígitos como números inteiros. Felizmente, há APIs na linguagem Java para ir e vir entre strings e números inteiros. Para começar, precisamos lidar com a grande parte de texto incontrolável do exemplo acima.

Listagem 11. Analisando o texto
(def big-num-str 
    (str "73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450"))

Aqui, tiramos proveito do suporte do Clojure a strings de várias linhas. Usamos a função str para analisar o literal de string de várias linhas. Em seguida, usamos a macro def para definir uma constante chamada big-num-str. No entanto, o que será mais útil para transformar isso em uma sequência de números inteiros? Isso será feito na Listagem 12.

Listagem 12. Criando uma sequência numérica
(def the-digits
    (map #(Integer. (str %)) 
        (filter #(Character/isDigit %) (seq big-num-str))))

Novamente, vamos começar na expressão mais interna. Usamos a função seq para transformar big-num-str em uma sequência. No entanto, constata-se que essa sequência não é exatamente o que queremos. Você pode ver isso com a ajuda do REPL, mostrado a seguir.

Listagem 13. Examinando a sequência big-num-str
user=> (seq big-num-str)
(\7 \3 \1 \6 \7 \1 \7 \6 \5 \3 \1 \3 \3 \0 \6 \2 \4 \9 \1 \9 \2 \2 \5 \1 \1 \9
 \6 \7 \4 \4 \2 \6 \5 \7 \4 \7 \4 \2 \3 \5 \5 \3 \4 \9 \1 \9 \4 \9 \3 \4
 \newline...

O REPL mostra caracteres (um caractere Java) como \c. Portanto, \7 é o caractere 7, e \newline é o caractere \n (uma nova linha). Isso é o que obteremos para analisar o texto diretamente. Obviamente precisamos nos livrar das novas linhas e convertê-las para números inteiros antes de podermos fazer qualquer cálculo útil. Isso é o que fizemos na Listagem 11. Lá usamos um filtro para remover as linhas novas. Observe mais uma vez que usamos um fechamento abreviado para a função de predicado transmitida para a função filter. O fechamento está usando Character/isDigit. Esse é o método estático isDigit de java.lang.Character. Assim, o filtro só permite caracteres que sejam dígitos numéricos, desconsiderando os caracteres de linha nova.

Agora que nos livramos das linhas novas, precisamos convertê-las para números inteiros. Movendo-se na Listagem 12, observe que usamos a função map, que leva dois parâmetros: uma função e uma sequência. Ela retorna uma nova sequência na qual o enésimo elemento da sequência é o resultado de aplicar a função ao enésimo elemento da sequência original. Para a função, novamente estamos usando a notação de fechamento abreviada. Primeiro usamos a função str do Clojure para converter o caractere em uma string. Por que fazemos isso? Porque em seguida criaremos um inteiro usando o construtor para java.lang.Integer. Isso é denotado pelo Número inteiro. Você poderia pensar nessa expressão como uma nova expressão java.lang.Integer(str(%)). Usando isso com a função map, obtemos uma sequência de números inteiros, como queríamos. Agora podemos resolver o problema.

Listagem 14. Exemplo 3
(println (apply max 
    (map #(reduce * %)
        (for [idx (range (count the-digits))] 
            (take 5 (drop idx the-digits))))))

Para entender essa parte do código, vamos começar com a macro for. Isso não é igual a um loop for na linguagem Java. Ao contrário, é uma compreensão de sequência. Primeiro, criamos uma vinculação usando os colchetes. Nesse caso, estamos vinculando a variável idx a uma sequência de 0 ... N-1 sendo que N é o número de elementos na sequência the-digits, (N = 1.000, uma vez que o número original tinha 1.000 dígitos). Em seguida, a macro for leva uma expressão que ela usa para gerar uma nova sequência. Ela repetirá cada elemento da sequência idx, avaliará a expressão e adicionará o resultado à sequência de retorno. Você poderá ver como, de várias formas, isso age como um loop for. A expressão usada na compreensão usará primeiro a função drop para descartar os primeiros elementos M da sequência, em seguida, use a função take para tirar os primeiros cinco elementos da sequência abreviada. Lembre-se de que M será 0, depois 1, depois 2, etc., portanto o resultado será uma sequência de sequências, sendo que o primeiro elemento será (e1, e2, e3, e4, e5), o próximo será (e2, e3, e4, e5, e6), etc., sendo que e1, e2, etc. são os elementos de the-digits.

Agora que temos essa sequência de sequências, usaremos a função map. Transformamos cada sequência de cinco números para o produto desses cinco números usando a função reduce. Agora temos uma sequência de números inteiros, sendo que o primeiro elemento é o produto de elementos 1-5, o segundo elemento é o produto de elementos 2-6, etc. Queremos o máximo de tal produto. Para fazer isso, usaremos a função max. No entanto, max espera vários elementos transmitidos a ele, não uma única sequência. Para transformar a sequência em vários elementos a serem transmitidos para max, usaremos a função apply. Isso produz o máximo que queremos para resolver o problema e obviamente imprime a resposta. Agora resolveremos vários problemas enquanto aprendemos a usar o Clojure ao mesmo tempo.


Resumo

Neste artigo, introduzimos a linguagem de programação Clojure e tiraremos benefício do uso do plug-in Clojure do Eclipse. Fizemos uma breve análise de algumas de suas filosofias e recursos, mas nos concentramos nos exemplos de códigos. Nesses exemplos simples, vimos muitos dos principais recursos da linguagem: funções, macros, vínculos, recursão, sequências ociosas, fechamentos, compreensões e integração co a tecnologia Java. Há dois muitos outros aspectos do Clojure. Felizmente, a linguagem chamou sua atenção e você analisará alguns dos recursos e aprenderá mais sobre ela.

Recursos

Aprender

Obter produtos e tecnologias

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre
ArticleID=439927
ArticleTitle=A linguagem de programação Clojure
publish-date=10262009