sábado, 27 de novembro de 2010

Flask

Flask Há diversos frameworks em Python para Web, Django, Zope, web2py, Pyramid e TurboGears e Pylons.

Venho aqui para falar de um microframework chamado Flask.

Simples, flexível e poderoso, é capaz de manter desde o projeto mais simples até CMS no estilo Django ou grandes aplicações como em Pylons.

A instalação é também extremamente simples, já que se encontra no PyPI:
bash$ easy_install Flask


Como exemplo vou mostrar uma aplicação ao estilo Flask, registrando as URLs com decorador route, mas para aplicações mais complexas sugiro criar um arquivo url_rules.py que importe o objeto aplicação e use o método add_url_rule em vez do decorador.

Nossa aplicação simples exibirá o conteúdo dos arquivos em /proc/ dos sistemas Unix (por falta de ideia melhor).

Podemos começar importanto os recursos necessários:
from flask import Flask, make_response


  • Flask: classe da aplicação
  • make_response: função capaz de criar um objeto de resposta HTTP


Para a leitura dos arquivos e diretórios vamos precisar do módulo os:
import os


Vamos agora criar duas funções, uma que retorne a listagem de arquivos para um diretório e outra que retorne o conteúdo de um arquivo:
def list_dir(path):
filelist = os.listdir(path)
filelist.sort()
return '\n'.join(filelist)


def read_file(path):
data = 'NO DATA'
with open(path, 'r') as fd:
data = fd.read()
return data


Agora é possível criar a aplicação:
app = Flask(__name__)
app.debug = True


Podemos então criar uma função que receba o caminho do arquivo/diretório a ser lido e retorne para o navegador.

Caso seja necessário editar os cabeçalhos ou lidar com qualquer peculiaridade do objeto de resposta HTTP, é possível instanciá-lo manualmente. Caso contrário, retornar uma simples string já faz com que ela seja entendida como o conteúdo do objeto.

Se uma tupla for retornada, o primeiro valor será o conteúdo e o segundo o status de retorno.

Sabendo disso, podemos definir a função:
@app.route('/<path:filename>/')
def read_proc(filename):
real_path = os.path.join('/proc', filename)
data = 'NO DATA'

try:
if os.path.isfile(real_path):
data = read_file(real_path)

elif os.path.isdir(real_path):
data = list_dir(real_path)

else:
return 'NOT FOUND', 404

# Criando HTTP response apenas para editar headers
response = make_response(data)
response.headers['Content-Type'] = 'text/plain'
return response

except IOError:
# Você não pode ler este arquivo/diretório!
return 'BAD REQUEST', 400


A rota indica que o argumento filename receberá como parâmetro toda a URL passada (path: indica uma string com /).

Para a raiz da aplicação, poderíamos usar as funções redirect e url_for, por exemplo:
@app.route('/')
def index():
return redirect(url_for('read_proc', filename='cpuinfo'))


O que redirecionaria para a URL referente à função read_proc, passando 'cpuinfo' como parâmetro, mas faz mais sentido retornar o resultado da função:
@app.route('/')
def index():
return read_proc('')


Agora só falta colocar a aplicação para rodar:
if __name__ == '__main__':
app.run(host='0.0.0.0')


Execute o script e acesse no navegador: http://localhost:5000/ – você verá a listagem do diretório /proc/.

Acesse no navegador: http://localhost:5000/cpuinfo/ e você verá o conteúdo do arquivo /proc/cpuinfo.

Pretendo em uma próxima oportunidade demonstrar com construir uma estrutura mais complexa usando um arquivo com roteamente em vez de decorador.

Para mais diversão, leia a documentação e fascine-se também com a quantidade de vezes que a expressão «you don’t have to deal with that» se repete.

[]’s
Cacilhας, La Batalema

quinta-feira, 2 de setembro de 2010

Torne-se excelente

Glider Este é um artigo que meu amigo Argentino me apresentou, do Klaus Wuestefeld, autor do manifesto da Computação Soberana.

O artigo original – ou pelo menos o endereço que me foi apresentado – se encontra no GitHub e aconselho todos a lerem.

Mas antes, no artigo original os comentários tenderam para discussão sobre a importância do curso superior. O foco do texto não é esse! Não é criticar a faculdade ou sua importância. O foco é mais na prioridade que damos às coisas.

Em outras palavras: um curso académico é importante, mas possui menor prioridade do que a experiência profissional, ainda mais na Computação, curso que no Brasil ainda não está academicamente bem definido e em muitas faculdades tende a ser regido por interesses empresariais no lugar de pelo conhecimento.

Segue o artigo:

Torne-se excelente


Seja realmente bom em alguma coisa. Não fique só choramingando ou querendo progredir às custas dos outros. Não pense que, porque você sentou 4 anos numa faculdade ouvindo um professor falar sobre software, você sabe alguma coisa. Jogador de futebol não aprende a jogar bola tendo aula. Ele pratica. Instrumentistas geniais não aprendem a tocar tendo aula. Eles praticam. Pratique. Chegue em casa depois do trabalho e da aula e pratique. No final de semana, pratique.

Crie seu próprio vírus, seu proprio jogo, seu proprio SO, seu proprio gerenciador de janelas, seu proprio webserver, sua propria VM, qualquer coisa. Várias coisas.

Não precisa ser só programação. Pode ser networking, vendas, etc. Só precisa ser bom mesmo. Tenha paixão pela coisa.

As melhores práticas do mercado são polinizadas primeiro nos projetos de software livre. Aprenda com eles.

Discípulo, Viajante, Mestre: Primeiro seja um discípulo, tenha mestres locais, aprenda alguma coisa com alguem realmente bom, qualquer estilo. Depois viaje, encontre outros mestres e aprenda o estilo deles. Por fim, tenha o seu estilo, tenha discípulos, seja um mestre.

Vou fazer o curso da Mary Poppendieck em SP semana que vem e quando tiver o curso de Scrumban do Alisson e do Rodrigo quero fazer também.

«Torne-se excelente» também pode ser chamado de «Melhoria Continua» ou Learning.

Não seja deslumbrado


Desenvolvimento de software é a mesma coisa há 60 anos: modelo imperativo. Há 30 anos: orientação a objetos. Bancos de dados relacionais: 30 anos. («Web», por exemplo, não é uma tecnologia ou um paradigma. É meramente um conjunto de restrições sobre como desenvolver e distribuir seu software).

Não corra atras da ultima buzzword do mercado. Busque a essência, os fundamentos.

Busque na Wikipédia e Grokke: determinismo, complexidade de algoritmos O(), problema de parada de Turing. Pronto, pode largar a faculdade. Falando sério.

Trabalhe com software livre. Não dê ouvidos a grandes empresas, grandes instituições ou grandes nomes só porque são grandes.

Você acha que vai aprender mais, ter mais networking e mais chance de alocação no mercado trabalhando em par comigo no Sneer por um ano, 8h por semana, ou passando 4 anos na faculdade, 20h por semana, pagando sei lá quanto por mês?

Você acha que vai aprender mais trabalhando em par com o Bamboo 6 meses na linguagem Boo e na engine do Unity ou fazendo um ano de pós em «a buzzword da moda»?

«Não seja deslumbrado» também é conhecido como Coolness.

Mantenha-se Móvel


Com a demanda que temos hoje no mercado, se você é desenvolvedor de software e não consegue negociar um contrato com uma empresa onde você é pago por hora e pode trabalhar quantas horas quiser com um mínimo de meio período, você precisa rever a sua vida.

