<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>DestaqueBlog &#187; Português</title>
	<atom:link href="http://weblog.destaquenet.com/category/pt-br/feed/" rel="self" type="application/rss+xml" />
	<link>http://weblog.destaquenet.com</link>
	<description>Blog da equipe Destaquenet.</description>
	<lastBuildDate>Tue, 23 Nov 2010 17:06:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Emacs e Slime: Seu Laboratório Lisp</title>
		<link>http://weblog.destaquenet.com/2010/11/18/emacs-e-slime-seu-laboratorio-lisp/</link>
		<comments>http://weblog.destaquenet.com/2010/11/18/emacs-e-slime-seu-laboratorio-lisp/#comments</comments>
		<pubDate>Thu, 18 Nov 2010 12:50:40 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Português]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[dicas]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[slime]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=1175</guid>
		<description><![CDATA[Esse post vai para quem está estudando Clojure (ou outro Lisp qualquer) e está tendo dificuldades para configurar o Emacs. Não é, Ronaldo?! Esteja preparado para uma enorme quantidade de gambiarras. ELPA A primeira coisa que faço numa nova instalação &#8230; <a href="http://weblog.destaquenet.com/2010/11/18/emacs-e-slime-seu-laboratorio-lisp/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Esse post vai para quem está estudando <a href="http://clojure.org">Clojure</a> (ou outro <a href="http://en.wikipedia.org/wiki/Lisp_(programming_language)">Lisp</a> qualquer) e está tendo dificuldades para configurar o <a href="http://www.gnu.org/software/emacs/">Emacs</a>. Não é, <a href="http://twitter.com/rferraz">Ronaldo</a>?! <img src='http://weblog.destaquenet.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Esteja preparado para uma enorme quantidade de gambiarras.</p>
<h3>ELPA</h3>
<p>A primeira coisa que faço numa nova instalação do Emacs é configurar o <a href="http://tromey.com/elpa">ELPA</a>, ou <em>Emacs Lisp Package Archive</em>. Para quem não conhece, pense no ELPA como se fosse um <code>apt-get</code> da vida, guardadas as devidas proporções (como veremos a seguir).</p>
<p>As instruções para instalação podem ser vistas <a href="http://tromey.com/elpa/install.html">nesta página</a>. Se tudo der certo, agora deve ser possível rodar o comando <code>M-x package-list-packages &lt;ENTER&gt;</code>. Leia <a href="http://sean.wenzel.net/docs/emacs/quick_reference/">este documento</a> caso tenha dificuldades para usar atalhos e comandos do Emacs.</p>
<p>Após alguns instantes, a lista de pacotes disponíveis para instalação via ELPA deve ser exibida num buffer secundário.</p>
<p><span id="more-1175"></span></p>
<h3>Clojure-Mode</h3>
<p>Coloque o cursor sobre a linha do pacote <code>swank-clojure</code> e pressione a tecla <code>I</code> para marcá-lo para instalação. Faça o mesmo com o pacote <a href="http://www.emacswiki.org/ParEdit"><code>paredit</code></a>. Se outros pacotes foram marcados acidentalmente, mova o cursor para as linhas correspondentes e pressione <code>U</code> para desfazer a marcação. Pressione <code>X</code> para prosseguir com a instalação.</p>
<p>Feito isso, ao rodar o comando <code>M-x slime &lt;ENTER&gt;</code>, o Emacs irá perguntar se você deseja que ele faça o download dos JARs de Clojure. Não adianta dizer que sim, pois não irá funcionar. <img src='http://weblog.destaquenet.com/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' /> </p>
<p>Para resolver isso, baixe manualmente os <a href="http://clojure.org/downloads">JARs de Clojure</a> e os coloque no diretório <code>~/.clojure/</code>. Em seguida, baixe o <a href="http://clojars.org/repo/swank-clojure/swank-clojure/">JAR mais recente</a> projeto <a href="https://github.com/technomancy/swank-clojure">swank-clojure</a> e o coloque no diretório <code>~/.swank-clojure/</code>.</p>
<p>Pronto. Reinicie o Emacs e rode o comando <code>M-x slime &lt;ENTER&gt;</code> para iniciar um REPL Clojure dentro do Emacs!</p>
<div id="attachment_1363" class="wp-caption aligncenter" style="width: 310px"><a href="http://weblog.destaquenet.com/wp-content/uploads/2010/11/clj-repl.png"><img src="http://weblog.destaquenet.com/wp-content/uploads/2010/11/clj-repl-300x168.png" alt="REPL Clojure" title="clj-repl" width="300" height="168" class="size-medium wp-image-1363" /></a><p class="wp-caption-text">Clojure no Emacs Slime</p></div>
<p>Vale lembrar que o Slime fornece vários recursos para edição de código, como auto-completion, exibição de docstrings, entre outras coisas. Consulte o <a href="http://common-lisp.net/project/slime/">site do projeto</a> para mais informações.</p>
<h3>Outros Lisps</h3>
<p>Rode o comando abaixo para instalar duas das principais implementações open source do ANSI Common Lisp, <a href="http://www.gnu.org/software/clisp">CLISP</a> e <a href="http://www.sbcl.org/">SBCL</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> clisp sbcl</pre></div></div>

<p>Finalmente, abra o arquivo <code>~/.emacs</code> e cole o código a seguir na última linha:</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">;; paredit + lisp modes</span>
<span style="color: #66cc66;">&#40;</span>defvar *lisp-modes* '<span style="color: #66cc66;">&#40;</span>clojure-mode-hook lisp-mode-hook emacs-lisp-mode-hook
                       lisp-interaction-mode-hook slime-repl-mode-hook<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">;; config used in all lisp modes</span>
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> lisp-config <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span>paredit-mode t<span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span>show-paren-mode t<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">mapc</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">lambda</span> <span style="color: #66cc66;">&#40;</span>mode<span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#40;</span>add-hook mode 'lisp-config<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> *lisp-modes*<span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">;; other lisp implementations</span>
<span style="color: #66cc66;">&#40;</span>eval-after-load <span style="color: #ff0000;">&quot;slime&quot;</span>
  '<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">progn</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">setq</span> slime-lisp-implementations
                '<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>sbcl <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;/usr/bin/sbcl&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
                  <span style="color: #66cc66;">&#40;</span>clisp <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;/usr/bin/clisp&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<h3>Swank</h3>
<p>As últimas versões do Slime já trazem servidores Swank para diversas implementações Lisp, mas curiosamente essa parte do código não é baixada quando se instala o Slime via ELPA.</p>
<p>Certifique-se de que um cliente CVS esteja instalado e rode o comando abaixo para fazer o download da última versão do Slime:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">cvs</span> <span style="color: #660033;">-d</span> :pserver:anonymous:anonymous<span style="color: #000000; font-weight: bold;">@</span>common-lisp.net:<span style="color: #000000; font-weight: bold;">/</span>project<span style="color: #000000; font-weight: bold;">/</span>slime<span style="color: #000000; font-weight: bold;">/</span>cvsroot <span style="color: #c20cb9; font-weight: bold;">co</span> slime</pre></div></div>

<p>Em seguida, vá até o diretório <code>slime</code> recém-criado e copie todos os arquivos deste diretório por cima dos arquivos instalados via ELPA em <code>~/.emacs.d/elpa/slime-&lt;VERSION&gt;</code>. Aproveite e remova o arquivo <code>slime.elc</code> deste último diretório, já que tal arquivo é uma versão compilada de um arquivo que acabamos de sobrescrever.</p>
<p>Reinicie o Emacs. O comando <code>M-x slime &lt;ENTER&gt;</code> continua servindo para iniciar um REPL Clojure. Para iniciar um REPL SBCL, por exemplo, rode o comando <code>M-- M-x slime &lt;ENTER&gt;</code>, digite <code>sbcl</code> e pressione <code>&lt;ENTER&gt;</code>.</p>
<div id="attachment_1364" class="wp-caption aligncenter" style="width: 310px"><a href="http://weblog.destaquenet.com/wp-content/uploads/2010/11/sbcl-repl.png"><img src="http://weblog.destaquenet.com/wp-content/uploads/2010/11/sbcl-repl-300x168.png" alt="REPL SBCL" title="sbcl-repl" width="300" height="168" class="size-medium wp-image-1364" /></a><p class="wp-caption-text">SBCL no Emacs Slime</p></div>
<h4><em>&#8220;Nunca vi tanta gambiarra num lugar só&#8230;&#8221;</em></h4>
<p>Tudo seria mais fácil se o ELPA disponibilizasse versões minimamente atualizadas &#8212; e não-&#8221;capadas&#8221; &#8212; de certos pacotes, por isso creio que essa complicação deva ser temporária. Atualizarei este texto quando a coisa mudar. Para melhor, espero.</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2010/11/18/emacs-e-slime-seu-laboratorio-lisp/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Entendendo Licenças Open Source com Clojure</title>
		<link>http://weblog.destaquenet.com/2010/10/05/entendendo-licencas-open-source-com-clojure/</link>
		<comments>http://weblog.destaquenet.com/2010/10/05/entendendo-licencas-open-source-com-clojure/#comments</comments>
		<pubDate>Tue, 05 Oct 2010 12:52:42 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Português]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[app]]></category>
		<category><![CDATA[appengine]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[compojure]]></category>
		<category><![CDATA[licenças]]></category>
		<category><![CDATA[licensator]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[programação funcional]]></category>
		<category><![CDATA[projeto]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=1141</guid>
		<description><![CDATA[Só quem desenvolve ou contribui com projetos open source sabe como é legal. A pior parte é definir sob qual licença soltar o código, e essa tarefa é muitas vezes negligenciada por desenvolvedores de software. Para quem não viu, recentemente &#8230; <a href="http://weblog.destaquenet.com/2010/10/05/entendendo-licencas-open-source-com-clojure/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Só quem desenvolve ou contribui com projetos open source sabe como é legal. A pior parte é definir sob qual licença soltar o código, e essa tarefa é muitas vezes negligenciada por desenvolvedores de software.</p>
<p>Para quem não viu, recentemente colocamos no ar o <a href="http://www.destaquenet.com/portifolio/licensator/">Licensator</a>, uma aplicação web que, além de reunir informações sobre as licenças open source mais populares, é capaz de indicar as licenças apropriadas para cada caso.</p>
<p>A linguagem escolhida para implementar o projeto foi <a href="http://clojure.org">Clojure</a>, que se mostrou excelente para resolver esse tipo de problema. Veremos hoje como o principal algoritmo da aplicação funciona.</p>
<p><span id="more-1141"></span></p>
<h3>REPL: onde tudo começa</h3>
<p>Um dos pontos fortes das linguagens dinâmicas é a facilidade em transformar idéias em código funcional, e com Clojure não é diferente. A idéia por trás do Licensator surgiu justamente em uma dessas sessões de codificação no <a href="http://clojure.org/repl_and_main">REPL</a>, o ambiente interativo da linguagem. Após alguns minutos brincando, vi que o problema era simples de resolver.</p>
<p>Apesar do elevado número de licenças, podemos facilmente extrair informações comuns a todas elas, como: se a licença é copyleft, se pode ser usada por código fechado (proprietário), entre outras coisas.</p>
<p>Por exemplo, vamos pegar a licença <a href="http://www.opensource.org/licenses/apache2.0.php">Apache v2.0</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>def *licenses*
     <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">:</span><span style="color: #555;">id</span> <span style="color: #66cc66;">:</span><span style="color: #555;">apl-v20</span>
       <span style="color: #66cc66;">:</span><span style="color: #555;">long-</span><span style="color: #b1b100;">name</span> <span style="color: #ff0000;">&quot;Apache License v2.0&quot;</span>
       <span style="color: #66cc66;">:</span><span style="color: #555;">short-</span><span style="color: #b1b100;">name</span> <span style="color: #ff0000;">&quot;Apache v2.0&quot;</span>
       <span style="color: #66cc66;">:</span><span style="color: #555;">url</span> <span style="color: #ff0000;">&quot;http://www.opensource.org/licenses/apache2.0.php&quot;</span>
       <span style="color: #66cc66;">:</span><span style="color: #555;">copyright</span> true
       <span style="color: #66cc66;">:</span><span style="color: #555;">patent</span> true
       <span style="color: #66cc66;">:</span><span style="color: #555;">closed-source-linking</span> true
       <span style="color: #66cc66;">:</span><span style="color: #555;">derivative-work</span> true
       <span style="color: #66cc66;">:</span><span style="color: #555;">affero</span> false
       <span style="color: #66cc66;">:</span><span style="color: #555;">copyleft</span> false
       <span style="color: #66cc66;">:</span><span style="color: #555;">charge-for-distribution</span> true
       <span style="color: #66cc66;">:</span><span style="color: #555;">charge-for-use</span> true
       <span style="color: #66cc66;">:</span><span style="color: #555;">compatible-with</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">:</span><span style="color: #555;">apl-v20</span> <span style="color: #66cc66;">:</span><span style="color: #555;">afl-v30</span> <span style="color: #66cc66;">:</span><span style="color: #555;">cddl-v10</span> <span style="color: #66cc66;">:</span><span style="color: #555;">epl-v10</span> <span style="color: #66cc66;">:</span><span style="color: #555;">freebsd</span>
                         <span style="color: #66cc66;">:</span><span style="color: #555;">new-bsd</span> <span style="color: #66cc66;">:</span><span style="color: #555;">mit</span> <span style="color: #66cc66;">:</span><span style="color: #555;">mpl-v11</span> <span style="color: #66cc66;">:</span><span style="color: #555;">public-domain</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>A lista completa de licenças pode ser vista <a href="http://github.com/danielfm/licensator/blob/master/src/licensator/licenses.clj">aqui</a>.</p>
<p>Considerando que todas as licenças têm esse mesmo conjunto de informações, como podemos saber quais licenças não são recíprocas e possuem cláusulas explícitas de copyright?</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>map <span style="color: #66cc66;">:</span><span style="color: #555;">id</span>
  <span style="color: #66cc66;">&#40;</span>filter #<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">and</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">copyright</span> <span style="color: #66cc66;">%</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">not</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">copyleft</span> <span style="color: #66cc66;">%</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> *licenses*<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">=&gt;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">afl-v30</span> <span style="color: #66cc66;">:</span><span style="color: #555;">apl-v20</span> <span style="color: #66cc66;">:</span><span style="color: #555;">epl-v10</span> <span style="color: #66cc66;">:</span><span style="color: #555;">freebsd</span> <span style="color: #66cc66;">:</span><span style="color: #555;">mit</span> <span style="color: #66cc66;">:</span><span style="color: #555;">new-bsd</span> <span style="color: #66cc66;">:</span><span style="color: #555;">bsd</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Se você conhece um pouco sobre programação funcional, este código deve ser fácil de acompanhar. De qualquer forma, o que ele faz é retornar o <code>:id</code> de todas as licenças onde <code>:copyright</code> é verdadeiro e <code>:copyleft</code> é falso.</p>
<p>Outro exemplo: quais licenças são compatíveis com Apache v2.0 e <a href="http://www.opensource.org/licenses/cddl1.php">CDDL v1.0</a>?</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>use 'clojure<span style="color: #66cc66;">.</span><span style="color: #b1b100;">set</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>map <span style="color: #66cc66;">:</span><span style="color: #555;">id</span>
  <span style="color: #66cc66;">&#40;</span>filter #<span style="color: #66cc66;">&#40;</span>subset? <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">set</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">:</span><span style="color: #555;">apl-v20</span> <span style="color: #66cc66;">:</span><span style="color: #555;">cddl-v10</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>
                    <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">set</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">compatible-with</span> <span style="color: #66cc66;">%</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> *licenses*<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">=&gt;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">apl-v20</span> <span style="color: #66cc66;">:</span><span style="color: #555;">cddl-v10</span> <span style="color: #66cc66;">:</span><span style="color: #555;">epl-v10</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Aqui usamos a namespace <a href="http://clojure.github.com/clojure/clojure.set-api.html">clojure.set</a>, que conta com algumas funções úteis para álgebra relacional. O código é muito parecido com o anterior; a mudança é que agora usamos a função <code>subset?</code> para buscar as licenças compatíveis com <code>[:apl-v20 :cddl-v10]</code>.</p>
<p>Último exemplo: quais licenças recíprocas são compatíveis com Apache v2.0?</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>map <span style="color: #66cc66;">:</span><span style="color: #555;">id</span>
  <span style="color: #66cc66;">&#40;</span>filter #<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">and</span> <span style="color: #66cc66;">&#40;</span>subset? <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">set</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">:</span><span style="color: #555;">apl-v20</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">set</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">compatible-with</span> <span style="color: #66cc66;">%</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
                <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">copyleft</span> <span style="color: #66cc66;">%</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> *licenses*<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">=&gt;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">cddl-v10</span> <span style="color: #66cc66;">:</span><span style="color: #555;">agpl-v30</span> <span style="color: #66cc66;">:</span><span style="color: #555;">gpl-v30</span> <span style="color: #66cc66;">:</span><span style="color: #555;">lgpl-v30</span> <span style="color: #66cc66;">:</span><span style="color: #555;">mpl-v11</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Neste ponto já se pode perceber que não existe mágica nenhuma por trás do algoritmo; o que ele faz é filtrar as licenças com base numa função.</p>
<h3>A solução</h3>
<p>O código que acabamos de ver funciona, mas não é apropriado para resolver o problema uma vez que a lógica de consulta se encontra fixa no código.</p>
<p>O ideal seria se os critérios de busca fossem expressados como um map&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>def cmap
     <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">:</span><span style="color: #555;">patent</span> true<span style="color: #66cc66;">,</span> <span style="color: #66cc66;">:</span><span style="color: #555;">closed-source-linking</span> true<span style="color: #66cc66;">,</span> <span style="color: #66cc66;">:</span><span style="color: #555;">compatible-with</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">:</span><span style="color: #555;">mit</span> <span style="color: #66cc66;">:</span><span style="color: #555;">new-bsd</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>&#8230;portanto precisamos de uma função que faça a filtragem das licenças com base nesse mapa, algo como:</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>defn find-matches <span style="color: #66cc66;">&#91;</span>cmap data<span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&#40;</span>filter <span style="color: #66cc66;">&#40;</span>where cmap<span style="color: #66cc66;">&#41;</span> data<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>No caso, essa função <code>where</code>, que ainda não definimos, deve retornar uma função que filtre os elementos (licenças) em <code>data</code> de acordo com o mapa de critérios <code>cmap</code>.</p>
<p>Vamos por partes. Quais condições em <code>cmap</code> são verdadeiras para a licença Apache v2.0?</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>defn criteria-matches? <span style="color: #66cc66;">&#91;</span>license <span style="color: #66cc66;">&#91;</span>kval cval<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>
  <span style="color: #ff0000;">&quot;Verifica se o critério 'centry' é verdadeiro para a licença 'license'.&quot;</span>
  <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#91;</span>lval <span style="color: #66cc66;">&#40;</span>kval license<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span>
    <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">nil</span>? cval<span style="color: #66cc66;">&#41;</span>
      true
      <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>coll? lval<span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#40;</span>subset? <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">set</span> cval<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">set</span> lval<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">=</span> cval lval<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>map <span style="color: #66cc66;">&#40;</span>partial criteria-matches? apl-v20<span style="color: #66cc66;">&#41;</span> cmap<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">=&gt;</span> <span style="color: #66cc66;">&#40;</span>true true true<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Uma licença só pode ser considerada compatível com os critérios se a lista retornada contém apenas valores verdadeiros. Portanto, neste caso, a licença Apache v2.0 é considerada compatível com os critérios informados:</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>every? true? <span style="color: #66cc66;">&#40;</span>map <span style="color: #66cc66;">&#40;</span>partial criteria-matches? apl-v20<span style="color: #66cc66;">&#41;</span> cmap<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">=&gt;</span> true</pre></div></div>

<p>Logo, uma possível implementação para a função <code>where</code> seria:</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>defn where
  <span style="color: #ff0000;">&quot;Retorna função que diz se todos os critérios em 'cmap' são verdadeiros para a licença 'lentry'.&quot;</span>
  <span style="color: #66cc66;">&#91;</span>cmap<span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&#40;</span>fn <span style="color: #66cc66;">&#91;</span>lentry<span style="color: #66cc66;">&#93;</span>
    <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#91;</span>res <span style="color: #66cc66;">&#40;</span>map <span style="color: #66cc66;">&#40;</span>fn <span style="color: #66cc66;">&#91;</span>centry<span style="color: #66cc66;">&#93;</span>
		     <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#91;</span>cval <span style="color: #66cc66;">&#40;</span>val centry<span style="color: #66cc66;">&#41;</span>
			   lval <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>key centry<span style="color: #66cc66;">&#41;</span> lentry<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span>
		       <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">nil</span>? cval<span style="color: #66cc66;">&#41;</span>
			 true
			 <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>coll? lval<span style="color: #66cc66;">&#41;</span>
			   <span style="color: #66cc66;">&#40;</span>subset? <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">set</span> cval<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">set</span> lval<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
			   <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">=</span> cval lval<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> cmap<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span>
      <span style="color: #66cc66;">&#40;</span>every? true? res<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Este código é uma junção dos dois anteriores. A função <code>where</code> recebe o mapa <code>cmap</code> com os critérios de pesquisa, e retorna uma segunda função. Esta função recebe uma licença <code>lentry</code> e verifica se todos os critérios informados são verdadeiros para esta licença.</p>
<p>Como <code>where</code> é usada em conjunto com <code>filter</code> na função <code>find-matches</code>, isso fará com que todas as licenças compatíveis sejam retornadas:</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>map <span style="color: #66cc66;">:</span><span style="color: #555;">id</span> <span style="color: #66cc66;">&#40;</span>find-matches cmap *licenses*<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">=&gt;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">afl-v30</span> <span style="color: #66cc66;">:</span><span style="color: #555;">apl-v20</span> <span style="color: #66cc66;">:</span><span style="color: #555;">cddl-v10</span> <span style="color: #66cc66;">:</span><span style="color: #555;">epl-v10</span> <span style="color: #66cc66;">:</span><span style="color: #555;">lgpl-v30</span> <span style="color: #66cc66;">:</span><span style="color: #555;">mpl-v11</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Uma das coisas legais de Clojure &#8212; e outras linguagens funcionais &#8212; é a quantidade ridícula de código necessário para resolver certos problemas. Este algoritmo, por exemplo, tem apenas 15 linhas (muito curtas) de código. Onde está seu Deus agora?! <img src='http://weblog.destaquenet.com/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> </p>
<p>O <a href="http://github.com/danielfm/licensator">código da aplicação</a> está no Github para quem tiver interesse em ver o restante do código.</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2010/10/05/entendendo-licencas-open-source-com-clojure/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Fecha-se um ciclo; outro se inicia&#8230;</title>
		<link>http://weblog.destaquenet.com/2010/09/27/fecha-se-um-ciclo-outro-se-inicia/</link>
		<comments>http://weblog.destaquenet.com/2010/09/27/fecha-se-um-ciclo-outro-se-inicia/#comments</comments>
		<pubDate>Mon, 27 Sep 2010 17:07:58 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Off Topic]]></category>
		<category><![CDATA[Português]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[oportunidade]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[trabalho]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=1138</guid>
		<description><![CDATA[Atualização (15/Nov): Gostaria de agradecer a todos que divulgaram este post e/ou me enviaram propostas, algumas delas muito boas. Aproveito também para comunicar que inicio meus trabalhos na Globo.com nas próximas semanas. Pois bem. Após quase três anos de serviços &#8230; <a href="http://weblog.destaquenet.com/2010/09/27/fecha-se-um-ciclo-outro-se-inicia/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>Atualização</strong> (15/Nov): Gostaria de agradecer a todos que divulgaram este post e/ou me enviaram propostas, algumas delas muito boas. Aproveito também para comunicar que inicio meus trabalhos na <a href="http://globo.com">Globo.com</a> nas próximas semanas.</p>
<p><a href="http://globo.com"><img src="http://weblog.destaquenet.com/wp-content/uploads/2010/09/globocom.png" alt="Globo.com" title="Globo.com" width="200" height="115" class="aligncenter size-full wp-image-1310" /></a></p>
<p>Pois bem. Após quase três anos de serviços prestados e <a href="http://www.destaquenet.com/portifolio/">vários projetos</a> desenvolvidos ao longo desse tempo, chegou a hora de me despedir de meu principal cliente, a <a href="http://gsp.com.br/">GSP</a>, uma das maiores loteadoras do Brasil. Um abraço aos amigos que ficaram, e aos que já não estão mais lá. Foi um prazer!</p>
<p>A principal tecnologia com que eu trabalhei nesse período foi <a href="http://java.com/">Java</a>, com uma pitada de <a href="http://python.org/">Python</a> aqui e ali. Mas, como irremediável curioso que sou, não pude deixar de brincar com <a href="http://pharo-project.org/">outras</a> <a href="http://clojure.org/">coisas</a> também.</p>
<p>Agora, no entanto, é hora de pensar no futuro. Se você precisa de um profissional <a href="http://www.destaquenet.com/empresa/#daniel">com o meu perfil</a>, ou conhece alguma empresa que precise, <a href="http://www.destaquenet.com/contato/">entre em contato comigo</a> ou passe o link deste post adiante. Busco trabalhar com empresas ou pessoas que:</p>
<ol>
<li>Tenham projetos não convencionais;</li>
<li>Tratem a tecnologia com a devida atenção;</li>
<li>Contem com equipes multi-disciplinares, com gente que ama o que faz e que busca melhorar a todo instante.</li>
</ol>
<p>Apesar de morar no interior de São Paulo, estou aberto a propostas de outras cidades, de preferência em tempo integral.</p>
<p>Valeu!</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2010/09/27/fecha-se-um-ciclo-outro-se-inicia/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Clojure Invade o Dev In Sampa</title>
		<link>http://weblog.destaquenet.com/2010/08/10/clojure-invade-o-dev-in-sampa/</link>
		<comments>http://weblog.destaquenet.com/2010/08/10/clojure-invade-o-dev-in-sampa/#comments</comments>
		<pubDate>Tue, 10 Aug 2010 11:30:34 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Off Topic]]></category>
		<category><![CDATA[Português]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[devinsampa]]></category>
		<category><![CDATA[encontro]]></category>
		<category><![CDATA[evento]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jvm]]></category>
		<category><![CDATA[palestra]]></category>
		<category><![CDATA[sao paulo]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=1062</guid>
		<description><![CDATA[No próximo sábado, dia 14/08, acontecerá em São Paulo o 2º Dev In Sampa, um encontro de desenvolvedores de software que não faz propaganda do governo nem apresenta palestras com foco em um único fornecedor. Já era hora! Infelizmente, por &#8230; <a href="http://weblog.destaquenet.com/2010/08/10/clojure-invade-o-dev-in-sampa/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>No próximo sábado, dia 14/08, acontecerá em São Paulo o 2º <a href="http://devinsampa.com.br/">Dev In Sampa</a>, um encontro de desenvolvedores de software que não <a href="http://fisl.softwarelivre.org/">faz propaganda do governo</a> nem apresenta palestras com <a href="http://www.oracle.com/us/javaonedevelop/index.html">foco em um único fornecedor</a>. Já era hora!</p>
<p>Infelizmente, por <a href="http://weblog.destaquenet.com/2009/10/05/use-web-scraping-para-acompanhar-seus-pedidos-na-ticketmaster/">razões de força maior</a> eu não pude comparecer na primeira edição do evento, mas este ano eu estarei presente, e ainda por cima <a href="http://devinsampa.com.br/palestras#presentation-3">como palestrante</a>.</p>
<p>Por isso, antes de mais nada, eu gostaria de agradecer àqueles que votaram na minha palestra. Isso mostra que <a href="http://clojure.org/">Clojure</a> anda despertando o interesse da rapazeada também no Brasil, o que é muito bom.</p>
<p><strong>Update:</strong> Apresentação e códigos-fonte <a href="http://github.com/danielfm/clojure-devinsampa">disponíveis para download</a>.</p>
<p><span id="more-1062"></span></p>
<h3>Sobre a palestra</h3>
<p>Apresentar uma linguagem de programação numa palestra de 50 minutos é sempre uma tarefa complicada, especialmente se essa linguagem de programação traz consigo uma <a href="http://clojure.org/rationale">bagagem</a> que vai muito além da sintaxe.</p>
<p>Quando eu assisto uma palestra sobre linguagens de programação, existem duas coisas que me irritam. A primeira é quando o palestrante soca um monte de código e se limita à sintaxe, explicando tudo vírgula por vírgula, sem nenhum contexto. A outra é quando o palestrante fala sobre uma linguagem mas não mostra nenhum exemplo.</p>
<p>Para não repetir esses erros, eu optei por um estilo diferente, onde a linguagem é abordada e explorada aos poucos, mas sempre seguindo uma linha para que haja um começo, um meio e um fim.</p>
<p>Meu objetivo não será ensinar ninguém a programar em Clojure, e sim mostrar alguns dos recursos que eu considero importantes. Assim, quem se interessar pode pesquisar mais por conta própria. Afinal, não somos todos auto-didatas?</p>
<p>Quem tiver dúvidas ao final da palestra, ou quiser apenas jogar conversa fora, é só me chamar pelo <a href="http://twitter.com/danielfmt">Twitter</a>. Também não irei reclamar se alguém quiser pagar meu almoço. <img src='http://weblog.destaquenet.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>O &#8220;pós-evento&#8221;</h3>
<p>Ao final, a apresentação será disponibilizada para download no <a href="http://github.com/danielfm">GitHub</a>, juntamente com os <em>muitos</em> exemplos de código. Os slides virão acompanhados de notas que poderão ser lidas como uma espécie de artigo.</p>
<p>Deixarei os comentários deste post habilitados para quem quiser deixar dúvidas ou mensagens sobre a palestra.</p>
<p>É isso aí. Nos encontramos lá!</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2010/08/10/clojure-invade-o-dev-in-sampa/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Crie seu próprio pendrive USB multi-boot salvador da pátria</title>
		<link>http://weblog.destaquenet.com/2010/08/02/crie-seu-proprio-pendrive-usb-multi-boot-salvador-da-patria/</link>
		<comments>http://weblog.destaquenet.com/2010/08/02/crie-seu-proprio-pendrive-usb-multi-boot-salvador-da-patria/#comments</comments>
		<pubDate>Mon, 02 Aug 2010 11:20:50 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Português]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[boot]]></category>
		<category><![CDATA[clonezilla]]></category>
		<category><![CDATA[drive]]></category>
		<category><![CDATA[ferramentas]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[gparted]]></category>
		<category><![CDATA[grub]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[memtest]]></category>
		<category><![CDATA[mint]]></category>
		<category><![CDATA[multi-boot]]></category>
		<category><![CDATA[pendrive]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[usb]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=1060</guid>
		<description><![CDATA[Não preciso convencê-lo de que carregar algumas distribuições Linux com você pode fazer a diferença entre a vida e a morte. Bem, é claro que eu estou sendo um pouco dramático, mas é realmente muito bom poder rodar um teste &#8230; <a href="http://weblog.destaquenet.com/2010/08/02/crie-seu-proprio-pendrive-usb-multi-boot-salvador-da-patria/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Não preciso convencê-lo de que carregar algumas distribuições Linux com você pode fazer a diferença entre a vida e a morte. Bem, é claro que eu estou sendo um pouco dramático, mas é realmente muito bom poder rodar um teste de memória numa máquina que insiste em jogar erros estranhos na sua cara, ou mesmo copiar discos ou partições importantes quando você está por aí.</p>
<p>Para mim, algumas ferramentas e distribuições são particularmente úteis:</p>
<ul>
<li><a href="http://clonezilla.org/">Clonezilla</a>. Ferramenta muito boa para clonagem de disco/partição. Leva algum tempo para iniciantes se acostumarem com ela, mas vale o esforço. Já fui salvo por esta ferramenta mais de uma vez.</li>
<li><a href="http://gparted.sourceforge.net/">GParted</a>. Excelente ferramenta para particionamento de disco.</li>
<li><a href="http://linuxmint.com/">Linux Mint</a>. Distribuição Linux baseada no Ubuntu muito fácil de usar. Eu gosto muito da edição Live-DVD, que inclui softwares como <a href="http://www.videolan.org/vlc/">VLC</a>, <a href="http://www.openoffice.org/">OpenOffice</a> e <a href="http://java.com/">Java</a>.</li>
<li><a href="http://ubuntu.com/">Ubuntu</a>. Uma das distribuições Linux mais populares hoje em dia.</li>
<li><a href="http://www.memtest.org/">Memtest86+</a>. Ferramenta para teste de memória incluída na maioria das distribuições Linux modernas. Indispensável.</li>
</ul>
<p>Agora, em vez de queimar um CD/DVD com cada uma dessas ferramentas, nós iremos usar um pendrive USB multi-boot.</p>
<p><span id="more-1060"></span></p>
<h3>Preparando a pendrive</h3>
<p>O primeiro passo é instalar um bootloader na pendrive para possamos escolher qual distribuição carregar quando bootando a partir dela. Sorte minha que a distribuição Linux que uso, Ubuntu, já vem com o Grub2 pré-instalado. Esta versão do <a href="http://www.gnu.org/software/grub/">Grub</a> em particular é necessária, já que ela nos permite montar e bootar imagens .ISO.</p>
<p>Uma vez que você esteja com o Grub2 instalado, plugue sua pendrive e se certifique de que sua partição principal seja bootável, e que ela esteja formatada com FAT32 (<code>vfat</code>).</p>
<p>Então, rode este comando para instalar o Grub2 no pendrive:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> grub-install <span style="color: #660033;">--no-floppy</span> <span style="color: #660033;">--root-directory</span>=<span style="color: #000000; font-weight: bold;">/</span>media<span style="color: #000000; font-weight: bold;">/</span>PENDRIVE <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdX</pre></div></div>

<p>Lembre de fazer com que <code>root-directory</code> aponte para o caminho onde o pendrive está montado, e <code>/dev/sdX</code> para o dispositivo em si. Por favor, verifique os parâmetros duas vezes antes de rodar o comando, ou você corre o risco de fazer algo de que se arrependerá depois!</p>
<h3>Configurando o Grub2</h3>
<p>Agora é hora de baixar as imagens .ISO das distribuições mencionadas anteriormente e colocá-las no diretório <code>/boot/iso</code> dentro da pendrive. Então, crie o arquivo <code>/boot/grub/grub.cfg</code> com o seguinte conteúdo:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">menuentry <span style="color: #ff0000;">&quot;Linux Mint 9 x86&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">set</span> <span style="color: #007800;">isofile</span>=<span style="color: #ff0000;">&quot;/boot/iso/linuxmint-9-gnome-dvd-i386.iso&quot;</span>
  loopback loop <span style="color: #007800;">$isofile</span>
  linux <span style="color: #7a0874; font-weight: bold;">&#40;</span>loop<span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #000000; font-weight: bold;">/</span>casper<span style="color: #000000; font-weight: bold;">/</span>vmlinuz <span style="color: #007800;">boot</span>=casper iso-scan<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">filename</span>=<span style="color: #007800;">$isofile</span> noeject noprompt <span style="color: #660033;">--</span>
  initrd <span style="color: #7a0874; font-weight: bold;">&#40;</span>loop<span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #000000; font-weight: bold;">/</span>casper<span style="color: #000000; font-weight: bold;">/</span>initrd.lz
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
menuentry <span style="color: #ff0000;">&quot;Ubuntu 10.04 Desktop x86&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">set</span> <span style="color: #007800;">isofile</span>=<span style="color: #ff0000;">&quot;/boot/iso/ubuntu-10.04-desktop-i386.iso&quot;</span>
  loopback loop <span style="color: #007800;">$isofile</span>
  linux <span style="color: #7a0874; font-weight: bold;">&#40;</span>loop<span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #000000; font-weight: bold;">/</span>casper<span style="color: #000000; font-weight: bold;">/</span>vmlinuz <span style="color: #007800;">boot</span>=casper iso-scan<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">filename</span>=<span style="color: #007800;">$isofile</span> noeject noprompt <span style="color: #660033;">--</span>
  initrd <span style="color: #7a0874; font-weight: bold;">&#40;</span>loop<span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #000000; font-weight: bold;">/</span>casper<span style="color: #000000; font-weight: bold;">/</span>initrd.lz
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
menuentry <span style="color: #ff0000;">&quot;Clonezilla Live 1.2.5-17 x86&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">set</span> <span style="color: #007800;">isofile</span>=<span style="color: #ff0000;">&quot;/boot/iso/clonezilla-live-1.2.5-17-i686.iso&quot;</span>
  loopback loop <span style="color: #007800;">$isofile</span> 
  linux <span style="color: #7a0874; font-weight: bold;">&#40;</span>loop<span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #000000; font-weight: bold;">/</span>live<span style="color: #000000; font-weight: bold;">/</span>vmlinuz <span style="color: #007800;">boot</span>=live <span style="color: #007800;">union</span>=aufs nolocales noprompt <span style="color: #007800;">ip</span>=frommedia <span style="color: #007800;">toram</span>=filesystem.squashfs <span style="color: #007800;">findiso</span>=<span style="color: #007800;">$isofile</span> 
  initrd <span style="color: #7a0874; font-weight: bold;">&#40;</span>loop<span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #000000; font-weight: bold;">/</span>live<span style="color: #000000; font-weight: bold;">/</span>initrd.img
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
menuentry <span style="color: #ff0000;">&quot;GParted Live 0.5.2-9 x86&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">set</span> <span style="color: #007800;">isofile</span>=<span style="color: #ff0000;">&quot;/boot/iso/gparted-live-0.5.2-9.iso&quot;</span>
  loopback loop <span style="color: #007800;">$isofile</span> 
  linux <span style="color: #7a0874; font-weight: bold;">&#40;</span>loop<span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #000000; font-weight: bold;">/</span>live<span style="color: #000000; font-weight: bold;">/</span>vmlinuz <span style="color: #007800;">boot</span>=live <span style="color: #007800;">union</span>=aufs nolocales noprompt <span style="color: #007800;">ip</span>=frommedia <span style="color: #007800;">toram</span>=filesystem.squashfs <span style="color: #007800;">findiso</span>=<span style="color: #007800;">$isofile</span> 
  initrd <span style="color: #7a0874; font-weight: bold;">&#40;</span>loop<span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #000000; font-weight: bold;">/</span>live<span style="color: #000000; font-weight: bold;">/</span>initrd.img
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
menuentry <span style="color: #ff0000;">&quot;Memory test (memtest86+)&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
  linux16 <span style="color: #000000; font-weight: bold;">/</span>boot<span style="color: #000000; font-weight: bold;">/</span>iso<span style="color: #000000; font-weight: bold;">/</span>memtest86+.bin
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

<p>Não se esqueça de alterar o valor as variáveis <code>isofile</code>, se necessário.</p>
<h3>Ressalva</h3>
<p>Esse negócio todo é novo, e existem apenas algumas  distribuições que podem ser bootadas dessa forma. Caso queira testar outras distribuições, você provavelmente terá que descobrir quais opções de Kernel usar em cada uma delas.</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2010/08/02/crie-seu-proprio-pendrive-usb-multi-boot-salvador-da-patria/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Django Para Dispositivos Móveis</title>
		<link>http://weblog.destaquenet.com/2010/07/12/django-para-dispositivos-moveis/</link>
		<comments>http://weblog.destaquenet.com/2010/07/12/django-para-dispositivos-moveis/#comments</comments>
		<pubDate>Mon, 12 Jul 2010 11:10:21 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Português]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[configuração]]></category>
		<category><![CDATA[deploy]]></category>
		<category><![CDATA[dispositivo]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[móvel]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[wsgi]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=944</guid>
		<description><![CDATA[Estamos vivendo o que alguns chamam de &#8220;explosão mobile&#8221;, um tempo onde um número cada vez maior de dispositivos móveis &#8212; como tablets e smartphones &#8212; se tornam parte significante da Web. Esta é a razão pela qual ter seu &#8230; <a href="http://weblog.destaquenet.com/2010/07/12/django-para-dispositivos-moveis/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Estamos vivendo o que alguns chamam de &#8220;explosão mobile&#8221;, um tempo onde um número cada vez maior de dispositivos móveis &#8212; como tablets e smartphones &#8212; se tornam parte significante da Web. Esta é a razão pela qual ter seu website preparado para tais dispositivos é cada vez mais importante.</p>
<p>Felizmente, <a href="http://djangoproject.com/">Django</a> é um dos poucos frameworks web que tornam este um problema simples de solucionar.</p>
<p><span id="more-944"></span></p>
<h3>Como resolvemos este problema</h3>
<p>Um jeito simples é criar um módulo <code>settings.py</code> separado para a versão &#8220;mobile&#8221;. Isso nos permite rodar dois sites diferentes reusando a mesma base de código. Além disso, cada versão pode ter seu próprio diretório de templates, configurações de URL, etc.</p>
<p>Vamos fazer isso. No diretório-raíz do projeto, crie um arquivo <code>m_settings.py</code> com o seguinte conteúdo:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Arquivo: myproject/m_settings.py</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;Configurações para a versão &quot;mobile&quot; do website.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Carrega as configurações padrão</span>
<span style="color: #ff7700;font-weight:bold;">from</span> settings <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Domínio &quot;m.mydomain.com&quot;</span>
SITE_ID = <span style="color: #ff4500;">2</span>
PREPEND_WWW = <span style="color: #008000;">False</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Usado em outras partes do código para determinar qual versão está rodando</span>
DEFAULT_VERSION = <span style="color: #008000;">False</span>
MOBILE_VERSION  = <span style="color: #008000;">True</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># URLs para a versão mobile</span>
ROOT_URLCONF  = <span style="color: #483d8b;">'myproject.m_urls'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Templates para a versão mobile</span>
TEMPLATE_DIRS = <span style="color: black;">&#40;</span>
    <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">normpath</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span> + <span style="color: #483d8b;">'/template/mobile'</span><span style="color: black;">&#41;</span>,
<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Outras configurações...</span></pre></div></div>

<p>O fato de os dois sites compartilharem a mesma base de código não significa que eles devem ter as mesmas configurações de URL. Aliás, o normal é que versões próprias para dispositivos móveis sejam mais simples, com uma quantidade reduzida de mapeamentos de URLs.</p>
<p>Para definir as configurações de URL da versão mobile, crie um arquivo <code>m_urls.py</code> com o seguinte conteúdo:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Arquivo: myproject/m_urls.py</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;Mapeamentos de URL para a versão &quot;mobile&quot;.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span>.<span style="color: black;">urls</span>.<span style="color: black;">defaults</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #808080; font-style: italic;"># from django.contrib import admin</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># admin.autodiscover()</span>
&nbsp;
handler404 = <span style="color: #483d8b;">'website.views.error_404_handler'</span>
handler500 = <span style="color: #483d8b;">'website.views.error_500_handler'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># URLs</span>
urlpatterns = patterns<span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>,
    <span style="color: #808080; font-style: italic;"># I18N</span>
    <span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^i18n/'</span>, include<span style="color: black;">&#40;</span><span style="color: #483d8b;">'django.conf.urls.i18n'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Apps internas</span>
    <span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^contact/'</span>, include<span style="color: black;">&#40;</span><span style="color: #483d8b;">'contact.urls'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># (r'^admin/doc/', include('django.contrib.admindocs.urls')),</span>
    <span style="color: #808080; font-style: italic;"># (r'^admin/', include(admin.site.urls)),</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Outras configurações...</span>
<span style="color: black;">&#41;</span></pre></div></div>

<p>Perceba que, neste exemplo em particular, a <a href="http://docs.djangoproject.com/en/dev/ref/contrib/admin/">app Admin</a> não é acessível através da versão mobile. Isso apenas serve para mostrar que temos total liberdade para estruturar ambas as versões de diferentes formas, sem muitas dificuldades.</p>
<h3>Desenvolvendo</h3>
<p>Você certamente já sabe como rodar o servidor de desenvolvimento para a versão padrão. O que a maioria dos desenvolvedores desconhece, entretanto, é que é possível escolher qual a porta e/ou módulo <code>settings.py</code> deve ser usado pelo script, o que nos permite rodar um servidor para cada versão do nosso site:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># Terminal 1: versão padrão</span>
$ python manage.py runserver <span style="color: #000000;">8000</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Terminal 2: versão mobile</span>
$ python manage.py runserver <span style="color: #660033;">--settings</span>=m_settings <span style="color: #000000;">8001</span></pre></div></div>

<p>Pronto, agora é só continuar com o desenvolvimento da forma que você já está acostumado.</p>
<h3>Testando</h3>
<p>Você provavelmente notou que temos duas configurações que podem ser usadas para determinar qual versão do site está rodando, <code>DEFAULT_VERSION</code> e <code>MOBILE_VERSION</code>. </p>
<p>Por isso, é só uma questão de checar tais configurações quando for necessário fazer coisas diferentes em cada uma das versões do site. Isso é particularmente útil quando você tem uma app usada em ambas as versões e quer criar testes para cada uma das versões:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Arquivo: myproject/myapp/tests/__init__.py</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;Testes para MyApp.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>settings, <span style="color: #483d8b;">'DEFAULT_VERSION'</span>, <span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Testa a versão padrão</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> default_models_tests <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> default_navigation_tests <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>settings, <span style="color: #483d8b;">'MOBILE_VERSION'</span>, <span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Testa a versão mobile</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> mobile_models_tests <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> mobile_navigation_tests <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span></pre></div></div>

<p>Você pode rodar os testes para cada versão de uma forma semelhante a que fizemos com o comando <code>runserver</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># Versão padrão</span>
$ python manage.py <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>appname...<span style="color: #7a0874; font-weight: bold;">&#93;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Versão mobile</span>
$ python manage.py <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #660033;">--settings</span>=m_settings <span style="color: #7a0874; font-weight: bold;">&#91;</span>appname...<span style="color: #7a0874; font-weight: bold;">&#93;</span></pre></div></div>

<h3>Colocando em produção</h3>
<p>Apesar do que você possa achar, esta é a parte fácil.</p>
<p>Uma vez que a forma recomendada de <a href="http://docs.djangoproject.com/en/dev/howto/deployment/modwsgi/">colocar Django em produção</a> é com <a href="http://apache.org">Apache</a> e <a href="http://code.google.com/p/modwsgi/">mod_wsgi</a>, é possível que você já tenha um arquivo WSGI parecido com o seguinte:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">sys</span>
&nbsp;
APPS_PATH   = <span style="color: #483d8b;">'/home/user/wsgi_apps'</span>
MYPROJECT_PATH = <span style="color: #483d8b;">'%s/myproject'</span> <span style="color: #66cc66;">%</span> APPS_PATH
&nbsp;
<span style="color: #808080; font-style: italic;"># Eggs de terceiros</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">site</span>
<span style="color: #dc143c;">site</span>.<span style="color: black;">addsitedir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/home/user/.python/lib'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span> += <span style="color: black;">&#91;</span>APPS_PATH, MYPROJECT_PATH<span style="color: black;">&#93;</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'DJANGO_SETTINGS_MODULE'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'myproject.settings'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>
application = django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>.<span style="color: black;">WSGIHandler</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Tudo que precisamos fazer é configurar um outro sub-domínio WSGI no nosso servidor (ex: m.mywebsite.com) que referencia o seguinte arquivo de configurações WSGI:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">sys</span>
&nbsp;
APPS_PATH   = <span style="color: #483d8b;">'/home/user/wsgi_apps'</span>
MYPROJECT_PATH = <span style="color: #483d8b;">'%s/myproject'</span> <span style="color: #66cc66;">%</span> APPS_PATH
&nbsp;
<span style="color: #808080; font-style: italic;"># Eggs de terceiros</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">site</span>
<span style="color: #dc143c;">site</span>.<span style="color: black;">addsitedir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/home/user/.python/lib'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span> += <span style="color: black;">&#91;</span>APPS_PATH, MYPROJECT_PATH<span style="color: black;">&#93;</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'DJANGO_SETTINGS_MODULE'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'myproject.m_settings'</span> <span style="color: #808080; font-style: italic;"># Esta linha</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>
application = django.<span style="color: black;">core</span>.<span style="color: black;">handlers</span>.<span style="color: black;">wsgi</span>.<span style="color: black;">WSGIHandler</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>A única diferença entre esses dois arquivos WSGI é que cada um aponta para um módulo <code>settings.py</code> diferente. E não, você não precisa ter uma cópia do site para cada versão, afinal estamos usando a mesma base de código para ambas as versões, lembra? <img src='http://weblog.destaquenet.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<h3>Minimizando o tráfego</h3>
<p>Por incrível que pareça, nem todo mundo dispõe de conexões ultra-rápidas. Por isso, é muito importante que você mantenha seus sites tão leves quanto possível.</p>
<p>Existem vários projetos open source que podem ajudar nessa parte. Um deles é o <a href="http://code.google.com/p/django-compress/">django-compress</a>, uma app Django que fornece um sistema automatizado para compressão de arquivos CSS e JavaScript.</p>
<p>Aliás, não importa se seus websites são para dispositivos móveis ou não; você deve <em>sempre</em> tentar minimizar o tráfego.</p>
<h3>O que falta?</h3>
<p>Ainda temos um pequeno problema: quando alguém visita a versão padrão do site através de um dispositivo móvel, ou vice-versa, eles não são redirecionados para a versão apropriada. Mas isso é assunto para um próximo artigo!</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2010/07/12/django-para-dispositivos-moveis/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Servidor De Email Local No Ubuntu Com Exim</title>
		<link>http://weblog.destaquenet.com/2010/06/25/servidor-de-email-local-no-ubuntu-com-exim/</link>
		<comments>http://weblog.destaquenet.com/2010/06/25/servidor-de-email-local-no-ubuntu-com-exim/#comments</comments>
		<pubDate>Fri, 25 Jun 2010 11:10:07 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Português]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[ambiente]]></category>
		<category><![CDATA[configuração]]></category>
		<category><![CDATA[desenvolvimento]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[exim]]></category>
		<category><![CDATA[gmail]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[sendmail]]></category>
		<category><![CDATA[servidor]]></category>
		<category><![CDATA[smtp]]></category>
		<category><![CDATA[telnet]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=981</guid>
		<description><![CDATA[Vimos em um post anterior como criar testes para código Java que envia e-mails. Agora o assunto é outro. Exim é um MTA open source que pode ser usado como alternativa ao Sendmail em sistemas operacionais Unix. Eu não tenho &#8230; <a href="http://weblog.destaquenet.com/2010/06/25/servidor-de-email-local-no-ubuntu-com-exim/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Vimos em um post anterior como criar testes para <a href="http://weblog.destaquenet.com/2008/09/20/2-boas-formas-de-testar-clientes-javamail/">código Java que envia e-mails</a>. Agora o assunto é outro.</p>
<p><a href="http://www.exim.org/">Exim</a> é um <acronym title="Mail Transfer Agent">MTA</acronym> open source que pode ser usado como alternativa ao <a href="http://www.sendmail.org/">Sendmail</a> em sistemas operacionais Unix. Eu não tenho idéia de qual é a melhor alternativa disponível, mas se você procura por um servidor de relay para instalar na sua configuração de desenvolvimento, Exim é provavelmente a opção mais simples para começar.</p>
<p>Neste artigo, veremos como configurar o Exim para enviar mensagens através do <a href="http://gmail.com/">Gmail</a>.</p>
<p><span id="more-981"></span></p>
<h3>Instalando o Exim</h3>
<p>Primeiro precisamos instalar o Exim e suas dependências, o que é algo bastante trivial em distribuições Linux modernas como <a href="http://www.ubuntu.com/">Ubuntu</a>/<a href="http://www.debian.org/">Debian</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> exim4</pre></div></div>

<h3>Usando Exim como servidor de relay</h3>
<p>Existe um assistente que nos ajuda a fazer as configurações básicas; rode o comando abaixo para abrí-lo e preencha cada tela como segue:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> dpkg-reconfigure exim4-config</pre></div></div>

<ol>
<li><strong>General type of mail configuration:</strong> mail sent by smarthost; received via SMTP or fetchmail</li>
<li><strong>System mail name:</strong> seudominio.com</li>
<li><strong>IP-addresses to listen on for incoming connections:</strong> 127.0.0.1 ; ::1</li>
<li><strong>Other destinations for which mail is accepted:</strong> Deixe em branco</li>
<li><strong>Machines to relay mail for:</strong> Deixe em branco</li>
<li><strong>Host name for the outgoing smarthost:</strong> smtp.gmail.com:587</li>
<li><strong>Hide local mail name in outgoing mail:</strong> Yes</strong></li>
<li><strong>Visible domain name for local users:</strong> seudominio.com</li>
<li><strong>Keep number of DNS-queries minimal:</strong> No</li>
<li><strong>Delivery method for local mail:</strong> mbox format in /var/mail/</li>
<li><strong>Split configuration into small files:</strong> Yes</li>
<li><strong>Root and postmaster mail recipient:</strong> Deixe em branco</li>
</ol>
<p>Agora precisamos configurar as credenciais do usuário no arquivo <code>/etc/exim4/passwd.client</code> adicionando a seguinte linha:</p>
<pre>
# Troque [username] e [password] pelos dados corretos
*.google.com:[username]:[password]
</pre>
<p>Agora basta rodar o comando abaixo para terminar as configurações:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> update-exim4.conf</pre></div></div>

<h3>Testando o servidor</h3>
<p>Um jeito simples &#8212; e nerd &#8212; de testar se as configurações estão corretas é usar o comando <code>telnet</code>:</p>
<pre>
$ telnet localhost 25
    Trying ::1...
    Connected to localhost.
    Escape character is '^]'.
    220 localhost ESMTP Exim 4.71 Wed, 23 Jun 2010 22:28:56 -0300
HELO localhost
    250 localhost Hello localhost [::1]
MAIL FROM: usuario@seudominio.com
    250 OK
RCPT TO: destino@email.com
    250 Accepted
DATA
    354 Enter message, ending with "." on a line by itself
SUBJECT: Assunto da mensagem
Testando Exim via Telnet. Massa!
.
    250 OK id=1ORbG5-0005uh-EF
QUIT
    221 localhost closing connection
    Connection closed by foreign host.
</pre>
<p>Abra os arquivos de log em <code>/var/log/exim4</code> para ver se a mensagem foi transmitida sem erros. Uma tentativa bem sucedida se parece com o seguinte:</p>
<pre>
2010-06-23 22:29:47 1ORbG5-0005uh-EF <= local@seudominio.com H=localhost [::1] P=smtp S=345
2010-06-23 22:29:50 1ORbG5-0005uh-EF => destino@email.com R=smarthost T=remote_smtp_smarthost H=gmail-smtp-msa.l.google.com [74.125.45.109] ..."
2010-06-23 22:29:50 1ORbG5-0005uh-EF Completed
</pre>
<p>Caso você não receba a mensagem e os logs não acusem nenhum erro, verifique se a mensagem não foi parar na caixa de spam antes que você mude quaisquer configurações.</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2010/06/25/servidor-de-email-local-no-ubuntu-com-exim/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Em Tempos de Copa do Mundo&#8230;</title>
		<link>http://weblog.destaquenet.com/2010/06/15/em-tempos-de-copa-do-mundo/</link>
		<comments>http://weblog.destaquenet.com/2010/06/15/em-tempos-de-copa-do-mundo/#comments</comments>
		<pubDate>Tue, 15 Jun 2010 11:00:16 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Português]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[aposta]]></category>
		<category><![CDATA[bolão]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[copa do mundo]]></category>
		<category><![CDATA[futebol]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[meme]]></category>
		<category><![CDATA[programa]]></category>
		<category><![CDATA[solução]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=898</guid>
		<description><![CDATA[Há quem ache &#8212; e eu concordo &#8212; que a UEFA Champions League é um torneio mais relevante do que a Copa do Mundo, mas não podemos negar que o Mundial mexe com a nossa rotina. Mesmo quem não é &#8230; <a href="http://weblog.destaquenet.com/2010/06/15/em-tempos-de-copa-do-mundo/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Há quem ache &#8212; e eu concordo &#8212; que a <a href="http://www.uefa.com/uefachampionsleague/index.html">UEFA Champions League</a> é um torneio mais relevante do que a <a href="http://www.fifa.com/worldcup/index.html">Copa do Mundo</a>, mas não podemos negar que o Mundial mexe com a nossa rotina. Mesmo quem não é apaixonado pelo esporte passa a prestar atenção nas seleções, nas partidas, na festa.</p>
<p>E com a Copa do Mundo vem os bolões. Muitos bolões.</p>
<p>Todo mundo já sabe como funciona um bolão, embora a mecânica possa mudar de um lugar para outro:</p>
<ol>
<li>Cada palpite tem um valor fixo (ex: R$2,00).</li>
<li>Cada um pode dar quantos palpites quiser.</li>
<li>No final, o montante arrecadado é dividido igualmente entre os vencedores. Se não houverem vencedores: (a) o bolão &#8220;acumula&#8221;<sup class='footnote'><a href='#fn-898-1' id='fnref-898-1'>1</a></sup>, ou (b) todo mundo recebe seu dinheiro de volta, ou (c) sua-regra-maluca-aqui.</li>
</ol>
<p>Esse tipo de bolão é interessante, mas ele podia ser melhor em alguns aspectos.</p>
<p>Primeiro, o organizador acaba perdendo muito tempo correndo atrás de troco, afinal não é todo mundo que anda com dinheiro trocado na carteira. Além disso, valor fixo de palpite é muito chato, pois o valor arrecadado é dividido por igual entre os ganhadores. O bolão fica muito mais interessante quando o valor do palpite é variável e o valor arrecadado é dividido proporcionalmente entre os ganhadores. Assim, no caso de vários ganhadores, ganha mais quem apostar mais.</p>
<p>O problema de se fazer bolões com palpite variável é ter que ficar calculando o valor proporcional a ser dado a cada ganhador. Portanto eis o desafio: criar um programa que receba uma lista com todos os palpites e retorne uma lista com os palpites vencedores juntamente com o valor proporcional a ser pago a cada ganhador.</p>
<p>E aí, topa?</p>
<p><span id="more-898"></span></p>
<h3>Resolvendo o problema&#8230; em Clojure</h3>
<p>Como escrever mais código do que necessário está saindo de moda, optei por codificar uma possível solução em <a href="http://clojure.org">Clojure</a>. Por ser uma <a href="http://weblog.destaquenet.com/2009/06/16/programacao-funcional-vale-a-pena-aprender/">linguagem funcional</a>, Clojure é excelente para esse tipo de tarefa. Basta iniciar o <a href="http://clojure.org/repl_and_main">REPL</a> e mãos à obra!</p>
<p>Primeiramente, devemos definir como um palpite deve ser representado:</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>defstruct bet <span style="color: #66cc66;">:</span><span style="color: #b1b100;">name</span> <span style="color: #66cc66;">:</span><span style="color: #555;">amount</span> <span style="color: #66cc66;">:</span><span style="color: #555;">guess</span> <span style="color: #66cc66;">:</span><span style="color: #555;">rate</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Todos os palpites possuem o mesmo conjunto de informações, por isso definimos um <a href="http://clojure.org/data_structures#Data%20Structures-StructMaps">StructMap</a> com as chaves <code>:name</code>, <code>:amount</code>, <code>:guess</code> e <code>:rate</code>.</p>
<p>Abaixo, uma possível lista de palpites:</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>def pool
     <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#40;</span>struct bet <span style="color: #ff0000;">&quot;Daniel&quot;</span>  <span style="color: #cc66cc;">2.0</span> <span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">2</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #808080; font-style: italic;">;; Daniel aposta R$2,00 no placar 2x0</span>
      <span style="color: #66cc66;">&#40;</span>struct bet <span style="color: #ff0000;">&quot;Antônio&quot;</span> <span style="color: #cc66cc;">4.0</span> <span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #808080; font-style: italic;">;; Antônio aposta R$4,00 no placar 0x0</span>
      <span style="color: #66cc66;">&#40;</span>struct bet <span style="color: #ff0000;">&quot;Marcela&quot;</span> <span style="color: #cc66cc;">1.0</span> <span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">2</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #808080; font-style: italic;">;; Marcela aposta R$1,00 no placar 2x0</span>
     <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Certo, já sabemos como os palpites são representados. Agora, como saber o montante total de uma lista de palpites (a.k.a. bolão)? Simples, basta calcular o somatório dos valores de todos os palpites:</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>defn pool-amount <span style="color: #66cc66;">&#91;</span>poolseq<span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&#40;</span>reduce<span style="color: #66cc66;"> + </span><span style="color: #66cc66;">&#40;</span>map <span style="color: #66cc66;">:</span><span style="color: #555;">amount</span> poolseq<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">;; testando</span>
<span style="color: #66cc66;">&#40;</span>pool-amount pool<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">=&gt;</span> <span style="color: #cc66cc;">7.0</span></pre></div></div>

<p>Beleza, mas quanto cada palpite representa em relação ao total arrecadado? Afinal, precisamos calcular o valor proporcional a ser pago a cada ganhador.</p>
<p>Sem problemas, basta dividir o valor de cada palpite pelo montante total:</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>defn pool-rates <span style="color: #66cc66;">&#91;</span>poolseq<span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#91;</span>sum <span style="color: #66cc66;">&#40;</span>pool-amount poolseq<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span>
    <span style="color: #66cc66;">&#40;</span>map #<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">assoc</span> <span style="color: #66cc66;">%</span> <span style="color: #66cc66;">:</span><span style="color: #555;">rate</span> <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">amount</span> <span style="color: #66cc66;">%</span><span style="color: #66cc66;">&#41;</span> sum<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> poolseq<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">;; testando</span>
<span style="color: #66cc66;">&#40;</span>map <span style="color: #66cc66;">:</span><span style="color: #555;">rate</span> <span style="color: #66cc66;">&#40;</span>pool-rates pool<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">=&gt;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0.285</span> <span style="color: #66cc66;">...,</span> <span style="color: #cc66cc;">0.571</span> <span style="color: #66cc66;">...,</span> <span style="color: #cc66cc;">0.142</span> <span style="color: #66cc66;">...</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>reduce<span style="color: #66cc66;"> + </span><span style="color: #66cc66;">&#40;</span>map <span style="color: #66cc66;">:</span><span style="color: #555;">rate</span> <span style="color: #66cc66;">&#40;</span>pool-rates pool<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">=&gt;</span> <span style="color: #cc66cc;">1.0</span></pre></div></div>

<p>Repare que, se todos os participantes ganhassem um bolão, o valor recebido pelo Antônio seria o dobro do valor recebido pelo Daniel, que seria o dobro do valor recebido pela Marcela. Justiça, finalmente!</p>
<p>Pronto, agora só falta uma função para filtrar os ganhadores da lista de participantes e calcular o valor proporcional a ser pago a cada um deles:</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>defn pool-winners <span style="color: #66cc66;">&#91;</span>poolseq result<span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#91;</span>sum <span style="color: #66cc66;">&#40;</span>pool-amount poolseq<span style="color: #66cc66;">&#41;</span>
        winners <span style="color: #66cc66;">&#40;</span>filter #<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">guess</span> <span style="color: #66cc66;">%</span><span style="color: #66cc66;">&#41;</span> result<span style="color: #66cc66;">&#41;</span> poolseq<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span>
    <span style="color: #66cc66;">&#40;</span>map #<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">assoc</span> <span style="color: #66cc66;">%</span> <span style="color: #66cc66;">:</span><span style="color: #555;">amount</span> <span style="color: #66cc66;">&#40;</span>double <span style="color: #66cc66;">&#40;</span>* <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">rate</span> <span style="color: #66cc66;">%</span><span style="color: #66cc66;">&#41;</span> sum<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>pool-rates winners<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">;; testando</span>
<span style="color: #66cc66;">&#40;</span>pool-winners pool <span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">1</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #808080; font-style: italic;">;; sem ganhadores</span>
<span style="color: #66cc66;">=&gt;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>pool-winners pool <span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #808080; font-style: italic;">;; apenas um ganhador</span>
<span style="color: #66cc66;">=&gt;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">:</span><span style="color: #b1b100;">name</span> <span style="color: #ff0000;">&quot;Antônio&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">:</span><span style="color: #555;">amount</span> <span style="color: #cc66cc;">7.0</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">:</span><span style="color: #555;">guess</span> <span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">:</span><span style="color: #555;">rate</span> <span style="color: #cc66cc;">1.0</span><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>pool-winners pool <span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">2</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #808080; font-style: italic;">;; vários ganhadores</span>
<span style="color: #66cc66;">=&gt;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">:</span><span style="color: #b1b100;">name</span> <span style="color: #ff0000;">&quot;Daniel&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">:</span><span style="color: #555;">amount</span> <span style="color: #cc66cc;">4.66</span> <span style="color: #66cc66;">...,</span> <span style="color: #66cc66;">:</span><span style="color: #555;">guess</span> <span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">2</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">:</span><span style="color: #555;">rate</span> <span style="color: #cc66cc;">0.66</span> <span style="color: #66cc66;">...</span><span style="color: #66cc66;">&#125;</span>
    <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">:</span><span style="color: #b1b100;">name</span> <span style="color: #ff0000;">&quot;Marcela&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">:</span><span style="color: #555;">amount</span> <span style="color: #cc66cc;">2.33</span> <span style="color: #66cc66;">...,</span> <span style="color: #66cc66;">:</span><span style="color: #555;">guess</span> <span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">2</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">:</span><span style="color: #555;">rate</span> <span style="color: #cc66cc;">0.33</span> <span style="color: #66cc66;">...</span><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Uma grande vantagem dessa solução é que ela permite que você aposte em qualquer coisa. Quer apostar no sexo de um bebê logo após a boa notícia (ou má notícia, sei lá)?</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">;; :male = masculino, :female = feminino</span>
<span style="color: #66cc66;">&#40;</span>def pool <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#40;</span>struct bet <span style="color: #ff0000;">&quot;Daniel&quot;</span>  <span style="color: #cc66cc;">3.0</span> <span style="color: #66cc66;">:</span><span style="color: #555;">male</span><span style="color: #66cc66;">&#41;</span>
           <span style="color: #66cc66;">&#40;</span>struct bet <span style="color: #ff0000;">&quot;Antônio&quot;</span> <span style="color: #cc66cc;">5.0</span> <span style="color: #66cc66;">:</span><span style="color: #555;">female</span><span style="color: #66cc66;">&#41;</span>
           <span style="color: #66cc66;">&#40;</span>struct bet <span style="color: #ff0000;">&quot;Fran&quot;</span>    <span style="color: #cc66cc;">1.0</span> <span style="color: #66cc66;">:</span><span style="color: #555;">female</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>pool-winners pool <span style="color: #66cc66;">:</span><span style="color: #555;">female</span><span style="color: #66cc66;">&#41;</span> <span style="color: #808080; font-style: italic;">;; testando</span>
<span style="color: #66cc66;">=&gt;</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">:</span><span style="color: #b1b100;">name</span> <span style="color: #ff0000;">&quot;Antônio&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">:</span><span style="color: #555;">amount</span> <span style="color: #cc66cc;">7.5</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">...</span><span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">:</span><span style="color: #b1b100;">name</span> <span style="color: #ff0000;">&quot;Fran&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">:</span><span style="color: #555;">amount</span> <span style="color: #cc66cc;">1.5</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">...</span><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Aí está, uma solução simples para um problema simples. Como deveria ser sempre.</p>
<h3>Minha solução, na íntegra</h3>
<p>Embora seja possível resolver isso com um one-liner em Lisp/Clojure (afinal o <a href="http://clojure.org/reader">Reader</a> não trabalha com linhas, mas com <strong>estruturas de dados</strong>), eu optei por escrever um código que fosse o mais legível possível para quem não conhece ou está aprendendo Clojure:</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>defstruct bet <span style="color: #66cc66;">:</span><span style="color: #b1b100;">name</span> <span style="color: #66cc66;">:</span><span style="color: #555;">amount</span> <span style="color: #66cc66;">:</span><span style="color: #555;">guess</span> <span style="color: #66cc66;">:</span><span style="color: #555;">rate</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>defn pool-amount <span style="color: #66cc66;">&#91;</span>poolseq<span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&#40;</span>reduce<span style="color: #66cc66;"> + </span><span style="color: #66cc66;">&#40;</span>map <span style="color: #66cc66;">:</span><span style="color: #555;">amount</span> poolseq<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>defn pool-rates <span style="color: #66cc66;">&#91;</span>poolseq<span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#91;</span>sum <span style="color: #66cc66;">&#40;</span>pool-amount poolseq<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span>
    <span style="color: #66cc66;">&#40;</span>map #<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">assoc</span> <span style="color: #66cc66;">%</span> <span style="color: #66cc66;">:</span><span style="color: #555;">rate</span> <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">amount</span> <span style="color: #66cc66;">%</span><span style="color: #66cc66;">&#41;</span> sum<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> poolseq<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span>defn pool-winners <span style="color: #66cc66;">&#91;</span>poolseq result<span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#91;</span>sum <span style="color: #66cc66;">&#40;</span>pool-amount poolseq<span style="color: #66cc66;">&#41;</span>
        winners <span style="color: #66cc66;">&#40;</span>filter #<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">guess</span> <span style="color: #66cc66;">%</span><span style="color: #66cc66;">&#41;</span> result<span style="color: #66cc66;">&#41;</span> poolseq<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span>
    <span style="color: #66cc66;">&#40;</span>map #<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">assoc</span> <span style="color: #66cc66;">%</span> <span style="color: #66cc66;">:</span><span style="color: #555;">amount</span> <span style="color: #66cc66;">&#40;</span>double <span style="color: #66cc66;">&#40;</span>* <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">:</span><span style="color: #555;">rate</span> <span style="color: #66cc66;">%</span><span style="color: #66cc66;">&#41;</span> sum<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>pool-rates winners<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<h3>Levando adiante</h3>
<p>Você programa em Haskell? Python? Ruby? <a href="http://en.wikipedia.org/wiki/Brainfuck">Brainfuck</a>? Qual seria a sua solução para este problema de extrema importância para o desenvolvimento da raça humana? <img src='http://weblog.destaquenet.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p><strong>Atualização (03/11/2010).</strong> Solução em Common Lisp, usando <code>copy-*</code> para evitar mutabilidade:</p>

<div class="wp_syntax"><div class="code"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>defstruct bet <span style="color: #b1b100;">name</span> amount guess rate<span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> pool-amount <span style="color: #66cc66;">&#40;</span>pool<span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span>reduce #'+ <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">mapcar</span> #'bet-amount pool<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> pool-rates <span style="color: #66cc66;">&#40;</span>pool<span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>sum <span style="color: #66cc66;">&#40;</span>pool-amount pool<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">mapcar</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">lambda</span> <span style="color: #66cc66;">&#40;</span>bet<span style="color: #66cc66;">&#41;</span>
              <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>x <span style="color: #66cc66;">&#40;</span>copy-bet bet<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
                <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">setf</span> <span style="color: #66cc66;">&#40;</span>bet-rate x<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>/ <span style="color: #66cc66;">&#40;</span>bet-amount x<span style="color: #66cc66;">&#41;</span> sum<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
                x<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> pool<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">defun</span> pool-winners <span style="color: #66cc66;">&#40;</span>pool result<span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>sum <span style="color: #66cc66;">&#40;</span>pool-amount pool<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#40;</span>winners <span style="color: #66cc66;">&#40;</span>loop for bet in pool <span style="color: #b1b100;">when</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">equal</span> <span style="color: #66cc66;">&#40;</span>bet-guess bet<span style="color: #66cc66;">&#41;</span> result<span style="color: #66cc66;">&#41;</span> collect bet<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">mapcar</span> <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">lambda</span> <span style="color: #66cc66;">&#40;</span>winner<span style="color: #66cc66;">&#41;</span>
              <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>x <span style="color: #66cc66;">&#40;</span>copy-bet winner<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
                <span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">setf</span> <span style="color: #66cc66;">&#40;</span>bet-amount x<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>* <span style="color: #66cc66;">&#40;</span>bet-rate x<span style="color: #66cc66;">&#41;</span> sum<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
                x<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#40;</span>pool-rates winners<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>

<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-898-1'>Todo o montante recebido continua disponível no próximo bolão, mas os participantes devem pagar um novo palpite. <span class='footnotereverse'><a href='#fnref-898-1'>&#8617;</a></span></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2010/06/15/em-tempos-de-copa-do-mundo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django-Flash e o Novo Framework de Mensagens</title>
		<link>http://weblog.destaquenet.com/2010/05/21/django-flash-e-o-novo-framework-de-mensagens/</link>
		<comments>http://weblog.destaquenet.com/2010/05/21/django-flash-e-o-novo-framework-de-mensagens/#comments</comments>
		<pubDate>Fri, 21 May 2010 02:36:14 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Português]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[django-flash]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=890</guid>
		<description><![CDATA[No começo da semana, depois de vários meses de trabalho duro e algum atraso, a versão 1.2 do Django foi finalmente lançada. Este talvez seja o lançamento mais aguardado do framework desde seu surgimento, e inclui recursos há muito aguardados, &#8230; <a href="http://weblog.destaquenet.com/2010/05/21/django-flash-e-o-novo-framework-de-mensagens/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>No começo da semana, depois de vários meses de trabalho duro e algum atraso, a versão 1.2 do Django <a href="http://www.djangoproject.com/download/">foi finalmente lançada</a>. Este talvez seja o lançamento mais aguardado do framework desde seu surgimento, e inclui recursos há muito aguardados, como <a href="http://docs.djangoproject.com/en/dev/releases/1.2/#support-for-multiple-databases">suporte a múltiplos bancos de dados</a> e um <a href="http://docs.djangoproject.com/en/dev/releases/1.2/#messages-framework">framework de &#8220;mensagens&#8221;</a>.</p>
<p>Sim, eu disse que o Django 1.2 traz incluso um framework de &#8220;mensagens&#8221;. Bom, né? Django realmente precisava vir acompanhado de uma app para resolver essa questão. Isso não significa, no entanto, que <a href="http://djangoflash.destaquenet.com/">Django-Flash</a> será descontinuado ou abandonado.</p>
<p>Então, se você usa Django-Flash em seus projetos, não se preocupe! Nada mudará. Django-Flash já é compatível com Django 1.2, e nós ocontinuaremos a mantê-lo por algumas razões.</p>
<p>A primeira delas é que nos importamos com quem usa nosso software. Nós não quebraremos seus projetos se você decidir fazer o upgrade para uma versão mais recente do Django &#8211; ou se decidir continuar usando uma versão anterior.</p>
<p>A outra é a liberdade de escolha. Você sabe, não existe uma única forma de se resolver todos os problemas. As pessoas devem ser livres para escolher a ferramenta apropriada a uma determinada situação.</p>
<p>Por exemplo, baseado nas minhas primeiras impressões, existem algumas coisas que eu realmente não gostei no novo framework de &#8220;mensagens&#8221;:</p>
<ol>
<li>Ele é <em>verboso</em> mesmo nos casos de uso mais simples</li>
<li>Ele associa mensagens a números de prioridade, encorajando os usuários a usá-lo como um framework de logging/debugging. Quero dizer, um framework de &#8220;mensagens&#8221; não é um framework de logging/debugging, certo?</li>
</ol>
<p>Mas essa é apenas a minha opinião. Talvez seja isso que faz do open source algo tão formidável!</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2010/05/21/django-flash-e-o-novo-framework-de-mensagens/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python para S60: Trabalho em Andamento?</title>
		<link>http://weblog.destaquenet.com/2010/02/17/python-para-s60-trabalho-em-andamento/</link>
		<comments>http://weblog.destaquenet.com/2010/02/17/python-para-s60-trabalho-em-andamento/#comments</comments>
		<pubDate>Wed, 17 Feb 2010 12:30:29 +0000</pubDate>
		<dc:creator>Daniel Martins</dc:creator>
				<category><![CDATA[Português]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[celular]]></category>
		<category><![CDATA[nokia]]></category>
		<category><![CDATA[pys60]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[python for s60]]></category>
		<category><![CDATA[s60]]></category>
		<category><![CDATA[smartphone]]></category>
		<category><![CDATA[symbian]]></category>

		<guid isPermaLink="false">http://weblog.destaquenet.com/?p=846</guid>
		<description><![CDATA[Eu fui um dos sortudos que perderam o celular a alguns meses atrás, durante aquele show maluco do AC/DC. Surpreendentemente, isso não me deixou aborrecido; apesar de não ser um heavy user, essa foi a oportunidade perfeita para eu comprar &#8230; <a href="http://weblog.destaquenet.com/2010/02/17/python-para-s60-trabalho-em-andamento/">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Eu fui um dos sortudos que perderam o celular a alguns meses atrás, durante aquele <a href="http://weblog.destaquenet.com/2009/10/05/use-web-scraping-para-acompanhar-seus-pedidos-na-ticketmaster/">show maluco do AC/DC</a>. Surpreendentemente, isso não me deixou aborrecido; apesar de não ser um heavy user, essa foi a oportunidade perfeita para eu comprar meu primeiro smartphone.</p>
<p>No fim das contas eu acabei com um <a href="http://europe.nokia.com/find-products/devices/nokia-5800-xpressmusic">Nokia 5800 XpressMusic</a>, um smartphone relativamente barato e com features interessantes. Especificamente, o fato de poder rodar aplicações <a href="http://python.org">Python</a> nesse aparelho foi um fator decisivo!</p>
<p>Mas, o que exatamente podemos fazer com <a href="https://garage.maemo.org/projects/pys60/">Python para S60</a>? Eu decidi implementar uma aplicação não trivial para ver exatamente o que pode ser feito com ele. A aplicação em questão é um controle remoto Bluetooth chamado <a href="http://github.com/danielfm/pytriloquist">Pytriloquist</a>. (veja também <a href="http://www.flickr.com/photos/daniel_tritone/4313716091/in/set-72157623183881993/">screenshots</a> e <a href="http://www.youtube.com/watch?v=2IVXMAJHwI8">vídeo</a> de demonstração.)</p>
<p><span id="more-846"></span></p>
<h3>O que é Bom</h3>
<p><strong>Independência de Plataforma.</strong> A <a href="http://www.forum.nokia.com/Tools_Docs_and_Code/Tools/Platforms/S60_Platform_SDKs/">SDK para S60</a> só roda em Windows (que novidade). Isso obviamente é ruim para quem costuma usar outros sistemas operacionais. Felizmente, você não precisa de uma SDK gigante para desenvolver e distribuir aplicações para S60 se você escrevê-las em Python; tudo o que você precisa é do Python para S60, um editor de texto e um aparelho para testes.</p>
<p><strong>Linguagem e Biblioteca Padrão.</strong> Python é uma linguagem excelente: compacta, bonita, poderosa e tem uma biblioteca padrão <em>sensacional</em>. A boa notícia é que a maioria dos módulos rodam bem no S60. Por exemplo, é possível até localizar suas aplicações usando o módulo <code>gettext</code>!</p>
<h3>O que é Ruim</h3>
<p><strong>Trabalho em Andamento.</strong> Python para S60, até onde me consta, é um trabalho em andamento. Isso significa que a linguagem em si funciona bem, mas você pode dar falta de certos módulos ou <a href="https://garage.maemo.org/tracker/?atid=3201&#038;group_id=854&#038;func=browse">encontrar bugs</a> na biblioteca padrão. Por exemplo, enquanto eu escrevia o código Bluetooth para minha applicação, eu dei de cara com um <a href="https://garage.maemo.org/tracker/index.php?func=detail&#038;aid=3947&#038;group_id=854&#038;atid=3201">bug muito chato</a> onde você só pode chamar <code>btsocket.bt_discovert()</code> uma vez!</p>
<p><strong>Código Multi-Módulos.</strong> Se você está testando sua aplicação com Python ScriptShell, tudo irá funcionar de cara desde que você mantenha todo o código dentro de um único &#8212; e enorme &#8212; módulo. Se você quebrar seu código em vários módulos (ou pior, pacotes), você não poderá ter módulos importando uns aos outros, a menos que você ajuste o <code>PYTHON_PATH</code> de acordo.</p>
<p><strong>Documentação Incompleta e Desatualizada.</strong> Existem alguns PDFs e algumas documentações de API disponíveis, mas elas estão incompletas e desatualizadas, o que é ruim quando se trata de uma linguagem dinâmica; nós não temos um compilador para nos dizer o que há de errado com nosso código. Esse é o motivo pelo qual desenvolvedores Python são tão cuidadosos com documentação pra começo de conversa.</p>
<h3>O que é Feio</h3>
<p><strong>Acesso Limitado a Recursos Nativos.</strong> Especialmente em se tratando do sistema de UI nativo: você não pode mudar o texto das duas soft keys padrão, nem adicionar soft keys, nem adicionar mais que duas abas, nem ter um <code>Listbox</code> vazio, nem um monte de outras coisas. Você pode escrever UIs simples sem muito esforço, isso é verdade, mas essas deficiências todas tornam Python para S60 simplesmente inutilizável em projetos mais complexos.</p>
<p><strong>Inatividade do Projeto.</strong> O projeto parece estar em modo &#8220;stand by&#8221;. Novos bug reports são enviados de tempos em tempos, mas nenhum bug foi fechado há mais de <a href="https://garage.maemo.org/project/stats/?group_id=854">seis meses</a>.</p>
<h3>Conclusão</h3>
<p>Espero que as coisas mudem para melhor após o último <a href="http://www.symbian.org/symbian-feature-set/symbian-is-open-source">anúncio</a> feito pela Fundação Symbian, mas, enquanto isso, se você pretende criar aplicações sérias para S60, o faça em C++.</p>
]]></content:encoded>
			<wfw:commentRss>http://weblog.destaquenet.com/2010/02/17/python-para-s60-trabalho-em-andamento/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

