Pular para o conteúdo principal

Clojure - Funções, vetores e def

Nessa postagem escreveremos nossas primeiras linhas de código com o Clojure, aqui tentaremos trazer alguns conceitos para mais perto de quem já programa com os paradigmas mais tradicionais (orientação a objetos por exemplo), de modo que fique mais simples entender as intenções e começarmos a correlacionar alguns pontos, mesmo que alguns deles não sejam necessariamente a mesma coisa.

Funções

Como já é de conhecimento, funções são pequenas partes de um programa que executam um trabalho e devolvem um resultado, e para que esse trabalho seja realizado muitas vezes é necessário informar argumentos ou informações para que algo seja feito.

Em Clojure toda invocação de uma função ocorre dentro de parênteses, logo podemos interpretar o conteúdo que esta dentro dos parênteses da seguinte forma:

  • O primeiro valor é a função a ser executada;
  • O segundo valor é o primeiro argumento que a função receberá;

Vamos agora ao nosso primeiro exemplo, iremos chamar uma função que escreve no console, passando como "argumento" o famoso "Olá Mundo!":

(println "Olá Mundo!")

Nosso primeiro comando!

Vamos falar sobre a imagem agora, linha por linha:
  1. Na primeira linha estamos iniciando o Clojure com o comando "clj";
  2. Na segunda linha nos é apresentada a versão atual (1.10.3);
  3. Na terceira linha começamos a escrever nosso primeiro código, chamando a função "println";
  4. Na quarta linha temos o resultado da execução interna da função "println", que é a escrita no console da frase que informamos como "argumento";
  5. Na quinta linha temos o retorno da função "println", como ela não retorna nada recebemos nulo (nil);
  6. Na sexta e última linha temos o controle a disposição novamente para informar os próximos comandos;

Ainda sobre funções vale destacar que os operadores matemáticos também são considerados como funções, logo se quisermos somar dois números, por exemplo, precisaríamos iniciar a expressão com o operador de soma, seguido dos "argumentos" (números) que desejamos somar:

(+ 1 2)

Iniciar a a expressão com um número, utilizando um padrão de operação comum nas linguagens  de programação mais tradicionais resultaria em erro, uma vez que o Clojure tentaria interpretar um número como uma função:

(1 + 2)

Somando dois números

Na imagem acima vemos os dois exemplos, o primeiro com o resultado correto, onde a soma é o primeiro parâmetro e o segundo com o resultado incorreto, onde o Clojure nos diz que o número informado não é uma função.

 

def

Quando estamos programando é trivial mantermos determinados valores (independente do tipo) armazenados em memória, para podermos acessá-los durante a execução de uma aplicação ou função e comumente realizamos isso por meio de "variáveis", sendo justamente esse o conceito que utilizaremos agora para tentar entender o "def".

Com o "def" criamos (ou definimos) símbolos que nos permitem salvar e recuperar determinados valores, funcionando de forma semelhante a uma variável, sua sintaxe é simples, e funciona como uma função, onde temos a função propriamente dita, o símbolo a ser criado/atualizado e o valor que pretendemos associar ao símbolo:

(def total-de-alunos 25)

Para poder ver o valor armazenado em nosso símbolo podemos usar o "println" ou podemos ver seu conteúdo simplesmente digitando o nome do símbolo (fora de parentes é claro):

(println total-de-alunos)

total-de-alunos

Definindo um símbolo e vendo seu conteúdo

Na imagem acima vemos o seguinte:

  • Na linha três a definição do símbolo "total-de-alunos" com o valor "25";
  • Na linha quatro o retorno que nos indica o espaço onde nosso símbolo esta gravado (user);
  • Na linha cinco executamos a função "println" para ver o conteúdo;
  • Na linha oito verificamos o valor do símbolo diretamente, sem o uso de uma função;
  • Nas linhas seis e nove podemos ver o valor armazenado no símbolo;

Para alterar o valor de um símbolo basta utilizarmos o "def" novamente, informando o identificador e o novo valor, esse novo valor pode ser um número fixo (como vimos anteriormente) ou pode ser a execução de uma outra função:

(def total-de-alunos 30)

(def total-de-alunos (+ total-de-alunos 5))


Alterando o valor do símbolo

Podemos observar na imagem acima:

  • Na linha um definimos um novo valor para o símbolo;
  • Na linha três pedimos para ver o novo valor e na linha quatro o vemos (30);
  • Na linha cinco alteramos o valor novamente, fazendo com que o novo valor seja o valor já existente "30" somado a "5";
  • Na linha sete pedimos para ver o novo valor e na linha oito o vemos (35);


Vetores

Quando começamos a aprender uma nova linguagem de programação umas das primeiras estruturas que aprendemos para armazenar uma série de elementos é o vetor, em Clojure não é diferente, a exemplo do que vimos anteriormente, iremos usar o "def" para definir um símbolo ficando por conta do valor atribuído a definição desse vetor, em nosso caso iremos atribuir uma série de nomes entre colchetes:

(def alunos ["Maria", "Flávia", "Teresa"])

Perceba que no comando acima utilizamos "virgulas" para separar os elementos, mas o que conta mesmo para essa separação são os espaços, a virgula esta ali apenas como uma boa prática que nos permite identificar melhor os itens (inclusive as virgulas são consideradas como espaços no Clojure).

