Palhaço
| palhaço | ||
|---|---|---|
|
| ||
| Desenvolvedor(es) | ||
|
Richard Hickey https://clojure.org/ | ||
| Informações gerais | ||
| Extensões comuns | clj, cljs, cljc, edn e cljr | |
| Paradigma | Linguagem de programação funcional e multiparadigma | |
| Apareceu em | 2007 | |
| Desenhado por | Chupão Rico | |
| Última versão estável | (2022-03-22) | |
| tipo de sistema | dinâmico , forte | |
| implementações | JVM , CLR , JavaScript | |
| influenciado por | Lisp , ML , Haskell , Erlang Prolog | |
| Sistema operativo | Multi plataforma | |
| Licença | Licença Pública Eclipse | |
Clojure é um dialeto de linguagem de programação de propósito geral de Lisp . Coloca uma ênfase especial no paradigma funcional , com o objetivo (entre outros) de remover a complexidade associada à programação concorrente . O Clojure pode ser executado na máquina virtual Java e na máquina virtual da plataforma .NET , bem como compilado para JavaScript .
Princípios
Rich Hickey descreve o desenvolvimento do Clojure como uma busca por uma linguagem que ele não conseguia encontrar: um lisp funcional por padrão, construído sobre um ambiente robusto ao invés de sua própria plataforma, e com programação concorrente em mente. [ 1 ]
Da mesma forma, a orientação a objetos é rejeitada em princípio, oferecendo uma abordagem na qual os programas são expressos como a aplicação de funções em dados, e não como a interação entre entidades mutáveis que misturam representação de dados e comportamento. Por outro lado, recursos como instanciabilidade, polimorfismo e interfaces são efetivamente parte da linguagem.
Sintaxe
Como o resto da família Lisp, a sintaxe do Clojure é construída em expressões simbólicas que são convertidas em estruturas de dados por um leitor antes de serem compiladas. As expressões são caracterizadas por serem delimitadas por parênteses, e por sua notação de prefixo, pela qual o primeiro membro de cada lista é chamado como função, passando o restante dos membros como argumentos.
Essa peculiaridade, estranha para quem está acostumado às linguagens mais populares baseadas na sintaxe da linguagem de programação C, é a base de sua flexibilidade. Estruturas de dados como mapas , conjuntos e vetores têm uma expressão literal; eles não requerem nenhuma transformação ao serem incorporados na árvore sintática gerada pelo compilador. Clojure é um Lisp-1 e não foi especialmente projetado para ser compatível com outros lisp .
Macro
Uma macro é um pedaço de código que aceita outras expressões como argumentos, sem avaliá-las, transformando-as antes de avaliá-las. Isso permite o surgimento de "programas criando programas": acréscimos à linguagem - estruturas de controle de fluxo - ou criação de uma linguagem específica de domínio . Possibilidades em princípio não alcançáveis em outras famílias linguísticas sem recorrer ao desenvolvimento de um compilador .
O sistema de macros do Clojure é muito semelhante ao do Common Lisp , com a exceção de que a versão do Clojure do backquote (chamado de "aspas sintáticas") qualifica os símbolos com o namespace ao qual eles pertencem. Isso ajuda a evitar a captura não intencional, pois as ligações qualificadas por nome são proibidas. É possível forçar a expansão de uma macro que os capture, mas isso deve ser feito explicitamente. Clojure também proíbe a religação de nomes globais em outros namespaces que foram importados para o atual.
Outra característica da citação sintática é que ela permite um sistema de modelagem , no qual você pode especificar quais membros de uma lista devem ser avaliados usando os operadores unquote (~) e unquote-splice (~@), levando a macros mais concisas e gerenciável.
Recursos de idioma
- Desenvolvimento dinâmico com um console de avaliação ( REPL: read eval print loop ).
- Representação de funções como valores e preferência por recursão e uso de funções de ordem superior sobre iteração com base em efeitos colaterais .
- Números de precisão arbitrária e representação literal de frações, gerados em divisões não inteiras.
- Sequências com avaliação lenta (os elementos da sequência não são computados até que sejam necessários, o que permite representar conjuntos potencialmente infinitos).
- Sistema integrado de estruturas de dados persistentes e imutáveis.
- Controle de estado (conjunto de valores que uma entidade pode adquirir ao longo do tempo) em situações de simultaneidade por meio de sistemas transacionais, agentes e por meio de ligações locais .
- Interação com java : Ao serem compilados em bytecode JVM , aplicativos escritos em Clojure podem ser facilmente integrados em servidores de aplicativos ou outros ambientes Java com pouca complexidade adicional. Todas as interfaces possíveis na classe, estrutura de dados e nível de simultaneidade são implementadas por padrão para minimizar os esforços necessários para alcançar essa portabilidade.
Exemplos
Olá mundo . Observe que, devido à natureza do REPL, um comando de impressão não é necessário .
"Olá mundo!"
Um gerador de números único e consecutivo que suporta chamadas simultâneas:
( let [i ( atom 0 ) ]
( defn generate-unique-id
"Retorna um identificador numérico diferente para cada chamada."
[]
( swap! i inc )))
Uma subclasse anônima java.io.Writerdisso não escreve em lugar nenhum, e uma macro que a usa para silenciar todas as expressões avaliadas com ela.
( def bit-bucket-writer
( proxy [java.io.Writer] []
( write [buf] nil )
( close [] nil )
( flush [] nil )))
( defmacro noprint
"Avalia a expressão dada com todas as impressões para *out* silenciadas."
[& forms]
` ( binding [*out* bit-bucket-writer]
~@forms ))
( noprint
( println "Olá, ninguém!" ))
Neste exemplo, dez threads manipulam uma estrutura de dados compartilhada, que consiste em cem vetores contendo dez números únicos de início sequencial. Cada thread escolhe duas posições aleatórias em dois vetores aleatórios e as troca. Todas as alterações nos vetores são feitas nas transações usando o sistema de memória transacional do software Clojure . É por isso que mesmo após mil iterações nenhum número é perdido.
( defn run [nvecs nitems nthreads niters]
( let [vec-refs ( vec ( map ( comp ref vec )
( partição nitems ( range ( * nvecs nitems ))))))
swap #( let [v1 ( rand-int nvecs )
v2 ( rand-int nvecs )
i1 ( rand-int nitems )
i2 ( rand-int nitems ) ]
( dosync
( let [temp ( nth @ ( vec-refs v1 ) i1 ) ]
( alter ( vec-refs v1 ) assoc i1 ( nth @ ( vec-refs v2 ) i2 ))
( alter ( vec-refs v2 ) assoc i2 temp ))))
report #( do
( prn ( map deref vec-refs ))
( println "Distinct:"
( count ( distinct ( apply concat ( map deref vec-refs )))))) ]
( report )
( dorun ( apply pcalls ( repeat nthreads #( dotimes [_ niters] ( swap )))))
( report )))
( executar 100 10 10 100000 )
Saída do exemplo anterior:
( [0 1 2 3 4 5 6 7 8 9] [10 11 12 13 14 15 16 17 18 19] ...
[990 991 992 993 994 995 996 997 998 999] )
Distinto: 1000
( [382 318 466 963 619 22 21 273 45 596] [808 639 804 471 394 904 952 75 289 778] ...
[ 484 216 622 139 651 592 379 228 242 355 ] )
Bibliografia
- Halloway, Stuart (28 de maio de 2009), Programming Clojure (1ª edição), Pragmatic Bookshelf , pp. 304 , ISBN 1934356336 .
- VanderHart, Luke (31 de dezembro de 2009), Practical Clojure (1ª edição), Apress , p. 350, ISBN 1430272317 , arquivado do original em 17/09/2010, recuperado em 10/02/2010 .
- Rathore, Amit (dezembro de 2009), Clojure in Action (1ª edição), Manning , p. 475, ISBN 9781935182597 .
- Fogus, Michael; Houser, Chris (janeiro de 2010), The Joy of Clojure (1ª edição), Manning , p. 300, ISBN 9781935182641 .
Links externos
- Clojure página principal
- Repositório de código Clojure no GitHub
- Uma visão geral do Clojure
- tutoriais em vídeo
- clojuredocs.org - documentação e exemplos da comunidade
- clojure-doc.org - Site de documentação orientado pela comunidade para a linguagem de programação Clojure
Referências
- ^ "Princípios fundamentais" . Rich Hickey (em inglês) . Recuperado em 2008-10-17 isto não tem paradigma .