É melhor ter dois empregos de meio período que um de período integral, porque você pode largar um deles a qualquer momento.

Você nunca vai conseguir nada melhor se não tiver tempo, se não tiver disponibilidade pra pegar algo melhor quando aparecer.

Você sustenta seus pais e 7 irmãos? Não. Então pare de ser ganancioso e medroso no curto prazo, para de pagar facu, mestrado, pós, MBA, sei-lá-o-quê e vai aprender e empreender.

Trabalhe remoto. Não é o mais fácil, mas é perfeitamente possível.

Não fique reclamando que está trabalhando demais. Aumente seu preço e trabalhe menos.

Emparceire-se Promiscuamente


Participe de dojos, de congressos, de projetos de software livre. Tenha amigos, colegas, conhecidos. Seja conhecido. Não faça ruído em seis projetos e doze fóruns. Ajude de verdade em um ou dois projetos de cada vez. Ao longo do tempo, você terá ajudado em varios projetos, trabalhado em várias empresas.

Mentalidade de Abundância


Ajude seus amigos sem cobrar (a «camaradagem» do Vinícius). Dê palestras gratuitas. Cursos gratuitos. Participe de projetos de software livre.

Pare as vezes uma tarde pra receber um amigo seu e explicar seu projeto. Vá visitar seus amigos nos projetos deles. Viaje com algum amigo seu pra visitar um cliente dele, só pra conversar e fazer companhia.

Você tem um espaço onde dá cursos? É uma Aspercom, Caelum da vida? Chama os brothers para dar curso. Porra, bola um modelo em que as pessoas podem se inscrever para cursos variados, pagando um sinal, e mantém tipo uma agenda pré-combinada: «Será numa terça e quinta à noite, avisadas com duas semanas de antecedencia». Se rolar, beleza, se depois de meses não der quórum, devolve o sinal. Pode ser curso de Prevayler, de Kanban, de Scrum, de Lean, de Comp Soberana, de Restfulie, de Cucumber, de Rails, de Teste Automatizado Mega-Avançado, qualquer coisa.

Chame amigos seus pra dar curso em dupla com você. Divida clientes. Divida projetos, mesmo que não precise de ajuda.

Dizia o pai de um brother meu de infância: «Tudo que custa dinheiro é barato».

Busque modelos de custo zero


Trabalhe em coisas que tem custo administrativo/ burocrático/ manutenção zero. Por menos ganho que tragam, depois de prontas, estarão tendo uma relação custo/benefício infinitamente vantajosa.

Ganhe notoriedade


Faça coisas massa. Participe de projetos de software livre. Dê palestras gratuitas. Promova eventos (dojos, debates, grupos de usuários, etc).

By Dairton Bassi:

Não tenha medo!


Meta a cara. Arrisque empreender. Arrisque inovar. O que você tem a perder? No máximo um emprego, mas isso pode ser revertido facilmente em um mercado aquecido como o atual. O pior que pode acontecer é não dar certo. Mesmo assim você terá aprendido muito mais do que batendo cartão.

Saia da zona de conforto. Se o seu trabalho estiver fácil e sob controle, isso significa que ele não está mais agregando para a sua evolução técnica e pessoal.

Não desperdice a chance de trocar de função se a nova oportunidade for mais desafiadora. Isso fará você crescer tecnicamente e o preparará para desafios maiores ainda. Conhecer pessoas novas é tão importante quanto manter-se em contato com código.

Não se detenha por insegurança ou pela sensação de despreparo. Como você acha que vai ganhar experiência em alguma coisa se sempre adiá-la?


[]’s
Cacilhας, La Batalema

terça-feira, 31 de agosto de 2010

Blogagem Coletiva em repúdio ao AI5 Digital – 31/08

AI5 Digital

Veja também no blog do gutocarvalho.net:

Blogagem Coletiva em repúdio ao AI5 Digital – 31/08



Amigos, os adoradores do AI5Digital e da ditadura, os amantes do vigilantismo, os defensores dos direitos econômicos em detrimento dos direitos civis que formam o tripé do atraso, estão se movimentando para aprovar o famigerado e monstruoso AI5Digital que há muito deveria ter sido fulminado, destruído e acabado.

A turma do Grande Irmão: Azeredo, Febraban, Fecomercio e outros do mesmo quilate estão fazendo uma força tremenda para nos empurrar o AI5Digital guela abaixo de qualquer forma, vamos aos fatos:
  1. A mídia continua repetindo o Mantra da Irracionalidade contra a Internet
  2. No dia 05/08/10 O Deputado Pinto Itamaraty do PSDB apresentou parecer favorável ao AI5Digital, ignorando todos os argumentos e movimentos sociais dos últimos três anos.
  3. Seis dias depois aparece uma matéria dizendo que os Deputados buscarão acordo para votar a lei de crimes na Internet.
  4. E agora um evento para lá de esquisito organizado pela revista Decision Report, uma publicação que parece estar à serviço do Azeredo e do vigilantismo, se anuncia para o dia 31/08 com o título oportuno (para o tripé do atraso) de: Crimes Eletrônicos – A urgência da lei. O curioso e que este evento conta com 19 palestrantes para falarem em 2:30h, o que dá um pouco mais de 7 minutos para cada um.

Por estas e por outras que estamos convocando uma blogagem coletiva para o dia 31/08/10, justamente no dia do tal evento à serviço do Azeredo e do AI5digital, vamos fazer uma blogagem coletiva contra o AI5Digital para lembrar a todos que queremos a Internet como um espaço livre e democrático!!!

Fonte:
http://meganao.wordpress.com/2010/08/27/blogagem-coletiva-de-repudio-ao-ai5-digital/

Participe do MEGANÃO, acesse agora:

http://meganao.wordpress.com/o-mega-nao/quem-esta-participando/


[]’s
Cacilhας, La Batalema

quinta-feira, 26 de agosto de 2010

Paradigmas de programação

Glider Muito mais empolgante do que aprender uma nova linguagem de programação é aprender um novo paradigma de programação.

A parte mais louca é perceber como o paradigma funciona. Isso acontece de modo intuitivo, muito parecido com como quando se aprende uma língua nova: nada faz sentido no começo, tudo é muito mecânico; de repente um estalo e tudo faz sentido!

Há muitos paradigmas de programação, já andei falando disso antes, mas muitos são variações dos mesmos tipos básicos: paradigmas imperativo, funcional e declarativo.

Programação imperativa


É o primeiro paradigma com o qual a maioria dos programadores trava contato.

Na programação imperativa, o programa se parece com uma receita de bolo: uma sequência de ordens, chamadas comandos ou instruções (statements em inglês), que devem ser executadas.

A partir desse conceito, derivam diversos paradigmas secundários. O principal é a programação estruturada ou procedimental (procedural em inglês), onde os comandos são organizados em grupos, chamados funções, que podem ser evocados em momentos diferentes.

As funções podem receber ou não parâmetros, que alteram seu comportamento, e podem retornar valores. Em algumas linguagens, quando o grupo de comandos não recebe parâmetros nem retorna valores, ele é chamado subrotina.

Para exemplificar o funcionamento da programação imperativa, vamos implementar fatorial em C – mais simples impossível.

Para quem não sabe, fatorial consiste em uma função recursiva cuja parada é:
0! = 1


E o passo é:
n! = n * (n - 1)!