Para ver os itens de nosso vetor podemos usar tanto as formas já vistas até aqui, com o "println" ou digitando o nome do símbolo diretamente, o que resulta na apresentação de todos os valores ou podemos acessá-los por meio de suas posições, nesse último caso o vetor acaba funcionando como uma função que recebe como parâmetro a posição desejada:

(println alunos)

alunos

(alunos 2)

Criando o vetor e vendo seu conteúdo

Quando trabalhamos com vetor temos a disposição a função "count" para contar o total de elementos:

(count alunos)

Agora se nossa intenção for adicionar um novo item ao vetor devemos usar a função "conj", aqui é muito importante entendermos que essa função não altera o vetor original, o que ela faz é retornar um novo vetor que possui os valores anteriores e também o novo, isso devido a imutabilidade do Clojure:

(conj alunos "Eduardo")

Mas qual a vantagem da imutabilidade então? Bom ela nos garante que nossa informação (no caso os valores de nosso vetor) não serão alterados sem o nosso conhecimento ao utilizarmos outras funções, desse modo temos uma confiabilidade maior sobre a informação uma vez que ela só será alterada se realmente desejarmos, ou seja, não corremos o risco de termos os dados alterados por uma função que se quer conhecemos a implementação.

Adicionando valor ao vetor sem alterá-lo

Na imagem acima temos:

  • Na linha sete usamos a função "conj" para adicionar um elemento ao vetor;
  • Na linha oito a função "conj" nos retorna o novo vetor contendo a alteração que realizamos;
  • Na linha nove e dez podemos perceber que o vetor original "alunos" não foi alterado;

Certo, como já é possível imaginar, se nossa intenção for alterar o vetor original precisaremos então redefinir o valor do nosso símbolo "vetor", sendo que seu novo valor será o resultado da execução da função "conj":

(def alunos (conj alunos "Eduardo"))

Novo valor no vetor original

Como podemos ver na imagem acima agora o vetor original "alunos" possui o novo valor.


Conclusão

Nessa postagem sentimos o gostinho inicial do Clojure, escrevemos nosso primeiro "Olá Mundo!", definimos nossa primeira "variável" e criamos nosso primeiro vetor. Também nos deparamos com a imutabilidade, entendendo como ela funciona e uma de suas principais vantagens.


Saiba mais

Comentários

Mais visitadas

Aplicação Flask usando Nginx e Gunicorn

Aplicação Flask usando Nginx e Gunicorn Se você já desenvolveu uma aplicação Flask básica, sabe que o servidor de desenvolvimento embutido não é ideal para produção. Ele não é projetado para lidar com altos volumes de tráfego ou conexões simultâneas. Para tornar sua aplicação Flask mais robusta e pronta para produção, podemos usar o Gunicorn como servidor de aplicação e o Nginx como proxy reverso. Neste artigo, vamos adaptar o exemplo anterior ( Criando uma Aplicação CRUD com Flask, PostgreSQL e Docker ) para incluir o Nginx e o Gunicorn. O que são Nginx e Gunicorn? Gunicorn O Gunicorn (Green Unicorn) é um servidor de aplicação WSGI que roda aplicações Python como o Flask. Ele é eficiente e simples de configurar, lidando com múltiplas requisições ao mesmo tempo, algo que o servidor embutido do Flask não faz bem. Nginx O Nginx é um servidor web que atua como um proxy reverso. Ele recebe requisições HTTP e as encaminha ao Gunicorn. Além disso, o Nginx pode: Servir arquivos ...

Funções de Data e Hora (Delphi)

É muito comum nos depararmos no dia a dia com a necessidade de manipular datas e horas, seja para um calculo de permanência, dias de atraso enfim, é praticamente escapar de alguma situação que necessite desse tipo de controle. Assim como a necessidade e se utilizar algum recurso para manipular as datas e horas de alguma maneira e freqüente, as duvidas de como o faze-lo também é, basta um breve olhar em qualquer fórum especializado e lá está, alguma duvida relacionada, por isso decidi falar um pouco sobre uma unit muito poderosa chamada DateUtils para a manipulação de data e hora, com um grande numero de métodos e classes que facilitam a vida de qualquer um. Alguns exemplos: CompareDate(constA, B: TDateTime): TValueRelationship; Compara apenas a data de dois valores (do tipo TDateTime) retornando: LessThanValue O primeiro valor é menor que o segundo EqualsValue Os valores são iguais GreaterThanValue O primeiro valor é maior que o segundo CompareDateTime(const A, B: TD...

Listar arquivos existentes em diretório (Delphi)

Mostraremos uma maneira simples e prática para listar o conteúdo de um diretório com a opção de incluir nessa listagem os arquivos de seus subdiretórios. No exemplo abaixo temos um Edit para receber o diretório a ser pesquisado um CheckBox para indicar se os subdiretórios entrarão na pesquisa um botão para efetuar a pesquisa e um Memo para listar os arquivos encontrados, no final um Edit que receberá o cálculo final (em bytes) da soma do tamanho dos arquivos. procedure TForm1.Button1Click(Sender: TObject); begin   tamanhoTotal := 0;   memLista.Lines.Clear;   ListarArquivos(edtDiretorio.Text, chkSub.Checked);   Edit1.Text := IntToStr( tamanhoTotal ); end; procedure TForm1.ListarArquivos(Diretorio: string; Sub:Boolean); var   F: TSearchRec;   Ret: Integer;   TempNome: string; begin   Ret := FindFirst(Diretorio+'\*.*', faAnyFile, F);   try     while Ret = 0 do ...