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