Outra forma de entender é reiterativamente:
n! = 1 * 1 * 2 * 3 * … * (n - 2) * (n - 1) * n


Vamos implementar a função reiterativa em C para ilustrar melhor o paradigma:
#include <stdlib.h>
#include <stdio.h>

int factorial(int);


int main(int argc, char **argv) {
printf("O fatorial de 5 é %d\n", factorial(5));
return EXIT_SUCCESS;
}


int factorial(int x) {
int result = 1;
int i;
for (i=1; i<=x; ++i)
result *= i;
return result;
}


Cada comando é uma ordem dada ao sistema: atribua 1 à variável result; para cada i de 1 até o valor do argumento x, multiplique o valor de result pelo valor de i; retorne o valor de result.

São ordens dadas ao sistema.
[update 2011-07-24]
Na programação imperativa, é muito comum a manipulação de alterações de estado, daí o uso de variáveis – contentores (ou slots) que podem sofrer alterações de valor ao longo da existência do processo em execução.
[/update]


Orientação a objetos


Orientação a objetos não passa de um variante da programação imperativa, mas um variante digno de citação.

Na orientação a objetos, as ordens não são dadas a um sistema abstrato, mas objetos recebem as ordens e as executam.

O conceito de objeto é bem genérico: qualquer coisa pode ser um objeto, um número, uma janela na tela, uma coleção…

Na orientação a objetos as ordens dadas a um objeto são chamadas mensagens e a definição de como o objeto reage a cada mensagem é chamada método.

O exemplo será a versão recursiva de fatorial implementada em Smalltalk:
!Integer methodsFor: 'mathematical functions'!

factorial
self = 0 ifTrue: [↑ 1].
self > 0 ifTrue: [↑ self * (self - 1) factorial].
self error: 'Not valid for negative integers'.
!
!!


Transcript
show: 'O fatorial de 5 é ';
show: 5 factorial printString;
cr.


[update 2011-07-16]
Atualizei o código em Smalltalk segundo implementação da máquina virtual Pharo.
[/update]


O princípio é parecido com o anterior, mas em vez de dar uma ordem ao sistema – calcule o fatorial de 5 –, é dada ao próprio número – número 5, qual seu fatorial?

Observação: a orientação a objetos pode ser aplicada também à programação funcional.

Programação funcional


Enquanto na programação imperativa ordens são dadas ao sistema ou a objetos, no paradigma funcional são definidas funções, como as matemáticas, e o programa nasce da interação entre as funções: o resultado de umas funções é passado como parâmetro para outras.
[update 2011-07-24]
Na programação funcional, o estado do sistema tende a ser constante, havendo apenas a troca de informação por parâmetros. Assim é comum que não haja variáveis, mas incógnitas constantes, que não sofrem (ou não devem sofrer) alteração de valor ao longo da execução do programa.
[/update]


O mesmo exemplo, fatorial, em Common Lisp:
(defun factorial ((x integer))
(if (zerop x)
1
(* x (factorial (- x 1)))))


(format t "~%O fatorial de 5 é ~A~&" (factorial 5))


O conceito é ligeiramente difente: a função factorial, que recebe um parâmetro inteiro nomeado x, é definida como o resultado da função if; a função if recebe como primeiro parâmetro o resultado da função zerop, que é verdadeiro quando x é igual a zero; o segundo parâmetro de if, 1, é o resultado caso o primeiro parâmetro seja verdadeiro; o terceiro parâmetro é o resultado caso seja falso; o terceiro parâmetro é o resultado da função de multiplicação. Entendendo até aqui, o resto é autoexplicativo.

[update 2011-06-19]

Bônus!



Fatorial em Scheme:
(define (factorial x)
(if (zero? x)
1
(* x (factorial (- x 1)))))

(display "O fatorial de 5 é ")
(display (factorial 5))
(newline)


E em Erlang:
-module (fact).
-export([factorial/1]).

factorial(0) -> 1;
factorial(X) -> X * factorial(X - 1).


Salve como fact.erl. No prompt:
1> c("fact.erl").
{ok,fact}
2> fact:factorial(5).
120

[/update]


Programação declarativa


Este paradigma é um dos mais complicados para pescar

[update 2011-07-24]
Na programação declaração o código diz o que o programa deve fazer, não como.
[/update]


O programa consiste em uma lista de declarações de verdades.

Nos paradigmas anteriores havia variáveis, que sofriam atribuições. Na programação declarativa há incógnitas, que não sofrem atribuições! O valor de cada incógnita é constante e inicialmente desconhecido. O que o programa faz é cruzar as consultas (queries) com as declarações que formam o conjunto verdade para deduzir o valor das incógnitas.

O exemplo consiste no fatorial implementado em Prolog:
factorial(0, 1).

factorial(N, F) :-
N > 0,
N1 is N - 1,
factorial(N1, F1),
F is N * F1.


O que este conjunto verdade diz é que o fatorial de 0 é 1 e que o fatorial de N é F quando:
  1. N é maior que zero;
  2. N1 é N menos 1;
  3. o fatorial de N1 é F1;
  4. e F é igual a N vezes F1.


Para a consulta:
| ?- [factorial].
fatorial.pro compiled, 7 lines read - 869 bytes written, 7 ms
(1 ms) yes
| ?- factorial(5, X),
write('O fatorial de 5 é '),
write(X),
nl.


Para entender como funciona, há um applet em Java em um tutorial que demonstra o chinês. É só encontrar o applet na página, ir clicando em Step e ver acontecer.

A linguagem declarativa da vez é Erlang.

[update 2011-06-19]
Na época deste artigo, em vez de estudar Erlang, perguntei por aí e fui informado que Erlang seria uma linguagem declarativa. Agora que tomei vergonha na cara e estudei um pouco, descobri que é uma linguagem funcional, extremamente similar a Haskell.

Para experimentar Erlang, há o applet Try Erlang.
[/update]


[]’s
Cacilhας, La Batalema

segunda-feira, 16 de agosto de 2010

Diversão com ANTLR

ANTLR – Another Tool for Language Recognition – é uma ferramenta para construção de analisadores léxico (lexer) e sintático (parser) de linguagens formais para JVM.

A grosso modo, é uma ferramenta para implementação de linguagens de programação.

E ANTLRWorks é um IDE gráfico para ANTLR.

Para entender como funciona ANTLR, vou explicar o exemplo do próprio sítio. Então instale o ANTLRWorks e mãos à obra!

Avaliador de expressões


Quando iniciar o ANTLRWorks, crie uma gramática chamada Expr.g.

O código já vai aparecer com a seguinte linha:
grammar Expr;


A ideia aqui é criar um interpretador que avalie expressões matemáticas simples, inclusive com variáveis.

Para suportar variáveis, precisamos de algum lugar para armazenar seus valores. Para isso usamos Java:
@header {
import java.util.Map;
import java.util.HashMap;
}

@members {
Map<String, Integer> memory = new HashMap<String, Integer>();
}


Isso criará o contentor memory, que é um mapa de chaves string e valores inteiros.

ANTLR funciona definindo regras. Nossa primeira regra é programa (prog) e precisamos defini-la:
prog:   stat+;


Então nosso programa é um grupo (+) de comandos (stat), o que nos leva à próxima regra.

Definimos comando como:
stat:   expr NEWLINE { System.out.println($expr.value); }
| ID '=' expr NEWLINE
{ memory.put($ID.text, new Integer($expr.value)); }
| NEWLINE
;


Calma, vou explicar!

