Programação funcional no jQuery
Depois de muito tempo sem aparecer por aqui, volto para falar sobre um assunto que tenho tido muito interesse ultimamente: Javascript.
Javascript sempre foi uma linguagem abominada por muita gente, mas que há algum tempo tem recebido mais atenção. Na minha opinião, grande parte da evolução da linguagem se deve à criação de bibliotecas que simplificam (e muito!) as tarefas mais comuns no dia-a-dia do programador. Dentre estas bibliotecas, a minha favorita é a jQuery.
Comecei a usar jQuery na versão 1.2.6. De lá pra cá (a versão atual é a 1.4.2), muita coisa melhorou! A documentação está excelente, a existem ferramentas desenvolvidas por terceiros que são uma mão na roda!
Como Python é minha linguagem preferida, muitas vezes sinto falta de algumas funcionalidades dela quando estou programando em Javascript/jQuery. Recentemente descobri equivalentes às funções map e filter, para manipulação de listas, no jQuery.
A primeira opção é usar a jQuery.map(), cuja utilização é bem direta:
var resultado = jQuery.map([1, 2, 3, 4, 5], function(valor, i) {
return valor * valor;
});
O primeiro argumento é a lista (o array) e o segundo é a função (lambda) que será aplicada a cada item da lista. O retorno é uma nova lista: [1, 4, 9, 16, 25].
Infelizmente, não existe a função jQuery.filter(), mas a jQuery.map() pode ser usada em substituição, bastando que para isso se retorne null para os valores que deseja filtrar:
var resultado = jQuery.map([1, 2, 3, 4, 5], function(valor, i) {
return valor % 2 == 0 ? valor : null;
});
O retorno neste caso é: [2, 4].
A segunda opção eu acabei descobrindo por acaso. É possível usar as funções .map() e .filter(), originalmente utilizadas para manipulação de objetos jQuery, para manipular listas:
var resultado = $([1, 2, 3, 4, 5]).map(function(i, valor) {
return valor * valor;
}).get();
var resultado = $([1, 2, 3, 4, 5]).map(function(i, valor) {
return valor % 2 == 0;
}).get();
Note que neste caso a ordem dos argumentos da função lambda é o inverso do primeiro caso. Como essa última utilização não é tão direta, cabem algumas explicações.
Ao passar um array para a função jQuery (abreviada por $), é possível usar as funções .map() e .filter(), exatamente como você faria para elementos DOM. Como o resultado dessas funções é um objeto jQuery, é necessário usar a função .get(), para transformá-lo novamente em um array Javascript.
Para ajudar na compreensão, escrevi um exemplo funcional, com testes unitários feitos com o framework QUnit.
CSoC III: participe!
Chegam as férias da faculdade, e com elas vem aquele sentimento de eu podia estar fazendo algo de útil!. Se você tem se sentido assim, não se preocupe, pois temos uma ótima sugestão de atividade para você se ocupar nas férias, e ainda aproveitar para dar um upgrade no currículo: o CEFET Summer of Code!
O CSoC é uma iniciativa que visa ampliar o ensino de linguagens de programação nos cursos de Engenharia do CEFET/RJ. Resumindo, é um curso de programação organizado pelos alunos, em benefício dos alunos.
Várias pessoas já participaram das duas primeiras edições, e agora chegou a sua vez! O curso começa em 2 de fevereiro e dura até o início do período letivo (com pausa para o Carnaval). As aulas serão na COLAN — 3º andar do Bloco E, Unidade Maracanã — às terças e quintas, de 17h30 às 19h, pontualmente.
Até quem não sabe nada sobre programação pode participar! Vamos aprender Python, passando rapidamente por C e C++, utilizando o que há de mais inovador e atual no ensino de linguagens de programação.
Quanto custa? Nada, é de graça! Sério, quanto é? Eu já disse: é de graça!!!
Então, o que você está esperando?! Entre logo no nosso grupo de e-mails e garanta a sua vaga (são só 20!).
Daremos preferência aos alunos do CEFET/RJ; caso as vagas não sejam preenchidas, o curso será aberto ao público externo.
Abração!
O problema com as variáveis globais no Javascript
O Javascript é uma linguagem que muitos vêm como limitada, mas que, na minha opinião, tem seu valor. Por ser um pouco renegada, a maioria não se importa em entender muito bem como ela funciona, só quer saber o básico da sintaxe para fazer o que precisa.
Uma dúvida comum quando se está começando é sobre declaração de variáveis: quando e porque utilizar o var? Vejamos um exemplo:
var numero = 1;
function exibe()
{
alert(numero);
}
exibe();
Conforme esperado, o valor 1 é exibido, já que a variável numero é global. Para confirmar essa informação, vamos fazer:
var numero = 1;
function exibe()
{
alert(numero);
}
function altera()
{
numero = 2;
}
exibe();
altera();
exibe();
Como resultado, são exibidos os valores 1 e 2. Assim, a função altera está modificando o valor da variável global numero.
Afinal, onde o var se encaixa nessa história? O var serve para declarar o escopo da variável. Se uma variável é declarada sem o var, ela é automaticamente global. Quer ver?
function define()
{
numero = 1;
}
function exibe()
{
alert(numero);
}
define();
exibe();
O número 1 é exibido. Para confirmar, faça o seguinte:
function define()
{
var numero = 1;
}
function exibe()
{
alert(numero);
}
define();
exibe();
Neste caso ocorre o seguinte erro: ReferenceError: numero is not defined. Isto ocorre pois a variável numero pertence ao escopo da função define e, portanto, não pode ser acessada de dentro da função exibe.
Quais são as implicações disso? Considere o seguinte exemplo:
var Cachorro = function(nome)
{
_nome = nome;
this.get_nome = function()
{
return _nome;
}
// (...)
}
var Gato = function(nome)
{
_nome = nome;
this.get_nome = function()
{
return _nome;
}
// (...)
}
rex = new Cachorro('Rex');
mimi = new Gato('Mimi');
alert(rex.get_nome());
alert(mimi.get_nome());
Neste caso, é exibido Mimi duas vezes, ao invés do que esperávamos: Rex e Mimi. Isto acontece pois, ao contrário do que pretendíamos, _nome é uma variável global, e o último valor que é atribuído a ela é ‘Mimi’ (dentro do “construtor” da classe Gato).
Para evitar este tipo de problema, sempre declare suas variáveis no Javascript utilizando o var. O código corrigido ficaria assim:
var Cachorro = function(nome)
{
var _nome = nome;
this.get_nome = function()
{
return _nome;
}
// (...)
}
var Gato = function(nome)
{
var _nome = nome;
this.get_nome = function()
{
return _nome;
}
// (...)
}
var rex = new Cachorro('Rex');
var mimi = new Gato('Mimi');
alert(rex.get_nome());
alert(mimi.get_nome());
Python: valor ou referência?
Depois de um longo período sem escrever nada, volto para falar sobre um assunto que sempre me intrigou um pouco no Python: objetos são passados por valor ou por referência?
Um código vale mais do que mil palavras, então acompanhem comigo:
>>> tabela = [[0, 0], [0, 0], [0, 0]] >>> segunda_linha = tabela[1] >>> segunda_linha[0] = 1 >>> tabela [[0, 0], [1, 0], [0, 0]]
Ah, a beleza dos objetos sendo passados por referência! O segunda_linha é uma referência ao segundo elemento da lista tabela, portanto ao alterá-lo, estamos, na verdade, alterando a própria lista original. Quantas possibilidades! Sejamos, então, mais ousados:
>>> tabela = [[0, 0], [0, 0], [0, 0]] >>> primeira_celula_da_segunda_linha = tabela[1][0] >>> primeira_celula_da_segunda_linha = 1 >>> tabela [[0, 0], [0, 0], [0, 0]]
Êpa! Não funcionou! O que aconteceu?!
O problema neste caso não está na forma como o objeto está sendo passado. Na verdade, o que leva a esse comportamento é o método de atribuição do Python.
Ao invés de alterar tabela, “primeira_celula_da_segunda_linha = 1″ está reatribuindo a variável primeira_celula_da_segunda_linha ao objeto 1. Deste modo, não há como esperar que a lista original seja alterada. Simples, não?
Dev in Rio: um evento para desenvolvedores
Na última segunda-feira, 14 de setembro, participei do Dev in Rio 2009, um evento organizado por desenvolvedores e com o apoio da comunidade de software livre carioca.
A organização e a estrutura estavam excelentes! Tudo funcionando redondinho, e pequenos detalhes que fizeram a diferença, como os quadros de feedback, estrategicamente posicionados na saída do salão de palestras e na arena do Coding Dojo.
Vale ressaltar a presença de figuras internacionais, como Jeff Patton e Jacob Kaplan-Moss, e o apoio da galera de São Paulo, que ajudou bastante no Coding Dojo.
Parabéns aos organizadores, Henrique Bastos e Guilherme Chapiewski, e a todos que contribuíram para que o evento fosse um sucesso! Que venha o Dev in Rio 2010!
Apresentação sobre Coding Dojo e TDD na Chemtech
Hoje fiz uma apresentação sobre Coding Dojo e TDD lá na Chemtech para o grupo de Desenvolvimento de Software. Gostaria de agradecer ao Rodolfo Carvalho pela ajuda com o material e por ter “me emprestado” suas telas, e ao Henrique Bastos por ter me dado atenção e valiosas dicas, mesmo estando super atrasado pra pegar o voo para Porto Alegre. Abaixo estão as telas, feitas usando LaTeX + powerdot.
A apresentação teve uma prática de TDD (usando Python), e assim que eu aprender a usar o Git, e criar uma conta no GitHub, coloco o link aqui (eu poderia colocar o código em outro lugar, mas dessa forma eu me forço a ler o tutorial de Git que há tanto tempo está na minha TOREAD list).
Posição da logo em estilos da classe powerdot no LaTeX
Há algum tempo uso a classe powerdot do LaTeX para criar meus slides. Por não ter conseguido encontrar um estilo que atendesse à minha chatice aos meus requisitos, resolvi criar o meu próprio. Um problema que estava tendo era com relação ao posicionamento da logo, que não podia ser personalizado para cada tipo de slide. Na powerdot você pode inserir uma logo da seguinte forma:
\pdsetup{
\logocmd={\includegraphics{logo.eps}},
\logopos={.1\slidewidth,.9\slideheight},
\logohook=tl
}
Infelizmente, desta forma a logo vai aparecer sempre na mesma posição, o que não é o ideal. Se eu quiser, por exemplo, colocar a logo centralizada na tela de título, e na tela de conteúdo colocá-la no canto superior esquerdo, eu não posso. Ou melhor, não podia!
Fuçando um pouco no arquivo fonte da classe (/usr/share/texmf-dist/tex/latex/powerdot/powerdot.cls, no meu caso) descobri que se eu não definir a posição da logo (logopos), ela não é exibida. Fuçando mais um pouco, descobri como obter a logo definida pelo usuário. Bastou, então, usar meus humildes conhecimentos de PSTricks e definir a posição da logo em cada estilo, por exemplo:
\pddefinetemplate{titleslide}{
titlefont=\LARGE\bfseries\centering\color{pdcolor3},
texthook=t,textpos={.5\slidewidth,.75\slideheight},
textwidth=.9\slidewidth,textfont=\large\centering,
textheight=.6\slideheight
}{%
%--- Insere a logo
\rput[B](.5\slidewidth,.2\slideheight){%
\resizebox{!}{1.1cm}{\usebox\pd@logobox}}
}
Usei o comando resizebox para definir uma altura padronizada para a logo, de modo que o usuário não tenha que se preocupar com isso.
Em breve pretendo disponibilizar este estilo no qual estou trabalhando. Aguardem!
EDITADO:
A solução proposta acima apresenta um problema de erro de divisão por zero quando não é informada uma logo usando o comando logocmd. Um forma de contornar este problema é usar o pacote ifthen e inserir a logo somente se a largura da savebox for maior do que zero:
%--- Insere a logo
\newlength{\logoboxwidth}
\settowidth{\logoboxwidth}{\usebox\pd@logobox}
\ifthenelse{\logoboxwidth > 0}{
\rput[B](.5\slidewidth,.2\slideheight){%
\resizebox{!}{1.1cm}{\usebox\pd@logobox}}
}{}




