Um Manifesto!

...

  • Increase font size
  • Default font size
  • Decrease font size

Blog

Programação Funcional: Lendo listas e funções

E-mail Print PDF

Entender Programação Funcional é uma tarefa bem complicada no começo, por ser uma mudança extremamente radical na forma de pensar e de programar.

Na minha opinião temos dois pontos fundamentais a considerar: Listas e Funções. Exceto por modificadores de leitura, tudo ou é um ou é outro, e depende de ambos. Claro que há muito mais, mas acho esse o básico para ao menos “Ler” algo funcional.

Uma Lista não é um Array( ou Vetor) como estamos acostumados, mas uma série encadeada de símbolos(que podem ser ou não outra lista ou função). Para construir a seguinte lista : "Maça, Banana, Laranja" é entendida em idiomas LISP assim: (Maçã Banana Laranja).

Para entender um lista encadeada, podemos ter algo assim: (Maçã ("Banana nanica" "Banana D'Água") Laranja). É uma lista de 3 elementos, sendo que o segundo elemento é uma lista de dois elementos, mas se for assim (Maçã (Banana nanica Banana D'Água) laranja) o segundo elemento tem 4 elementos.

O processamento de Listas (LISP é isso) é feito da seguinte forma, supondo a lista:

(somar 1 2 (dividir 6 3))

O primeiro elemento de uma lista é esperado uma função, os elementos seguintes serão seus parâmetros, então temos a função "somar" recebendo os parâmetros inteiros 1 e 2, e como terceiro parâmetro vai receber o resultado do processamento da lista (dividir 6 3), que vai ser processada como uma chamada a função "dividir" recebendo 6 e 3 como parâmetros, o resultado volta como terceiro parâmetro a somar.

Como podemos ter quase qualquer coisa como símbolos, essa linha é implementada assim:

(+ 1 2 (/ 6 3))

"+" é um simbolo comum, que contem(aponta, na verdade) uma função capaz de somar que receber n argumentos, assim como "/" contem a função de divisão. Toda Lista é processada dessa forma, função + argumentos, apesar de termos modificadores (como # ou ') que alteram esse comportamento. Um array por exemplo é feito dessa forma: [ x y z ], logo não é um lista.

Agora chegamos nas funções, são exatamente como as funções matemáticas. Em LISP se define uma função usando a função especial “defun”, aqui vou usar o idioma de Clojure para demonstrar isto. Em clojure temos:

(defn funcao [x] ( processa x ) )

E o que isso quer dizer? Chamo a função “defn” e passo como argumentos o simbolo “funcao”, o array [x] e a lista ( processa x). “defn” vai ligar ao simbolo de escopo local “funcao” uma função que recebe um argumento ([x]) que será ligado a variável “x” do escopo interno da função, e que vai retornar o resultado da lista (processa x).

Como defn é uma função especial, (processa x) não é processado imediatamente, e sim, apenas quando a função for chamada. Assim quando eu chamo (funcao 3) esta lista vai retornar o resultado de (processa 3). Em um exemplo mais prático, temos:

(defn hello [name] ( println “Hello ” name) )
(hello “Diogo”) ; imprime “Hello Diogo”
(hello “Você”) ; imprime “Hello Você”

Este poderia ser implementado assim:

( (fn [name] (println “Hello ” name)) “Diogo” )

Definindo a função na hora, e passando o argumento. Então por exemplo podemos encadear chamadas:

(defn hello-maker [name] (str “Hello ” name)) ; retorna (str “Hello “ name), str constroi a String
(defn speaker [toSpeak] (println toSpeak))
(speaker (hello-maker “Diogo”))  
(defn quick-speak [speaker maker name] ( speaker (maker name))) ; são simbolo, e dentro de um escopo
(quick-speak speaker maker “diogo”)

Lembrando que por padrão somente o primeiro item é interpretado como função, a estrutura acima funciona. Agora um exemplo mais legal, fatorial, formatado:

(defn fac [x] (
  if (= x 1)
  x
  (* x (fac (- x 1)))
  )
)

Aqui temos uma séries de funções, a função ligada ao simbolo “=” recebe dois argumentos e retorna verdadeiro (booleano mesmo) se forem, quem diria, iguais. A função “if” (também é especial) recebe tres argumentos: Um boleano, uma lista(ou simbolo) para retornar em caso verdadeiro e uma para retorna caso falso. Ambas não são processadas até que if seja resolvido.

Então ao chamar (fac 5) temos x = 5, se a função “=” resolver que x e 1 são iguais, fac vai retorna x, se não vai retornar uma lista (* x (fac (- x 1))).

Então temos para retorna a função “*” que recebe x e (fac (- x 1)), processando temos fac recebendo (- x 1), que é a função “-” rebendo x e 1 , e vai retornar(surpresa) x - 1 , então retorna fac 4 (que vai ser 4 vezes factorial de 3), e por ai vai.

No caso do (fac 5) temos, no final:

(* 5 (* 4 (* 3 (* 2 1))))
(* 5 (* 4 (* 3 (2))))
até
120

Então:

(defn fac [x] ( if (= x 1) x (* x (fac (- x 1)))))
(println (fac 5)) ; imprime 120

Como disse, isso é o básico do básico, programação funcional é algo bem complexo e há muito a se aprender ainda, mas é divertido e vale a pena. Ainda bem que não sou professor, por me perdi completamente explicando ;)

Last Updated on Monday, 25 May 2009 20:06
 

Descontrair: A arte da programação

E-mail Print PDF

Um conto zen:

Eis que em uma aula de formação de monges programadores Zen, o aprendiz mais jovem perguntou:

"Como devo fazer:
static double fac(int x) {double fac = 1 ;while(x>0) fac=fac*x-- ; return fac ;}
ou
static double fac(int x) {if(x==1) return 1; else return x*fac(x-1) ;} ? "

Vários, prontamente e cheios de pompa, responderam:
def fatorial(number)
  if (number == 0)
    return 1
  else
    return number * fatorial(number - 1)
  end
end

Alguem disse, em voz baixa, como se não fizesse questão de falar:
def fatorial(num):
  if num <= 1:
    return 1
  else:
    return num * fatorial(num - 1)

Um dos alunos mais antigos diz desdenhando:
int fatorial(int num) {
  long fat;
  for(fat=1;num > 1;num--) {
    fat= fat*num;
  }
  return fat;
}

Eis que o mestre enigmaticamente responde a todos, que ficam perplexos:
(defn fac [x] ( if (= x 1) x (* x (fac (- x 1)))))

Após os ensinamentos, todos voltam a sua rotina e estágios, onde se deparam com a dura realidade da resposta:

function fac($num) {
 for($fac=1;$num>1;$num--){
  $fac = $fac * $num;
 }
 return $fac;
}


As vezes a resposta é que você menos deseja aceitar.

Ao voltarem no dia seguinte, cheios de questões sobre a vida e Scrum, encontram o mais Jovem caído em frente a porta, em estado de choque, babando, com uma singela mensagem em suas mãos:

Function fatorial2(valor)  
 Dim i, mult
 mult = valor  
 For i = valor-1 To 1 Step -1  
  mult = mult * i  
 Next  
 fatorial2 = mult  
End Function 

Neste dia, ninguém alcançou a iluminação.

Então o acadêmico mestre, entristecido por seus alunos que não podiam ver a luz fora da sala, perguntou a grande oraculo sobre a questão de seu perdido aprendiz, este definiu, sem mais:

fatorial

E o mestre finalmente entendeu o que deveria ensinar. 

Last Updated on Monday, 25 May 2009 20:08
 

Entrando na computação nas nuvens, com PHP e o Google App Engine

E-mail Print PDF

Continuando as aventuras em diferentes plataformas, hoje vamos levar o PHP para as nuvens com o Google App Engine. Se alguem já rodou o PHP no Quercus, fique tranquilo por que este é bem mais fácil.

Você vai precisar criar um conta no GAE na plataforma Java, que é early access ainda. Enquanto espera a liberação da conta, vamos preparar o ambiente de desenvolvimento.

Primeiro baixe o SDK java do google app engine da página do google, é o appengine-java-sdk. Extraia-o em algum lugar onde possa trabalhar com ele.

Agora pegue o projeto em branco do PHP, já pronto para o GAE, e o extraia proximo ao SDK.

Para ver o "hello world", você precisa executar o servidor de desenvolvimento para esta aplicação. O SDK vem com o utilitário para tal, a linha de comando para iniciar o servidor é esta:

$ appengine-java-sdk/bin/dev_appserver.sh blankphp/war

Basta chamar o script do servidor e passar o caminho do war da aplicação, agora esta acessivel em http://localhost:8080

Agora para começar seu próprio projeto crie um cópia do blankphp com o nome do seu app. Nesta nova pasta edit no arquivo  war/WEB-INF/web.xml, próximo do fim, a entrada servlet-mapping que aponta para phpblank para apontar para o novo projeto. Depois edite o appengine-web.xml na mesma pasta para o application corresponda a sua aplicação. Agora basta apontar o servidor para a nova pasta.

O desenvolvimento se dá colocando o conteúdo do "site" na pasta war, a partir da raiz. É legal colocar também um favicon.ico na raiz, senão a app engine reclama disso. No arquivo WEB-INF/urlrewrite.xml é possivel configurar redirecionamentos de URL como o Apache, no formato <rule><from>^$</from><to>index.php?$1</to></rule>.

Conforme a colaboração do Igor Cemim (lá no comentários), veja que por padrão o GAE não assume o index.php como arquivo de entrada padrão, ou seja ao entrar na URL sem /index.php não aparece nada. A solução é incluir a seguinte regra no urlrewrite.xml. Valeu Igor!

Graças ao Quercus, você pode fazer chamadas das classes java direto dentro do PHP, seguindo o exemplo:

<?

import  com.google.appengine.datastorage.Text ;
$text = new Text( "String");
echo $text->getValue();

?>

Veja que rodar uma aplicação no GAE não é a mesma coisa que no LAMP, a maior mudança é , sem dúvidas, no banco de dados. Por que não tem.

Não é que não tenha, mas como o JDBC não esta disponível, também não estão o PDO e *_connect() do PHP/Quercus. A solução de storage do GAE é o datastorage, atráves de JDO, JPA ou JDOQL.

Para usar o JDO você precisa criar as entidades em Java, no blankphp vem um exemplo bem fraco de como faze-lo. Você vai precisar compilar as classes com o ant (o build.xml já esta configurado), usando:

$ ant compile
E "enhance" a classe a ser persisitida (caso não esteja no build):

$ java -cp ../appengine-java-sdk/lib/appengine-tools-api.jar:war/WEB-INF/classes:../appengine-java-sdk/lib/user/appengine-api-1.0-sdk-1.2.1.jar com.google.appengine.tools.enhancer.Enhance war/WEB-INF/classes/app/JsonJDO.class

Lembrando de corrigir os caminhos para os JAR de acordo. Para usar o exemplo no PHP você poderia fazer assim:

<?

import Storage ;
$st = new Storage ;
$obj = $st->get($_GET['id']);
$json = $obj->getJson()->getValue();

$jsonNovo = '{"nome":"Diogo"}';
$st->put($_GET["id'],$jsonNovo);

?>

Agora, depois de escrever suas classes Java, seus arquivos PHP, frameworks etc, e tiver testado bastante (localhost:8080), é hora de enviar para o GAE, com a seguinte linha:

$ appengine-java-sdk/bin/appcfg.sh update blankphp/war

Trocando, claro, o blankphp pelo nome do projeto, depois vai pedir login e senha, e pronto, basta acessar seu app no GAE e ver tudo funcionar(ou não!).

Last Updated on Tuesday, 11 August 2009 00:38
 

Simples Ideias evolui para IdeasWall.org!

E-mail Print PDF

Como disse em um texto anterior, acho que tecnologia se aprende fazendo, como eu queria aprender e testar algumas coisas, surgiu o Simples Ideias. Na época, em janeiro, queria colocar em prática o máximo que aprendi sobre Restful, JQuery e Spaghetti,  e o Simples Ideias foi uma boa experiência.

Mas agora eu queria mais, então primeiro com o intuito de internacionalizar o aplicativo, surgiu o IdeasWall.org, que é a evolução do simples ideias, mas em inglês e com novas tecnologias. 

O básico continua o mesmo serviço, de guardar Idéias em Tags e acessar em qualquer lugar. Mas só isso que continua o mesmo.

Eu ia reescrever o serviço em outra linguagem sem ser PHP, como Clojure, mas essa mudança iria demorar muito então resolvi por reescrever, mas em PHP mesmo, mas sem usar o Spaghetti* por motivos que vou explicar mais a frente. Como o serviço é simples foi rápido reescreve-lo e graças aos testes em CURL, estava tudo funcionando. Vamos as interfaces:

Mobile. (J2ME)

O principal objetivo do app, desde antes, era acessar em qualquer lugar. Então a primeira nova interface a ficar pronta foi a para celular. Feita em J2ME de forma extremamente simples aqui pus em prática o estudo desta tecnologia.

As telas são simples e com controles rápido, todos os algoritmos foram reduzidos para caber nos aparelhos mais limitados, e o acesso a web é feito apenas quando necessário e com chamadas o reduzidas.

Obviamente também não oferece muitos recursos e não haverá muitos updates, exceto a opção de trabalhar offline e sincronizar por demanda no futuro.

Web. (JQuery)

A versão web, escrita em JQuery, foi a cópia da antiga interface do serviço, apenas adaptando as mudanças no webservice. É a primeira interface rica, e foi a ultima a ficar pronta, pois o JavaScript esta um lixo, shame on me.

Apesar disso é talvez a melhor opção de acesso, oferece todos os recursos implementados no serviço com um desempenho muito bom, além de esta a um link de distância.

Nela usei os recursos de Arrastar nós, Edição sem sair da página, Abas e muita requisição assíncrona com Json. Funciona no Opera, no Firefox, no Chrome e no IE 7, não funciona no IE6. No IE7 até que foi fácil, neste app eu não ligo para o IE6 mesmo. Não pude testar no Safari, mas aposto que não funciona.

Desktop. (JavaFX) 

Sem dúvida, o principal motivo do novo aplicativo. Estou muito empolgado com  a tecnologia do JavaFx e resolvi fazer um app para o JavaFx Challenge,  como não tive muito criatividade em pensar em algo novo, resolvi refazer o app de idéias. Como ia para o challenge ia ter que passar a Inglês e padronizar mais o serviço, então refiz logo tudo.

JavaFx é muito bom de trabalhar, com sua sintaxe declarativa e similaridades com programação funcional(um pouco longe, mas...) e ainda assim acesso a todo poder dos pacotes do Java. Essa foi o primeiro do novo serviço a ser implementado, logo após reescrever o PHP pela primeira vez. 

Essa é com certeza o que mais me dediquei, a interface esta tão trabalhada quanto aguentei, usei os belos icones do KDE, Oxygen e Crystal SVG, para me ajudar, e tentei deixar a interface o mais funcional possível.

Graças ao JavaFx o app funciona nos navegadores(Qualquer) como applet, ou pode ser lançado separado com o WebStart, além de poder arrasta-lo para área de trabalho para deixar instalado localmente.

Infelizmente ainda existem problemas, o  tempo para carregar o applet ainda acho muito demorado, mas a versão Webstart e local não sofrem disso, a API ainda tem poucas coisas mas de fácil extensão, e esbarrei num bug sinistro nos HttpRequest que paravam de funcionar. 

O Runtime é razoavelmente rápido até, e a experiência é boa, com  resposta rápida da interface o feedback é bom. Com as otimização corretas no código é fácil eliminar os gargalos. E em todo lugar que testei funcionou igual.

Webservice. (PHP e GAE) 

Como disse no começo reescrevi o webservice por que o queria em inglês e mais padronizado. Como o foco inicial era o JavaFx a primeira reescrita em PHP foi rápida, usei o RestServer e um classe de Sql qualquer, e em meio-dia estava pronta para testar o Javafx e mais tarde baixaria o Framework novamente e melhoraria o código.

No decorrer do desenvolvimento porém resolvi aproveitar a oportunidade para testar o Google App Engine, que tinha lançado o ambiente Java e já havia resultados usando o PHP através do Quercus. Quando o JavaFx já estava quase pronto, me cadastrei no GAE e registrei o domínio. 

Enquanto esperava entrar no GAE, instalei o Quercus para começar a portar o serviço, deu um bom trabalho mas funcionou. Aproveitei e comecei a adaptar logo a interface Web. Ai o tempo  estava esgotando, já que meu prazo é o JavaFx challenge.

Quando resolvi finalmente passar ao GAE tive ainda de configurar tudo, e a parte que mais me atrapalhou, mudar o esquema de banco de dados. Quer dizer, no GAE não temos um banco de dados comum, disso eu sabia, mas o que eu não tinha percebido é que não poderia usar um externo também!

Bom, tive que aprender JDO, fazer a persistência o mais simples possível em Java adaptar todo o PHP para usar o novo esquema, "wrapping" toda a alteração em uma classe de conexão em PHP.  

Enfim, estou cansado e resolvi deixar o web service como esta, já que ainda havia o bug no JavaFx, a página a escrever e testar tudo no Windows. Mas, finalmente, desde de o começo de abril com esse projeto, esta tudo pronto! Viva viva.

E agora?(futuro)

Pronto esta, mas ainda tem muito o que acrescentar:

  • Vou reescrever o serviço com certeza, mas ainda não sei se em PHP.
  • Um interface(ou adaptar a atual) capaz de ficar na bandeja.
  • Possibilidade de usar offline com sincronismo por demanda, em todas as versões.
  • IPhone?
  • Ambiente compartilhado?
  • Integração com o Google Calendar e E-mail?
  • Notas com data para termino ou para acontecer.

Fim. 

Espero que não tenha muito erro de português, não revisei o texto e estou com fome ;) 

Last Updated on Thursday, 14 May 2009 15:40
 

Rodando PHP no Quercus, no Linux

E-mail Print PDF

Conhece o Quercus? Se não, é um servlet "mui legal" capaz de rodar PHP em cima da plataforma Java, que tem ótima performance e capaz de integrar Java e PHP de forma transparente. Você pode inclusive usar as Classes do Java no PHP diretamente, e ter recursos como Threads e os frameworks PHP rodando lado-a-lado. 

E por que precisamos disso se já temos  o próprio PHP? Primeiro é sempre bom ter opções, mas também legal para configurar o PHP em ambiente já pronto para o Java, como o Google App Engine, e que por algum motivo ainda não suporta PHP. 

Agora vamos ao trabalho sujo, como configurar o Quercus com o Jetty no Linux. Primeiro, instale o Jetty, baixe a versão mais recente do Codehaus, como root:

# mkdir  /opt/jetty 
# unzip jetty*.zip
# cp -R jetty-version/* /opt/jetty

Por padrão o jetty usa a porta 8080, então depois de inicia-lo basta chamar "localhost:8080" no navegador, para lançar o jetty use o sequinte comando

# cp /opŧ/jetty
# java -jar start.jar

Agora é a vez do Quercus, vá ao site dele e baixe a versão war mais recente.(quase no fim da página), e então:

# jar -xv quercus*.jar
# cp WEB-INF/lib/* /opt/jetty/lib/

Agora é configurar o Jetty para usar o quercus, vamos adcionar a webapp no /opt/jetty/test/WEB-INF/web.xml , adcione dentro da tag <webapp> :

<servlet>
  <servlet-name>Quercus Servlet</servlet-name>
  <servlet-class>com.caucho.quercus.servlet.QuercusServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>Quercus Servlet</servlet-name>
  <url-pattern>*.php</url-pattern>
</servlet-mapping>
<welcome-file-list>
  <welcome-file>index.html</welcome-file>
  <welcome-file>index.php</welcome-file>
  <welcome-file>index.jsp</welcome-file>
</welcome-file-list>

Depois crie um arquivo webapps/test/index.php com <? phpinfo() ?>, e esta pronto. Basta acessar http://localhost:8080/index.php e ver o quercus em ação.

Last Updated on Sunday, 10 May 2009 12:17
 

Configurando o ambiente para o Clojure!

E-mail Print PDF

É hora da programação funcional, vou registrar aqui os passos para deixar o ambiente pronto para aprender Clojure, no Linux e com o VIM, por que eu sei que qualquer hora dessas vou precisar repetir esses passos.

Primeiro, pegue uma cópia do Clojure , coloque em alguma pasta.

Depois, você vai precisar do JLine, no linux ele esta nos repositórios da maioria das distros, então no debian:
# aptitude install libjline-java

Sequindo na brincadeira, prepare uma pasta para deixar os arquivos para rodar o clojure, no meu caso uso o /opt/clojure:

# mkdir /opt/clojure
# cp clojure*.jar /opt/clojure
# mv /opt/clojure/clojure*.jar /opt/clojure/clojure.jar
# cp /usr/share/java/jline*.jar /opt/clojure
# mv /opt/clojure/jline*.jar /opt/clojure/jline.jar
# touch /opt/clojure/clojure
# chmod 755 /opt/clojure/*
# ln -s /opt/clojure/clojure /usr/bin/clojure

Depois você também vai precisar do clojure-contrib, em um terminal compile o svn:

# svn checkout http://clojure-contrib.googlecode.com/svn/trunk/ contrib  
# cd contrib
# ant -Dclojure.jar=/opt/clojure/clojure.jar

Vamos criar então um lançador rápido para o clojure, tanto para o REPL e para o Script, no arquivo /opt/clojure/clojure fique com o seguinte conteúdo:

#!/bin/bash
THE_DIR=/opt/clojure
if [ -z "$1" ]; then
  java -cp $THE_DIR/jline.jar:$THE_DIR/clojure.jar:$THE_DIR/clojure-contrib.jar jline.ConsoleRunner clojure.lang.Repl
else
  java -cp $THE_DIR/clojure.jar:$THE_DIR/clojure-contrib.jar clojure.lang.Script $1 -- $*

Agora basta usar a interface REPL através do console com o comando "clojure" ou passar um script através de "clojure script.clj".

Agora é a vez do VIM, através deste plugin do vim para o Clojure. Primeiro baixe a versão mais recente. Coloque no seu .vimrc as sequintes opções:

syntax on
filetype plugin ident on
let clj_hightlight_builtins  = 1 
let clj_hightlight_contrib = 1 
let clj_parens_rainbow = 1
let clj_want_gorilla = 1
let vimclojure#NailgunClient = "/opt/clojure/ng/ng"

E na pasta que descompactou o vimclojure, crie o arquivo loca.properties, com o seguinte conteúdo

clojure.jar=/opt/clojure/clojure.jar
clojure-contrib.jar=/opt/clojure/clojure-contrib.jar
nailgun-client=ng
vimdir=~/.vim/plugins

Sendo a linha do vimdir o equilivante do seu diretório, rode os comandos então

$ ant
$ ant install 

Passe para root e copie o vimclojure.jar para o /opt/clojure:

# cp build/vimclojure.jar /opt/clojure/vimclojure.jar
# mkdir /opt/clojure/ng
# cp * /opt/clojure/ng -Rf

Depois crie um arquivo para lançar o servidor nailgun, ao qual o vim vai se conectar, em /opt/clojure/ng-server: 

#!/bin/sh
THE_DIR=/opt/clojure
java -cp $THE_DIR/clojure.jar:$THE_DIR/clojure-contrib.jar:$THE_DIR/vimclojure.jar com.martiansoftware.nailgun.NGServer 127.0.0.1

E o ambiente esta pronto. Agora é aprender a usar ;)

Last Updated on Thursday, 07 May 2009 01:09
 


Page 6 of 20