Um comando pode ser uma expressão (expr) seguida de uma mudança de linha (NEWLINE). Neste caso, será impresso na saída padrão (System.out) o valor da expressão ($expr.value);

Um comando também pode ser (| significa OU) um identificador (ID) seguido de um sinal de igual ('='), uma expressão e uma mudança de linha. Neste caso o valor da expressão ($expr.value) será armazenado no contentor memory na chave igual ao texto do identificador ($ID.text).

Um comando ainda pode ser uma mudança de linha, que não fará nada.

Agora precisamos definir uma série de regras: expr, NEWLINE e ID. Vamos começar por expr:
expr returns [int value]
: e=multExpr { $value = $e.value; }
( '+' e=multExpr { $value += $e.value; }
| '-' e=multExpr { $value -= $e.value; }
)*
;


Quer dizer que expr retorna um valor inteiro (int value) e consiste de uma expressão múltipla (multExpr) seguido de nenhuma, uma ou mais repetições (*) do que estiver entre parêntesis. O valor retornado é igual ao valor da expressão múltipla.

A atribuição e= é necessária por haver mais de uma ocorrência de multExpr.

Entre parêntesis tempos o sinal de adição ('+') seguido de uma multExpr ou (|) um sinal de subtração ('-') seguido de uma multExpr. No primeiro caso o valor da multExpr é adicionado ao valor retornado, no segundo é subtraído.

A regra multExpr é definida como:
multExpr returns [int value]
: e=atom { $value = $e.value; } ('*' e=atom { $value *= $e.value; })*
;


Uma multExpr retorna um valor inteiro e consiste de um ou mais atómicos (atom). Os valores dos atómicos são multiplicados.

Definindo um atómico:
atom returns [int value]
: INT { $value = Integer.parseInt($INT.text); }
| ID
{
Integer v = memory.get($ID.text);
if (v != null) $value = v.intValue();
else System.err.println("undefined variable " + $ID.text);
}
| '(' expr ')' { $value = $expr.value; }
;


Então um atómico pode ser um inteiro (INT, o valor é o corpo do inteiro: $INT.text), um identificador (ID, o valor é o relacionado à chave no contentor memory – se não existir, gera um erro) ou o resultado de uma expressão (expr), que deve estar entre parêntesis.

Falta definir as regras ID, INT e NEWLINE:
ID  :   ('a'..'z'|'A'..'Z')+;
INT : '0'..'9'+;
NEWLINE: '\r'? '\n';


Ou seja: identificador é uma sequência de letras, inteiro uma sequência de números e mudança de linha é CRLF ou LF.

Para finalizar, para ignorar espaços em branco:
WS  :   (' '|'\t')+ { skip(); };


Testando


Para testar, clique em Debug e preencha a caixa Text com:
x = 1
y = 2
3 * (x + y)


Os parêntesis e a mudança de linha na última linha são importantíssimos!

Clique Ok e divirta-se acompanhando o debugger! Repare que, ao final da execução, vai mostrar 9 na aba Output.

[]’s
Cacilhας, La Batalema

quarta-feira, 9 de junho de 2010

Por que as empresas teimam em contratar programadores mercenários?

Recentemente li The Python Paradox, de Paul Graham, e sua tradução O Paradoxo Python no #!SouNerd.

O texto faz todo sentido: quem aprende a fazer qualquer coisa por gosto tende a fazer melhor do que quem aprende a fazer por dinheiro. É uma verdade.

Assim, quem aprende a programar porque gosta de programar tende a programar melhor do que quem aprende para ganhar dinheiro e a grande maioria de quem aprende a programar Java só o faz por dinheiro (claro que há lá suas exceções), enquanto quem aprende linguagens mais exóticas o faz por prazer.

Então por que as empresas teimam em contratar programadores mercenários?

Pensando sobre isso e observando a comunidade, pensei em uma resposta…

Eu vejo três tipos de programadores, como três vértices de um triângulo cromático, e cada um está em uma região dessa área, mais próximo ou distante de cada vértice.

Esses três tipos são: amador, mercenário e empolgado (por falta de palavra melhor).

Mercenário


O mercenário é aquele que quer dinheiro e lucro é tudo o que o impulsiona. Geralmente não tem escrúpulos e faz tudo o que lhe mandam. Seu mantra é: «Pagando bem, que mal tem?»

Quem é 100% mercenário geralmente acaba largando a profissão por algo que dê mais dinheiro, mas basta estar um pentelésimo mais para o centro do triângulo que permanece na profissão.

Normalmente aprende uma linguagem que dê muitas opções de emprego – e que, por consequência, tenha de competir com muita gente –, como Java, C# ou PHP, e rejeita todas as demais. Quando as trata como inferiores, é apenas para tentar justificar a própria incompetência, resultante da falta de gosto pelo que faz.

Amador


O amador é aquele que gosta de verdade do que está fazendo, ele ama programar, daí amador.

Quem é 100% amador quase sempre se perde aprendendo coisas inúteis e não consegue ganhar dinheiro porque muitas vezes perde o foco do que precisa fazer, distraindo-se com besteiras.

Normalmente aprende linguagens bem diferentes, que poucos sabem, como Lisp, Smalltalk ou Fortran – talvez LOLCODE –, e não é incomum que aprenda uma penca de linguagens, nesse caso, também os hypes, como Python e Ruby.

Empolgado


O empolgado é aquele que vai atrás de algum hype, linguagem da moda. Há uns anos eram de Java, mas os empolgados da atualidade querem Python e/ou Ruby.

Quem é 100% empolgado sabe tudo que acontece na comunidade, mas quase nada de programação. Conhece todas as metodologias em alta, sabe todos os macetes e design patterns de sua linguagem que precisa para impressionar os iniciantes, mas não é lá muito eficiente. É tão preocupado com a auto-imagem e o que acontece na comunidade que se esquece que há todo um background a ser aprendido por trás da Computação.

**


Felizmente (quase) ninguém é 100% alguma coisa.


Depois de toda esta dissertação, por que diabos as empresas mais engessadas preferem os mercenários?

Por causa de seu mantra! Basta pagar o que o mercenário acha muito – o que muitas vezes é quase nada pra empresa – e ele faz qualquer coisa que mandarem, torna-se um cão bem adestrado. Essas empresas não querem eficiência, querem obediência.

O que as empresas não veem é que esses cães não são tão ágeis quanto os gatos que pulam pelos telhados: aqueles que, apesar de em nenhum extremo, se encontram mais próximos do vértice do amador.

Na verdade as metodologias ágeis não são práticas de trabalho, mas técnicas sociais para atrair programadores que, apesar de ainda um pouco mercenários, sejam muito mais amadores – ser um pouco empolgado também ajuda, já que as linguagens hype facilitam pela grande mobilidade da comunidade. As empresas mais espertas e as start-up viram isso e usam as metodologias ágeis para criar equipes enxutas e mais eficientes do que qualquer equipe de mercenários jamais conseguirá ser.

[]’s
Cacilhας, La Batalema

sexta-feira, 28 de maio de 2010

DISQUS e perda dos comentários

Twitter Gente,

Devido a uma proliferação absurda de spams nos comentários do Kodumaro, implementei o serviço DISQUS para gerência dos mesmos.

Infelizmente, parece que todos os comentários antigos se perderam. =(

Peço desculpas a todos, a implementação foi uma necessidade e a perda dos comentários um efeito colateral indesejado.

[]’s
Cacilhας, La Batalema

quinta-feira, 22 de abril de 2010

Parrot VM

Parrot Parrot VM é a máquina virtual criada com base nas linguagens de programação Python e Perl que proporciona o ambiente para a criação, a implementação e o uso de linguagens de programa. As linguagens suportadas pela máquina virtual estão listadas na página do projeto, com destaque para a curiosa e elegante linguagem tutorial Squaak.


Um dos exemplos de Squaak é factorial.sq:
# Copyright (C) 2008, Parrot Foundation.
# $Id: factorial.sq 36833 2009-02-17 20:09:26Z allison $

print("Please enter number: ")
x = read()

sub factorial(n)
## test for < 2 because all numbers are represented by
## floating-point numbers, and equality checks on those
## do not work (yet?)
if n < 2 then
return 1
else
return n * factorial(n - 1)
end
end

print("factorial of ", x, " is: ", factorial(x))


Voltando à Parrot VM, ela possui uma linguagem própria, um assembly.

Seguem aqui dois exemplos de seu assembly. Ambos gravam o que é digitado pelo usuário em um arquivo (test.text) e depois exibem o conteúdo do arquivo. Simples.

O objetivo de dois códigos é mostrar como pode ser feita a escrita e leitura em arquivo usando descritor de arquivo, de modo totalmente procedimental (como em C), e usando manipulador de arquivo, lançando mão da orientação a objetos.

Descritor de arquivo (procedimental)


.sub 'main' :main
.local string filename
.local string line
.local pmc STDIN
.local pmc fd

filename = 'test.text'
STDIN = getstdin

# Writing operation
fd = open filename, 'w'
print "> "
line = readline STDIN
print fd, line
close fd

# Reading operation
fd = open filename, 'r'
line = read fd, 10240
print line
close fd
.end


Manipulador de arquivo (OO)


.sub 'main' :main
.local string filename
.local string line
.local pmc STDIN
.local pmc file_handle

filename = 'test.text'
STDIN = getstdin
file_handle = new 'FileHandle'

# Writing operation
file_handle.'open'(filename, 'w')
file_handle.'encoding'('utf-8')
print "> "
line = readline STDIN
file_handle.'print'(line)
file_handle.'close'()

# Reading operation
file_handle.'open'(filename, 'r')
line = file_handle.'readall'()
print line
file_handle.'close'()
.end


[]’s
Cacilhας, La Batalema

domingo, 11 de abril de 2010

Coleções com Smalltalk

Smalltalk Dando seguimento a uma série de artigos sobre GNU Smalltalk, este artigo demonstra alguns recursos de coleção (arrays e dicionários).

A classe base para coleções é Collection, filha de Iterable. As demais classes, como Array, Dictionary, Bag e Set, são herdeiras diretas ou indiretas de Collection.

Para criar um instância vazia de qualquer subclasse de Collection, você pode usar a mensagem #new.

Array


Há duas sintaxes para instanciação de Array, uma literal e outra programável.

A sintaxe literal suporta apenas dados literais: inicia-se com #(, os elementos são separados por blanks (espaços, tabulações, mudanças de linha) e é fechado com ).

Por exemplo:
#(1 2 3)


A limitação dessa sintaxe é que ela só suporta valores literais, não suporta qualquer forma de código (bloco, variável, construtor, etc…). Portanto, não é recomendável.

A sintaxe recomendada para criação de array com código é {}, pois a sintaxe literal suporta apenas literais. A sintaxe com suporte a código se inicia com {, os elementos são separados por ponto (.) seguido de blank e é fechado por }.

Por exemplo:
| anArray b |

b := 2.
anArray := {
1.
b.
[3] value.
}.


O principal seletor para leitura de elementos em um array é #at:ifAbsent:, que recebe como primeiro parâmetro o índice e como segundo um bloco que retorna o valor em caso se ausência.

Por exemplo:
anArray at: 2 ifAbsent: [0]


Retorna o elemento de índice 2 ou, em caso de não existir, retorna zero ([0] value).

Dictionary


Essa classe representa um dicionário ou hash, ou seja, uma coleção de pares chave-valor.

Por exemplo:
| aDict |

aDict := Dictionary from: {
#a -> 1.
#b -> 2.
#c -> 3.
}.


Se usar Squeak ou Pharo, a mensagem de criação é #newFrom: em vez de #from:.

Também aceita a mensagem #at:ifAbsent:, que recebe como primeiro parâmetro a chave e como segundo um bloco que retorna o valor em caso de ausência. Ainda responde à mensagem #at:, que recebe apenas a chave e, em caso de ausência, levanta uma exceção NotFound.

A mensagem para inserir um novo par é #add::
aDict add: (#d -> 4).


Para alterar o valor de uma chave use #at:put::
aDict at: #a put: 5.


Também funciona para adicionar novo par.

Para remover um par pela chave basta usar a mensagem #removeKey::
aDict removeKey: #a.


À mensagem #keys responde uma lista – uma instância de Set, de fato – das chaves dos pares, já o seletor #keysAndValuesDo: executa um bloco para cada par:
aDict keysAndValuesDo: [ :key :value |
Transcript
show: key printString;
tab;
show: value printString;
cr.
].


Set


Set é um array onde cada elemento é único, ou seja, não se repete. Para criar uma instância de Set:
| aSet |

aSet := #(1 2 3 4 5) asSet.


Para remover um elemento, use a mensagem #remove: e para adicionar #add:. Se o elemento adicionado já existir, nada acontece.

Para listar o conteúdo há a mensagem #do::
aSet do: [ :e |
Transcript show: e printString; cr.
].


Bag


Bag é exatamente o que o nome diz: um saco de elementos. Você pode ir jogando o que quiser lá dentro e os elementos vão sendo armazenados desordenadamente.
| aBag |

aBag := #(1 2 3 4 5) asBag.


Os principais seletores são #add:, #remove: e #do:, que funcionam de modo similar aos seletores de Set, mas permite duplicação de elementos.

Conclusão


Há uma série de outras classes filhas de Collection, como OrderedCollection, SortedCollection e LinkedList, e muitos outros seletores úteis.

Para mais informações, execute gst-blox, acesse SmalltalkClass Hierarchy Browser. Na nova janela, clique em ClassSearch e faça uma busca por Collection.

De classe em classe, navegue pelos métodos e veja como cada classe responde a cada mensagem.

[]’s
Cacilhας, La Batalema


PS: Referência: M206 Computing: An Object-oriented Approach

domingo, 4 de abril de 2010

Quem ama BLOXeia!

Smalltalk GNU Smalltalk é a implementação Smalltalk da Free Software Foundation para o sistema operacional GNU.

Para interface gráfica, ele oferece o módulo BLOX. Sua IDE pode ser iniciada pelo comando:
bash$ gst-blox


Caso queira navegar pelas classes de sua própria imagem – dev.im por exemplo –, use:
bash$ gst-blox -I dev.im


Este artigo apresentará um exemplo extremamente simples de uso programático do BLOX para criar interface gráfica com o usuário, baseado no código encontrado no tutorial oficial.

Primeiro vamos criar a imagem contendo o módulo BLOX:
bash$ gst-load -iI blox-sample.im Blox


Crie um arquivo fonte blox-sample.st onde vamos trabalhar.

Declare as variáveis que usaremos:
| win con lab bt |


Agora crie a janela principal com o título Example e seu container:
" Main window "
win := BLOX.BWindow new: 'Example'.
con := BLOX.BContainer new: win.


Para definar as dimensões da janela e a callback do botão de fechamento:
" Main window's geometry and close button "
win
width: 200 height: 50;

callback: [
BLOX.Blox terminateMainLoop.
true.
] message: #value.


A callback encerrará o ciclo principal. Callbacks de janelas precisam ter a última saída true (quando a janela deve ser fechada) ou false (quando a janela não deve ser fechada).

Podemos então configurar a geometria padrão para widgets filhos:
" Geometry management "
con
setVerticalLayout: true;
defaultHeight: 50;
defaultWidth: 200.


Agora, para criar um rótulo (label) e um botão:
lab := BLOX.BLabel new: con label: 'Waiting...'.
bt := BLOX.BButton new: con label: 'Click me'.


O rótulo exibirá seu texto centralizado, com fundo azul e cor de texto branco:
" Label setup "
lab
alignment: #TopCenter;
backgroundColor: #blue;
foregroundColor: #white.


A callback que responde ao evento clique no botão:
" Button callback "
bt
callback: [
lab label: 'HELLO WORLD!'.
] message: #value.


Para exibir a janela:
" Show window "
win map.


Por último devemos iniciar o ciclo principal (mainloop):
" Start mainloop "
BLOX.Blox dispatchEvents: win.


Se quiser, é possível exibir uma mensagem indicando o fim do programa:
Transcript
show: 'Finished';
cr.


Resta apenas executar a aplicação:
bash$ gst -I blox-sample.im -f blox-sample.st


Outra opção ao BLOX é Gtk+.

[]’s
Cacilhας, La Batalema

sábado, 3 de abril de 2010

SUnit

Smalltalk Smalltalk possui um ótimo arcabouço de teste unitário chamado SUnit – Smalltalk Unit Test Suite. Porém sua documentação é um tanto fraca.

Segue aqui um pequeno tutorial de uso do SUnit. Veja que não é necessariamente a forma correta de usá-lo. Usaremos GNU Smalltalk.

Imagine que queremos implementar um método em Integer que retorna se o número é primo ou não. Podemos primeiro criar um test case para verificar seu funcionamento.

Para isso, crie um arquivo test-is-prime.st e defina a seguinte classe:
TestCase subclass: #TestIsPrime
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Unit Test'
!


A classe TestIsPrime é filha de TestCase e, para nosso fim atual, não precisará de atributos.

Precisaremos de um método de classe que execute os testes, para que não precisemos criar uma TestSuite:
!TestIsPrime class methodsFor: 'running'!

run
(self testSelectors) do: [ :test |
self run: test.
].
!
!


Podemos agora criar a categoria accessing para os testes:
!TestIsPrime methodsFor: 'accessing'!


O primeiro teste pode ser para determinar se números negativos retornam um erro quando se tenta determinar sua primalidade:
testNegative
self should: [ -1 isPrime ] raise: ArithmeticError.
!


Não esqueça de indentar!
[update 2010-04-04]
A indentação aqui tem objetivo exclusivo de manter a clareza do código.
[/update]


O método #should:raise: executa um bloco e asserta que uma exceção será levantada, neste caso ArithmeticError.

Podemos fazer o mesmo para zero:
testZero
self should: [ 0 isPrime ] raise: ArithmeticError.
!


Já para o número um, é preciso assertar que ele não é primo, ou seja, retorne falso:
testOne
self shouldnt: [ 1 isPrime ].
!


O método #shouldnt: executa um bloco esperando pelo retorno falso.

Mas quando chegarmos ao dois, ele é primo:
testTwo
self should: [ 2 isPrime ].
!


O método #should: executa um bloco esperando pelo retorno verdadeiro.

Você pode fazer isso indefinidamente se quiser:
testSomeOtherValues
self should: [ 3 isPrime ].
self shouldnt: [ 4 isPrime ].
self should: [ 5 isPrime ].
self shouldnt: [ 6 isPrime ].
self should: [ 7 isPrime ].
self shouldnt: [ 8 isPrime ].
self shouldnt: [ 9 isPrime ].
self shouldnt: [ 10 isPrime ].
self should: [ 11 isPrime ].
!


Quando cançar, encerre a lista de métodos da categoria com a linha:
!


Ou, se preferir ser mais explícito:
!!


No final, adicione uma linha para executar os testes:
TestIsPrime run.


Para rodar os testes, copie a imagem contendo seu código para, por exemplo, test.im e acrescente o SUnit com o seguinte comando:
bash$ gst-load -I test.im SUnit


Agora, com a imagem preparada, você pode executar os testes:
bash$ gst-sunit -I test.im -f test-is-prime.st


Se tudo correr bem, nada acontecerá, caso contrário você poderá receber uma mensagem do tipo:
TestIsPrime>>#testSomeOtherValues ..
FAILURE: Assertion failed


Onde TestIsPrime>>#testSomeOtherValues significa que falhou o teste contido no método #testSomeOtherValues da classe TestIsPrime.

[]’s
Cacilhας, La Batalema

sexta-feira, 5 de março de 2010

Python é capa da TIdigital de Março

Gente,

Segunda-feira todo mundo correndo pras bancas!
TIdigital Março

Em março, Python em foco na revista TIdigital.

Fonte: PythOn Rio.

[]’s
Cacilhας, La Batalema

sábado, 27 de fevereiro de 2010

MongoDB

Logo Há atualmente na Computação uma onda de adoção de bancos de dados não-relacionais, comumente chamados NoSQL.

O foco principal dos bancos NoSQL atuais é a orientação a documentos, uma variação hash da orientação a objetos e alternativa aos RDBMSs, que dominaram a orientação dos gerenciadores de banco de dados por décadas.

O principal banco NoSQL é o CouchDB, DBMS do Projeto Apache baseado em Erlang, porém há uma alternativa bem mais simples e aparentemente tão poderosa quanto: MongoDB.

MongoDB combina os melhores funcionalidades de orientação a documentos, hashes e RDBMSs. É um banco de dados orientado a documentos, escalável, livre de esquema, de alto desempenho e código aberto escrito em C++.

Este artigo dá continuidade ao artigo nas Reflexões de Monte Gasppa e Giulia C. sobre a instalação do MongoDB. Aqui você poderá ver um pouquinho do uso de um banco de dados orientado a documentos.

Este artigo é baseado na documentação oficial e entende que você instalou o MongoDB segundo descrito nas Reflexões de Monte Gasppa e Giulia C..

Conexão na base de dados


Para conectar na base basta usar o comando mongo:
bash$ mongo
MongoDB shell version: 1.2.2
url: test
connecting to: test
type "help" for help
>


Caso você tenha configurado uma porta alternativa em /srv/mongodb/etc/mongodb.conf, você pode especificar isso na linha de comando do cliente:
bash$ mongo --port 27018


Você também pode se conectar a um servidor remoto, caso ele esteja habilitado para conexão externa, usando a flag --host.

Para escolher qual base de dados usar, o comando é use:
> use mydb


Autorização


Você pode se autorizar na linha de comando com as opções -u (usuário) e -p (senha), ou já do prompt do interpretador:
> use admin
> db.auth('admin', 'ra35EG/dz');


Comandos básicos


A linguagem de interação com MongoDB é Javascript, mas há alguns comandos úteis no interpretador.

Para listar comandos úteis:
> help


Listar recursos uteis da base atual:
> db.help();


Listar recursos uteis de uma coleção (levemente equivalente a tabela de um banco relacional), no exemplo foo:
> db.foo.help();


Para listar as bases instaladas:
> show dbs


Para listar as coleções da base atual:
> show collections


Listar usuários da base atual:
> show users


Criar usuário na base atual:
> db.addUser('admin', 'ra35EG/dz');


Autenticar-se:
> db.auth('admin', 'ra35EG/dz');


Listar o conteúdo de uma coleção:
> db.foo.find();


Apagar uma coleção:
> db.foo.drop();


Apagar a base de dados atual:
> db.dropDatabase();


Armazenamento de dados


Repare que o MongoDB é livre de esquema, portanto uma coleção pode conter estruturas de dados radicalmente diferentes, sempre no formato JSON.

Por exemplo, vamos inserir dois dados distintos na coleção foo da base mydb:
> use mydb
> var j = { name: 'mongo' };
> var t = { x: 3 };
> db.foo.save(j);
> db.foo.save(t);
> db.foo.find();
{ "_id" : ObjectId("4b8949d9cd50237b8573833b"), "name" : "mongo" }
{ "_id" : ObjectId("4b8949dbcd50237b8573833c"), "x" : 3 }


Você não precisa predefinir a coleção, que é criada automaticamente no salvamento da primeira estrutura. O campo _id é criado automaticamente e é a chave primária.

Para apagar o objeto j:
> j = db.foo.findOne({ name: 'mongo' });
> db.foo.remove(j);


Para apagar todos os objetos basta remover a coleção:
> db.foo.drop();


Vamos usar um pouco mais de lógica:
> for (var i=0; i<100; ++i) db.foo.save({ x: i, y: i*i });


Esse loop cria cem registros, com x variando de zero a noventa e nove e y igual a seu quadrado:
> db.foo.find();
{ "_id" : ObjectId("4b894c05cd50237b8573833e"), "x" : 0, "y" : 0 }
{ "_id" : ObjectId("4b894c05cd50237b8573833f"), "x" : 1, "y" : 1 }
{ "_id" : ObjectId("4b894c05cd50237b85738340"), "x" : 2, "y" : 4 }
{ "_id" : ObjectId("4b894c05cd50237b85738341"), "x" : 3, "y" : 9 }
{ "_id" : ObjectId("4b894c05cd50237b85738342"), "x" : 4, "y" : 16 }
{ "_id" : ObjectId("4b894c05cd50237b85738343"), "x" : 5, "y" : 25 }
{ "_id" : ObjectId("4b894c05cd50237b85738344"), "x" : 6, "y" : 36 }
{ "_id" : ObjectId("4b894c05cd50237b85738345"), "x" : 7, "y" : 49 }
{ "_id" : ObjectId("4b894c05cd50237b85738346"), "x" : 8, "y" : 64 }
{ "_id" : ObjectId("4b894c05cd50237b85738347"), "x" : 9, "y" : 81 }
{ "_id" : ObjectId("4b894c05cd50237b85738348"), "x" : 10, "y" : 100 }
{ "_id" : ObjectId("4b894c05cd50237b85738349"), "x" : 11, "y" : 121 }
{ "_id" : ObjectId("4b894c05cd50237b8573834a"), "x" : 12, "y" : 144 }
{ "_id" : ObjectId("4b894c05cd50237b8573834b"), "x" : 13, "y" : 169 }
{ "_id" : ObjectId("4b894c05cd50237b8573834c"), "x" : 14, "y" : 196 }
{ "_id" : ObjectId("4b894c05cd50237b8573834d"), "x" : 15, "y" : 225 }
{ "_id" : ObjectId("4b894c05cd50237b8573834e"), "x" : 16, "y" : 256 }
{ "_id" : ObjectId("4b894c05cd50237b8573834f"), "x" : 17, "y" : 289 }
{ "_id" : ObjectId("4b894c05cd50237b85738350"), "x" : 18, "y" : 324 }
{ "_id" : ObjectId("4b894c05cd50237b85738351"), "x" : 19, "y" : 361 }
has more


Consultas (queries)


É possível fazer consultas simples ou bem complexas assim como em modelos relacionais usando MongoDB.

Vamos obter uma contagem de objetos:
> db.foo.find().count();
100


Só os cinco primeiros objetos:
> db.foo.find().limit(5);
{ "_id" : ObjectId("4b894c05cd50237b8573833e"), "x" : 0, "y" : 0 }
{ "_id" : ObjectId("4b894c05cd50237b8573833f"), "x" : 1, "y" : 1 }
{ "_id" : ObjectId("4b894c05cd50237b85738340"), "x" : 2, "y" : 4 }
{ "_id" : ObjectId("4b894c05cd50237b85738341"), "x" : 3, "y" : 9 }


Agora os cinco seguintes:
> db.foo.find().skip(5).limit(5);
{ "_id" : ObjectId("4b894c05cd50237b85738343"), "x" : 5, "y" : 25 }
{ "_id" : ObjectId("4b894c05cd50237b85738344"), "x" : 6, "y" : 36 }
{ "_id" : ObjectId("4b894c05cd50237b85738345"), "x" : 7, "y" : 49 }
{ "_id" : ObjectId("4b894c05cd50237b85738346"), "x" : 8, "y" : 64 }
{ "_id" : ObjectId("4b894c05cd50237b85738347"), "x" : 9, "y" : 81 }


Para obter o elemento com valor de x vinte e quatro:
> var e = db.foo.findOne({ x: 24 });
> print(e.y);
576
> print(tojson(e));
{ "_id" : ObjectId("4b894c05cd50237b85738356"), "x" : 24, "y" : 576 }


Consultas avançadas


Vamos complicar um pouco…

Para obter todos os registros com x maior que cinquenta:
> db.foo.find('this.x > 50');
{ "_id" : ObjectId("4b894c05cd50237b85738371"), "x" : 51, "y" : 2601 }
{ "_id" : ObjectId("4b894c05cd50237b85738372"), "x" : 52, "y" : 2704 }
{ "_id" : ObjectId("4b894c05cd50237b85738373"), "x" : 53, "y" : 2809 }
{ "_id" : ObjectId("4b894c05cd50237b85738374"), "x" : 54, "y" : 2916 }
{ "_id" : ObjectId("4b894c05cd50237b85738375"), "x" : 55, "y" : 3025 }
{ "_id" : ObjectId("4b894c05cd50237b85738376"), "x" : 56, "y" : 3136 }
{ "_id" : ObjectId("4b894c05cd50237b85738377"), "x" : 57, "y" : 3249 }
{ "_id" : ObjectId("4b894c05cd50237b85738378"), "x" : 58, "y" : 3364 }
{ "_id" : ObjectId("4b894c05cd50237b85738379"), "x" : 59, "y" : 3481 }
{ "_id" : ObjectId("4b894c05cd50237b8573837a"), "x" : 60, "y" : 3600 }
{ "_id" : ObjectId("4b894c05cd50237b8573837b"), "x" : 61, "y" : 3721 }
{ "_id" : ObjectId("4b894c05cd50237b8573837c"), "x" : 62, "y" : 3844 }
{ "_id" : ObjectId("4b894c05cd50237b8573837d"), "x" : 63, "y" : 3969 }
{ "_id" : ObjectId("4b894c05cd50237b8573837e"), "x" : 64, "y" : 4096 }
{ "_id" : ObjectId("4b894c05cd50237b8573837f"), "x" : 65, "y" : 4225 }
{ "_id" : ObjectId("4b894c05cd50237b85738380"), "x" : 66, "y" : 4356 }
{ "_id" : ObjectId("4b894c05cd50237b85738381"), "x" : 67, "y" : 4489 }
{ "_id" : ObjectId("4b894c05cd50237b85738382"), "x" : 68, "y" : 4624 }
{ "_id" : ObjectId("4b894c05cd50237b85738383"), "x" : 69, "y" : 4761 }
{ "_id" : ObjectId("4b894c05cd50237b85738384"), "x" : 70, "y" : 4900 }
has more


Outra opção é usar o operador condicional $gt:
> db.foo.find({ x: { $gt: 50 } });


Da mesma forma outros operadores. Por exemplo, todos os elementos com x entre vinte e três e vinte e seis, inclusive:
> db.foo.find('23 <= this.x && this.x <= 26');


Ou:
> db.foo.find({ x: { $gte: 23, $lte: 26 } });


Os principais operadores são:
  • $lt – menor que
  • $gt – maior que
  • $lte – menor ou igual a
  • $gte – maior ou igual a
  • $ne – diferente de
  • $in – está em (recebe uma lista)
  • $nin – não está em
  • $mod – resto igual a (recebe uma lista onde o primeiro valor é o divisor e o segundo o resto)
  • $exists – contém ou não o atributo
  • $not – negação de uma condição


Ordenação


A ordenação é feita usando o método sort. Por exemplo, para ordenar de modo descrescente pelo atributo y:
> db.foo.find().sort({ y: -1 });


Expressões regulares

Quando há campos com valor string, é possível usar expressões regulares:
> db.foo.find({ name: /^mon.o$/i });


Índices

Quando você faz muitas consultas baseadas em um determinado atributo, é interessante criar um índice para ele. Por exemplo, se quisermos criar um índice para nosso atributo x:
> db.foo.ensureIndex({ x: 1 });


Obs.¹: o atributo _id possui índice por padrão.

Obs.²: é possível criar índices compostos.

Agregação


Não vou entrar nesse mérito, mas é possível criar agregações, como GROUP_BY de SQL. Para tanto veja a documentação oficial.

Módulos de conexão com linguagens de programação


Há módulos para várias linguagens, que podem ser encontrados na lista de APIs.

O módulo que pude e me fascinou foi para Python. Sua instalação usando easy_install foi muito simples:
bash$ sudo easy_install -U pymongo


E seu uso extremamente fácil devido à similiaridade entre dicionários de Python e JSON. A única reclamação que faço é o fato do método db.auth() do MongoDB ter sido traduzido como db.authenticate() em Python, o que me fez perder alguns segundos tentando entender por que não funcionava.

**


Espero que este artigo seja mais do que útil e incite o uso dessa intrigante ferramenta.

[]’s
Cacilhas, La Batalema

quinta-feira, 25 de fevereiro de 2010

Kodumaro no Twitter

Twitter Kodumaro agora no Twitter!

@kodumaro


A conta será usada para divulgar novos artigos e para troca de ideias com os leitores.

[]’s
Cacilhas, La Batalema

quinta-feira, 14 de janeiro de 2010

FizzBuzz (No Stairway to Heaven)

Glider Hoje um amigo meu veio falar comigo de uma brincadeira velha – e que eu não conhecia – chamada FizzBuzz.

[update 2010-01-15]
Sugestão de apontador do Cesar Barros: If something is worth doing….

A propósito, atualizei o código Lisp.
[/update]

A brincadeira consiste em imprimir uma sequência de números, tradicionalmente de 1 a 100. Porém os números múltiplos de 3 devem ser substituídos por fizz e os números múltiplos de 5 por buzz. Os números que são divisíveis por 3 e por 5 devem ser substituídos por fizzbuzz.

No Stackoverflow você pode encontrar as versões mais loucas, como LOLCODE, Brainf*ck, Ook, assembly de 8051, 6502 e Linux IA-32, Hebreu Estruturado, Cobol e Forth, como destaque para o poético código em Perl.

Aqui quero postar algumas soluções que achei interessantes.

**

Em Haskell:
putStr (concat [if (mod x 15)==0 then "fizzbuzz\n" else if (mod x 3)==0 then "fizz\n" else if (mod x 5)==0 then "buzz\n" else (show x) ++ "\n" | x <- [1..100]])


Em Python:
print "\n".join('fizzbuzz' if x%15==0 else 'fizz' if x%3==0 else 'buzz' if x%5==0 else str(x) for x in xrange(1, 101))


Em Perl:
print +(fizz)[$_%3] . (buzz)[$_%5] || $_, $/ for 1..100;


Em Common Lisp:
(format t "~{~A~%~}" (loop for x from 1 to 100 collect (if (zerop (mod x 15)) "fizzbuzz" (if (zerop (mod x 3)) "fizz" (if (zerop (mod x 5)) "buzz" x)))))


[]’s
Cacilhas, La Batalema

sexta-feira, 8 de janeiro de 2010

Ajude a mostrar a PythonBrasil na PyCon 2010

Meu amigo Henrique Bastos publicou hoje um artigo entitulado Ajude a mostrar a PythonBrasil na PyCon 2010.

A proposta é muito legal e já preenchi o formulário para reunir informações sobre a Comunidade Python no Brasil.

Segue uma reprodução do artigo:
Salve Pythonistas!

De 19 a 21 de fevereiro será realizada a PyCon, em Atlanta nos Estados Unidos. Como alguns de vocês já sabem, participarei do evento apresentando a palestra #78 entitulada «Small acts make great revolutions».

Esta apresentação será uma evolução da palestra relâmpago que fiz na PythonBrasil[5] em Caxias do Sul, onde tento difundir os conceitos por trás das iniciativas que vêm movimentando a comunidade no Rio de Janeiro.

No entanto, falar só do que acontece no Rio me parece muito pouco para uma oportunidade dessas. Quero muito aproveitar a PyCon para mostrar o grande desenvolvimento da Comunidade Python no Brasil. Pessoasfantásticas estão fazendo as coisas acontecerem em Terras Brasilis. E a exemplo do que fiz no FISL 10, pretendo continuar na linha de tentar evidenciar que na nossa comunidade, o todo é muito maior do que a soma das partes. Mas para isto, eu preciso da ajuda de vocês.

Para poder falar com propriedade sobre a Comunidade Python no Brasil, precisamos traçar o perfil do nosso grupo. Por isso, preparei um rápido questionário online que ajudará a levantar informações sobre nossa comunidade. Ele está disponível em: http://henriquebastos.wufoo.com/forms/vamos-divulgar-nossa-comunidade-python-na-pycon/

É muito importante que o maior número de pythonistas respondam à pesquisa. Isso vai ajudar muito! Portanto, não economizem nos retweets e espalhem o link da pesquisa por todas as listas de email no Brasil, relacionadas com Python.

Além disso, também estou buscando links para boas fotos em alta resolução, como as tiradas na escadaria da PUC-RS durante o FISL 10 e as fotos «aéreas» da PythonBrasil[4] na UVA etc. Basta publicarem os links para as fotos nos comentários deste post ou me enviar por email.

Obrigado à todos, e vamo que vamo!

[]’s!


Já andei tuitando e divulguei nas Reflexões de Monte Gasppa e Giulia C. também. Convido todos então a ler o artigo e preencher o formulário, ajudando assim o Henrique a revelar e expor a Comunidade Python no Brasil ao Mundo!

[]’s
Cacilhas, La Batalema