<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1387996720436450649</id><updated>2012-01-22T07:23:13.231-03:00</updated><category term='Python'/><category term='Evento'/><category term='ECMA'/><category term='C'/><category term='Pylons'/><category term='Tcl'/><category term='Declarativa'/><category term='XML'/><category term='Math'/><category term='Perl'/><category term='Conceitual'/><category term='Java'/><category term='OO'/><category term='Prolog'/><category term='Lisp'/><category term='WSGI'/><category term='OpenID'/><category term='Haskell'/><category term='Funcional'/><category term='PHP'/><category term='Shell'/><category term='git'/><category term='Smalltalk'/><category term='Ruby'/><category term='turbogears'/><category term='Lua'/><category term='Patterns'/><category term='Basic'/><title type='text'>Kodumaro</title><subtitle type='html'>As sombras da programação</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default?start-index=101&amp;max-results=100'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>109</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-155102472275163258</id><published>2012-01-22T07:02:00.007-03:00</published><updated>2012-01-22T07:23:13.248-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Funcional'/><title type='text'>Média harmónica</title><content type='html'>&lt;img style="border: medium none ; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://photos1.blogger.com/blogger/6505/3295/200/prog.png" alt="Poliedro" /&gt; Já que falávamos de variâncias e médias, um dos cálculos mais belos de média é a &lt;a href="http://pt.wikipedia.org/wiki/Média_harmônica"&gt;média harmónica&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Vou &lt;em&gt;roubar&lt;/em&gt; &lt;del&gt;a explicação&lt;/del&gt; o exemplo da Wikipédia por pura preguiça… :-/&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update]&lt;/tt&gt;&lt;br /&gt;Roubar a explicação não… roubei o exemplo. Para a explicação deixei o &lt;a href="http://pt.wikipedia.org/wiki/Média_harmônica"&gt;apontador&lt;/a&gt; para o artigo na Wikipédia – mais preguiçoso ainda!&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Você se lembra do colégio, quando tinha de calcular a velocidade média percorrida por um carro, certo? Imagine que um carro faz uma viagem de &lt;em&gt;x&lt;/em&gt; horas, tendo percorrido metade do tempo a 40Km/h e a outra metade a 60Km/h.&lt;br /&gt;&lt;br /&gt;Calcular a velocidade média é bem fácil, não?&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;img src="http://cacilhas.info/bin/mimetex.cgi?\frac{40Km/h+60Km/h}{2}=50Km/h" alt="(40Km/h + 60Km/h) / 2 = 50Km/h" /&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;Então o carro percorreu a distância a uma velocidade média de 50Km/h, tornando fácil calcular, por exemplo, a distância: se o carro andou por 3h, percorreu 150Km.&lt;br /&gt;&lt;br /&gt;Porém imagine que a proposição do problema não fosse quanto ao tempo, mas quanto à distância…&lt;br /&gt;&lt;br /&gt;O carro percorreu metade do &lt;strong&gt;percurso&lt;/strong&gt; (não do tempo) a 40Km/h e outra metade a 60Km/h. Qual a velocidade média?&lt;br /&gt;&lt;br /&gt;Para obter esse resultado, precisamos da média harmónica:&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;img src="http://cacilhas.info/bin/mimetex.cgi?\frac{2}{\frac{1}{40Km/h}+\frac{1}{60Km/h}}=48Km/h" alt="2 / ((1 / 40Km/h) + (1 / 60Km/h)) = 48Km/h" /&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;Então é o equivalente a percorrer todo o trajeto a 48Km/h.&lt;br /&gt;&lt;br /&gt;Isso também se aplica a diversos outros ramos, como a matemática financeira: se um investidor aplica um mesmo valor em compra de ações todos os meses, no final o preço médio das ações será a média harmónica dos preços das ações em cada mês.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Mãos à massa&lt;/h3&gt;&lt;br /&gt;Conversamos até agora sobre matemática, agora é hora de ver o código! Usarei novamente &lt;a href="http://schemers.org/"&gt;Scheme&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Vamos nos concentrar primeiro no cálculo do denominador. Novamente apelaremos para &lt;em&gt;&lt;a href="http://en.wikipedia.org/wiki/Map_(higher-order_function)"&gt;map&lt;/a&gt;/&lt;a href="http://en.wikipedia.org/wiki/Fold_(higher-order_function)"&gt;reduce&lt;/a&gt;&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;O &lt;em&gt;map&lt;/em&gt; será usado para inverter cada um dos elementos, para tanto usaremos a função lambda &lt;em&gt;(λx.(1/x))x&lt;sub&gt;i&lt;/sub&gt;&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(map (lambda (x) (/ 1 x)) *list*)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Feio isso, precisaremos de um somatório desses elementos, portanto usaremos &lt;em&gt;reduce&lt;/em&gt; novamente com &lt;code&gt;#'apply&lt;/code&gt; e &lt;code&gt;#'+&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(apply +&lt;br /&gt;       (map (lambda (x) (/ 1 x)) *list*))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O numerador é fácil, é a quantidade de elementos, ou tamanho da lista:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(length *list*)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Basta dividirmos um pelo outro e, quase sem querer, já temos o cálculo da média harmónica!&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(define harmonic-mean&lt;br /&gt;  (lambda (*list*)&lt;br /&gt;    (/&lt;br /&gt;      (length *list*)&lt;br /&gt;      (apply +&lt;br /&gt;             (map (lambda (x) (/ 1 x)) *list*)))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Se quiser testar com os valores do exemplo (40Km/h e 60Km/h):&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(let ((params '(40 60)))&lt;br /&gt;  (display (harmonic-mean params))&lt;br /&gt;  (newline))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update]&lt;/tt&gt;&lt;br /&gt;Ainda esperando o pessoal do &lt;a href="http://code.google.com/p/google-code-prettify/"&gt;Prettify&lt;/a&gt; corrigir o &lt;em&gt;syntax highlighting&lt;/em&gt; para &lt;a href="http://pt.wikipedia.org/wiki/Lisp"&gt;LISP&lt;/a&gt;.&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-155102472275163258?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/155102472275163258/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=155102472275163258' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/155102472275163258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/155102472275163258'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2012/01/media-harmonica.html' title='Média harmónica'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-3427944306447586523</id><published>2012-01-16T23:08:00.005-03:00</published><updated>2012-01-17T11:03:30.864-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='Funcional'/><title type='text'>Dissecando a variância</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://4.bp.blogspot.com/_rGfO7DAuOSE/Rgv00nwEXZI/AAAAAAAAAB8/r59qEVD0qOE/s200/haskell.jpg" alt="Paradigma funcional" /&gt; Este artigo dá seguimento ao &lt;a href="http://kodumaro.blogspot.com/2012/01/variancia.html"&gt;artigo sobre variância amostral&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;A variância pode ser entendida como a média aritmética dos quadrados dos desvios de cada elemento da população.&lt;br /&gt;&lt;br /&gt;O desvio de um elemento é a diferença entre o elemento e seu valor esperado. Quando lidamos com um conjunto, o valor esperado é a média dos elementos.&lt;br /&gt;&lt;br /&gt;Então o desvio do elemento &lt;em&gt;x&lt;sub&gt;i&lt;/sub&gt;&lt;/em&gt; é &lt;em&gt;x&lt;sub&gt;i&lt;/sub&gt;&amp;nbsp;-&amp;nbsp;&lt;span style="text-decoration: overline;"&gt;x&lt;/span&gt;&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;A variância populacional pode ser descrita como:&lt;br /&gt;&lt;center&gt;&lt;img src="http://cacilhas.info/bin/mimetex.cgi?\sigma^2_x=\frac{1}{n}\sum_{i=1}^n(x_i-\bar{x})^2" alt="σ²x=1/n Σ(xi - xm)" /&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;Na maioria dos casos, não se tem disponível todos os elementos de um conjunto, mas apenas uma amostra. Nesses casos, calculamos a variância de amostra ou variância amostral.&lt;br /&gt;&lt;br /&gt;A diferença no cálculo é que, em vez de dividirmos pelo número total de elementos da amostra no cálculo da média, dividimos pelo número total menos um, o que aumenta o resultado do desvio padrão, compensando não conhecermos todos os elementos do conjunto.&lt;br /&gt;&lt;br /&gt;Então o cálculo muda para:&lt;br /&gt;&lt;center&gt;&lt;img src="http://cacilhas.info/bin/mimetex.cgi?s^2_x=\frac{1}{n-1}\sum_{i=1}^n(x_i-\bar{x})^2" alt="s²x=1/(n - 1) Σ(xi - xm)" /&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;Em &lt;a href="http://www.erlang.org/"&gt;Erlang&lt;/a&gt;, para calcular o somatório dos desvios, primeiros usamos &lt;a href="http://pt.wikipedia.org/wiki/List_comprehension"&gt;&lt;em&gt;list comprehension&lt;/em&gt;&lt;/a&gt; para gerar uma lista dos quadrados desvios:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;[math:pow(Xi - Xm, 2) || Xi &amp;lt;- List]&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O que este código diz é: retorne a lista dos quadrados (&lt;code&gt;math:pow/2&lt;/code&gt;) das diferenças entre cada elemento (&lt;code&gt;Xi&lt;/code&gt;) da lista (&lt;code&gt;Xi&amp;nbsp;&amp;lt;-&amp;nbsp;List&lt;/code&gt;) e sua média (&lt;code&gt;Xm&lt;/code&gt;, calculado anteriormente).&lt;br /&gt;&lt;br /&gt;Depois ele usa &lt;code&gt;math:sum/1&lt;/code&gt; para gerar um somatório e retorna a divisão do resultado do somatório pelo tamanho da lista menos um (&lt;code&gt;Num&amp;nbsp;/&amp;nbsp;Demon&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;Volte ao &lt;a href="http://kodumaro.blogspot.com/2012/01/variancia.html"&gt;artigo anterior&lt;/a&gt; para ver como fica o código.&lt;br /&gt;&lt;br /&gt;Em &lt;a href="http://schemers.org/"&gt;Scheme&lt;/a&gt;, a lógica é quase a mesma, mas em vez de &lt;em&gt;list comprehension&lt;/em&gt;, é usado &lt;em&gt;&lt;a href="http://en.wikipedia.org/wiki/Map_(higher-order_function)"&gt;map&lt;/a&gt;/&lt;a href="http://en.wikipedia.org/wiki/Fold_(higher-order_function)"&gt;reduce&lt;/a&gt;&lt;/em&gt;. O &lt;code&gt;#'map&lt;/code&gt; roda a função anónima (&lt;a href="http://pt.wikipedia.org/wiki/Cálculo_lambda"&gt;&lt;em&gt;lambda&lt;/em&gt;&lt;/a&gt;) em cada elemento, extraindo os quadrados dos desvios.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update]&lt;/tt&gt;&lt;br /&gt;Troquei o &lt;em&gt;link&lt;/em&gt; para &lt;em&gt;map/reduce&lt;/em&gt;, que apontava para um &lt;a href="http://en.wikipedia.org/wiki/Map/reduce"&gt;arcabouço do Google&lt;/a&gt;, quando as referências reais seriam encontradas no segundo parágrafo do texto referenciado.&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;A função usada foi &lt;em&gt;(λx.(x&amp;nbsp;-&amp;nbsp;&lt;span style="text-decoration: overline;"&gt;x&lt;/span&gt;)²)x&lt;sub&gt;i&lt;/sub&gt;&lt;/em&gt;, ou: &lt;code&gt;(lambda (x) (expt (- x xm) 2))&lt;/code&gt; em LISP.&lt;br /&gt;&lt;br /&gt;Para o &lt;em&gt;reduce&lt;/em&gt; (&lt;code&gt;#'apply&lt;/code&gt;) é usado somatório (&lt;code&gt;#'+&lt;/code&gt;), aplicado ao conjunto resultante.&lt;br /&gt;&lt;br /&gt;Novalmente, volte ao &lt;a href="http://kodumaro.blogspot.com/2012/01/variancia.html"&gt;artigo anterior&lt;/a&gt; para ver o código.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-3427944306447586523?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/3427944306447586523/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=3427944306447586523' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/3427944306447586523'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/3427944306447586523'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2012/01/variancia-2.html' title='Dissecando a variância'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_rGfO7DAuOSE/Rgv00nwEXZI/AAAAAAAAAB8/r59qEVD0qOE/s72-c/haskell.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-8071660945048702559</id><published>2012-01-15T20:06:00.005-03:00</published><updated>2012-01-15T20:20:00.980-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Funcional'/><title type='text'>Variância</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 55px; height: 55px; border: none;" src="http://2.bp.blogspot.com/_rGfO7DAuOSE/SwSZGIY_eXI/AAAAAAAAATA/Gh-qDqdTMX0/s200/glider.png" alt="Glider" /&gt; Uma das operações mais importantes e necessárias da matemática é a &lt;a href="http://pt.wikipedia.org/wiki/Variância"&gt;variância de amostra&lt;/a&gt;. É usada, por exemplo, para o cálculo do desvio padrão e da regressão linear.&lt;br /&gt;&lt;br /&gt;Usando linguagens funcionais, a implementação fica muito mais elegante.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Erlang&lt;/h3&gt;&lt;br /&gt;Em &lt;a href="http://www.erlang.org/"&gt;Erlang&lt;/a&gt;, a função para o cálculo da variância toma o seguinte formato:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;variance(List) -&amp;gt;&lt;br /&gt;    Xm = mean(List),&lt;br /&gt;    Num = lists:sum([math:pow(Xi - Xm, 2) || Xi &amp;lt;- List]),&lt;br /&gt;    Denom = length(List) - 1,&lt;br /&gt;    Num / Denom.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;É preciso ainda definir a função de média, &lt;code&gt;mean/1&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;mean(List) -&amp;gt;&lt;br /&gt;    lists:sum(List) / length(List).&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;LISP&lt;/h3&gt;&lt;br /&gt;Em &lt;a href="http://schemers.org/"&gt;Scheme&lt;/a&gt; a implementação é um pouco mais verbosa, mas ainda assim elegante.&lt;br /&gt;&lt;br /&gt;Segue o código em &lt;a href="http://schemers.org/Documents/Standards/R5RS/"&gt;R⁵RS&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(define variance&lt;br /&gt;  (lambda (*list*)&lt;br /&gt;    (let ((xm (mean *list*)))&lt;br /&gt;      (/&lt;br /&gt;       (apply +&lt;br /&gt;              (map (lambda (x) (expt (- x xm) 2)) *list*))&lt;br /&gt;       (- (length *list*) 1)))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Também precisamos implementar a média:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(define mean&lt;br /&gt;  (lambda (*list*)&lt;br /&gt;    (/&lt;br /&gt;     (apply + *list*)&lt;br /&gt;     (length *list*))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Paradigma imperativo&lt;/h3&gt;&lt;br /&gt;Para comparação, segue a implementação de variância em uma linguagem imperativa, &lt;a href="http://pt.wikipedia.org/wiki/C_(linguagem_de_programação)"&gt;C&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;double variance(int length, double *list) {&lt;br /&gt;    double x_mean = mean(length, list);&lt;br /&gt;    double sum = 0;&lt;br /&gt;    int i;&lt;br /&gt;&lt;br /&gt;    for (i=0; i&amp;lt;length; ++i)&lt;br /&gt;        sum += pow(list[i] - x_mean, 2.);&lt;br /&gt;&lt;br /&gt;    return sum / (length - 1);&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;É preciso incluir o cabeçalho &lt;code&gt;math.h&lt;/code&gt;. Segue a implementação da função &lt;code&gt;mean()&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;double mean(int length, double *list) {&lt;br /&gt;    double sum = 0;&lt;br /&gt;    int i;&lt;br /&gt;&lt;br /&gt;    for (i=0; i&amp;lt;length; ++i)&lt;br /&gt;        sum += list[i];&lt;br /&gt;&lt;br /&gt;    return sum / length;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Perceba a mudança de estado, o que não ocorre nos códigos funcionais.&lt;br /&gt;&lt;br /&gt;Escolhi C em vez de &lt;a href="http://python.org"&gt;Python&lt;/a&gt;, porque Python também suporta bem o paradigma funcional, enquanto C é quase necessariamente imperativa.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-8071660945048702559?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/8071660945048702559/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=8071660945048702559' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8071660945048702559'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8071660945048702559'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2012/01/variancia.html' title='Variância'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_rGfO7DAuOSE/SwSZGIY_eXI/AAAAAAAAATA/Gh-qDqdTMX0/s72-c/glider.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-5444877383348468882</id><published>2011-10-17T15:48:00.019-03:00</published><updated>2011-10-19T17:31:27.030-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='Funcional'/><title type='text'>Racket</title><content type='html'>&lt;img style="float: left; margin:0 10px 10px 0; cursor: crosshair; width: 100px; height: 100px; border: none;" src="http://2.bp.blogspot.com/-8lF7wwUkFmQ/Tpx4nLMrg8I/AAAAAAAAAcE/x-8o5hkGBHE/s200/racket.jpg" alt="Racket" id="BLOGGER_PHOTO_ID_5664535045741446082" /&gt; Outro dia procurando por um bom interpretador/compilador para &lt;a href="http://docs.racket-lang.org/r6rs/"&gt;R⁶RS&lt;/a&gt;, encontrei algo muito mais interessante…&lt;br /&gt;&lt;br /&gt;Encontrei o &lt;a href="http://pt.wikipedia.org/wiki/Rapid_Application_Development"&gt;RAD&lt;/a&gt;-&lt;a href="http://pt.wikipedia.org/wiki/Ambiente_de_desenvolvimento_integrado"&gt;IDE&lt;/a&gt; &lt;a href="http://racket-lang.org/"&gt;Racket&lt;/a&gt;, antigo DrScheme.&lt;br /&gt;&lt;br /&gt;O interessante do Racket é que, além de ser um interpretador e compilador de R⁵RS e R⁶RS, também suporta – aliás, por padrão – uma linguagem de programação baseada em Scheme, também chamada Racket – antiga PLT Scheme –, muito poderosa; também traz um ambiente de desenvolvimento chamado DrRacket.&lt;br /&gt;&lt;br /&gt;Quando você escreve um &lt;em&gt;script&lt;/em&gt; em Scheme, a primeira linha indica a versão que você pretende usar:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#!r4rs&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Ou:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#!r5rs&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Ou:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#!r6rs&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Se o interpretador suportar a versão, ela será usada. Já no caso do Racket, outras opções são suportadas, como o padrão:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#lang racket&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Para a linguagem padrão.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update 2011-10-18]&lt;/tt&gt;&lt;br /&gt;Um &lt;em&gt;script&lt;/em&gt; R⁶RS começa sempre com um &lt;code&gt;import&lt;/code&gt;, por exemplo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#!r6rs&lt;br /&gt;(import (rnrs))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Você pode ter as funções de R⁶RS em um código Racket (PLT), basta usar:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#lang racket&lt;br /&gt;(require rnrs)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O módulo &lt;code&gt;rnrs&lt;/code&gt; traz toda a funcionalidade de R⁶RS.&lt;br /&gt;&lt;br /&gt;Outra coisa legal da linguagem Racket é que, em vez de &lt;code&gt;lambda&lt;/code&gt;, você pode usar &lt;code&gt;λ&lt;/code&gt; (⌘\ / &lt;tt&gt;C-\&lt;/tt&gt;).&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;E até mesmo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#lang planet jaymccarthy/c&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Para &lt;a href="http://pt.wikipedia.org/wiki/Linguagem_de_programação_C"&gt;linguagem de programação C&lt;/a&gt; – uma opção de C interpretado!&lt;br /&gt;&lt;br /&gt;Para tanto você precisa ter em seu &lt;code&gt;~/.racketrc&lt;/code&gt; o seguinte conteúdo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#lang racket&lt;br /&gt;(require (planet jaymccarthy/c:1:2))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para instalar o módulo C, você pode executar no &lt;em&gt;widget&lt;/em&gt; de definições (⌘D no Mac OS X, &lt;tt&gt;C-d&lt;/tt&gt; no Windows e no GNU/Linux):&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;(require (planet "main.rkt" ("jaymccarthy" "c.plt" 1 2)))&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update 2011-10-18]&lt;/tt&gt;&lt;br /&gt;Eu acho que você não precise instalar o módulo, basta colocar sua chamada em &lt;code&gt;~/.racketrc&lt;/code&gt; e, na primeira execução, o módulo será automaticamente baixado e instalado.&lt;br /&gt;&lt;br /&gt;Só não posso afirmar com certeza porque eu já havia instalado ele antes.&lt;br /&gt;&lt;br /&gt;No Windows, o arquivo é &lt;code&gt;racketrc.rktl&lt;/code&gt; e deve ficar no diretório de perfil do usuário.&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Programação visual&lt;/h3&gt;&lt;br /&gt;Para facilitar a vida de quem precisa desenvolver aplicações gráficas, você pode usar o &lt;a href="http://mred-designer.origo.ethz.ch/"&gt;MrEd Designer&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Para instalá-lo, execute no &lt;em&gt;widget&lt;/em&gt; de definições do DrRacket:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;(require (planet orseau/mred-designer:3:7))&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para iniciar o processo, use (recomendo criar um &lt;code&gt;alias&lt;/code&gt;):&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;gracket -e '(require (planet orseau/mred-designer:3:7))'&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Olá Mundo!&lt;/h3&gt;&lt;br /&gt;Vamos criar um programa simples. Primeiro abra o MrEd Designer.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update 2011-10-19]&lt;/tt&gt;&lt;br /&gt;Troquei os nomes dos &lt;em&gt;widgets&lt;/em&gt; pelos nomes usados no código Racket.&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Na janela &lt;tt&gt;Hierarchy&lt;/tt&gt; selecione &lt;code&gt;project-&lt;em&gt;XXX&lt;/em&gt;&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Na janela &lt;tt&gt;MrEd Designer&lt;/tt&gt;, na seção &lt;tt&gt;Containers&lt;/tt&gt;, clique no primeiro botão, &lt;code&gt;frame%&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Vai surgir uma janela pequena e, na hierarquia do projeto, um &lt;code&gt;frame%&lt;/code&gt; (&lt;code&gt;frame-&lt;em&gt;XXXX&lt;/em&gt;&lt;/code&gt;) sob o projeto.&lt;br /&gt;&lt;br /&gt;Na janela &lt;tt&gt;Hierarchy&lt;/tt&gt; selecione o &lt;code&gt;frame%&lt;/code&gt; que apareceu e repare que a janela &lt;tt&gt;Properties&lt;/tt&gt; mudou.&lt;br /&gt;&lt;br /&gt;Em &lt;tt&gt;Properties&lt;/tt&gt;, mude o valor de &lt;em&gt;label&lt;/em&gt; (que está &lt;code&gt;Frame&lt;/code&gt;) para &lt;code&gt;Olá Mundo!&lt;/code&gt; e clique em &lt;tt&gt;Save &amp;amp; Update Preview&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;Veja que o título da janela mudou.&lt;br /&gt;&lt;br /&gt;Agora, ainda com o &lt;code&gt;frame%&lt;/code&gt; selecionado, na janela &lt;tt&gt;MrEd Designer&lt;/tt&gt;, na seção &lt;tt&gt;Controls&lt;/tt&gt;, clique no primeiro botão, &lt;code&gt;message%&lt;/code&gt;. Repare que surgiu um elemento &lt;code&gt;message%&lt;/code&gt; (&lt;code&gt;message-&lt;em&gt;XXXX&lt;/em&gt;&lt;/code&gt;) na hieraquia, sob o &lt;code&gt;frame%&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Selecione o novo elemento e mude o &lt;em&gt;label&lt;/em&gt; (em &lt;tt&gt;Properties&lt;/tt&gt;) para &lt;code&gt;Olá Mundo!&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Clique em &lt;tt&gt;Choose Font…&lt;/tt&gt; e escolha uma fonte maior, sugiro Arial Bold 20, e clique em &lt;tt&gt;Ok&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;Clique novamente em &lt;tt&gt;Save &amp;amp; Update Preview&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;Selecione de novo o &lt;code&gt;frame%&lt;/code&gt; em &lt;tt&gt;Hierarchy&lt;/tt&gt; e, em &lt;tt&gt;MrEd Designer&lt;/tt&gt; → &lt;tt&gt;Controls&lt;/tt&gt;, clique no segundo botão, &lt;code&gt;button%&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Surgirá um elemento &lt;code&gt;button%&lt;/code&gt; (&lt;code&gt;button-&lt;em&gt;XXXX&lt;/em&gt;&lt;/code&gt;) sob o &lt;code&gt;frame%&lt;/code&gt;. Selecione-o.&lt;br /&gt;&lt;br /&gt;Mude o &lt;em&gt;label&lt;/em&gt; para &lt;code&gt;Ok&lt;/code&gt; e a fonte para Arial 14. Clique em &lt;tt&gt;Save &amp; Update Preview&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;Agora, na janela &lt;tt&gt;MrEd Designer&lt;/tt&gt;, no menu &lt;tt&gt;File&lt;/tt&gt; clique em &lt;tt&gt;Save Project&lt;/tt&gt; – ou pressione ⌘S / &lt;tt&gt;C-s&lt;/tt&gt;. Escolha o diretório e salve como &lt;code&gt;ola&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Depois clique em &lt;tt&gt;File&lt;/tt&gt; → &lt;tt&gt;Generate Scheme File…&lt;/tt&gt; – ⌘F5 no Mac. Salve como &lt;code&gt;ola.ss&lt;/code&gt; no mesmo diretório onde você salvou o projeto.&lt;br /&gt;&lt;br /&gt;Repare que você terá dois arquivos: &lt;code&gt;ola.*.med&lt;/code&gt; (o projeto) e &lt;code&gt;ola.ss&lt;/code&gt; (o código).&lt;br /&gt;&lt;br /&gt;Abra agora o arquivo &lt;code&gt;ola.ss&lt;/code&gt; no DrRacket:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;drracket ola.ss&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Procure a seguinte linha:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(button-&lt;em&gt;XXXX&lt;/em&gt;-callback (lambda (button control-event) (void))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Onde &lt;code&gt;&lt;em&gt;XXXX&lt;/em&gt;&lt;/code&gt; é uma sequência de dígitos decimais.&lt;br /&gt;&lt;br /&gt;Mude para:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(button-&lt;em&gt;XXXX&lt;/em&gt;-callback (lambda (button control-event) (displayln "Olá Mundo!"))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Veja a linha 8 do &lt;em&gt;script&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;;;; Call (project-&lt;em&gt;XXX&lt;/em&gt;-init) with optional arguments to this module&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Acrescente a linha sugerida ao final do arquivo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(project-&lt;em&gt;XXX&lt;/em&gt;-init)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Salve o arquivo – ⌘S / &lt;tt&gt;C-s&lt;/tt&gt; – depois rode/corra o programa – ⌘T / &lt;tt&gt;C-t&lt;/tt&gt; – e veja a mágica.&lt;br /&gt;&lt;br /&gt;Para executar o &lt;em&gt;script&lt;/em&gt; sem precisar levantar o DrRacket, use o comando:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;gracket ola.ss&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Se preferir tornar o &lt;em&gt;script&lt;/em&gt; executável, acrescente a primeira linha:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#!/usr/bin/env gracket&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Outros recursos&lt;/h3&gt;&lt;br /&gt;Você pode encontrar uma série de módulos interessantes no &lt;a href="http://planet.racket-lang.org/"&gt;PLaneT&lt;/a&gt;, como facilidades &lt;em&gt;web&lt;/em&gt;, conexão a banco de dados, &lt;code&gt;bzlib&lt;/code&gt;, Plan9, JSON, etc.&lt;br /&gt;&lt;br /&gt;Sobre construção de aplicações &lt;em&gt;web&lt;/em&gt;, leia &lt;a href="http://docs.racket-lang.org/continue/"&gt;Continue: Web Applications in Racket&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-5444877383348468882?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/5444877383348468882/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=5444877383348468882' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5444877383348468882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5444877383348468882'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2011/10/racket.html' title='Racket'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-8lF7wwUkFmQ/Tpx4nLMrg8I/AAAAAAAAAcE/x-8o5hkGBHE/s72-c/racket.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-491628860766930934</id><published>2011-10-15T09:22:00.003-03:00</published><updated>2011-10-15T09:26:02.789-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><title type='text'>R.I.P. Dennis Ritchie</title><content type='html'>Artigo original nas &lt;a href="http://montegasppa.blogspot.com/2011/10/e-agora-mesmo.html"&gt;Reflexões de Monte Gasppa e Giulia C.&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 100px; height: 125px; border: none;" src="http://3.bp.blogspot.com/-x9TCS45yyeU/Tpl2liNRBhI/AAAAAAAAAb4/K2MGMW1LDO0/s200/dennis-ritchie.jpg" alt="Dennis Ritchie" id="BLOGGER_PHOTO_ID_5663688393604793874" /&gt; No mesmo mês em que morreu &lt;a href="http://montegasppa.blogspot.com/2011/10/e-agora.html"&gt;o mago da distorção da realidade&lt;/a&gt;, também nos deixa &lt;a href="http://pt.wikipedia.org/wiki/Dennis_Ritchie"&gt;Dennis Ritchie&lt;/a&gt;, criador das linguagens de programação B (baseada em APL) e &lt;a href="http://pt.wikipedia.org/wiki/Linguagem_de_programa%C3%A7%C3%A3o_C"&gt;C&lt;/a&gt; e cocriador do sistema operacional &lt;a href="http://pt.wikipedia.org/wiki/UNIX"&gt;U&lt;small&gt;NIX&lt;/small&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Se Steve Jobs esteve envolvido direta ou indiretamente com cada avanço tecnológico que não fosse voltado para resolver problemas da própria máquina, salvo raríssimas exceções, Dennis Ritchie foi o criador da linguagem de programação – e dos conceitos envolvidos – usada como base para quase todas as linguagens modernas, além de ter participado ativa e diretamente da criação do sistema operacional que serve de base para todos os sistemas atuais &lt;strong&gt;que funcionam&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;A parte mais triste é ver todo o &lt;em&gt;bafafá&lt;/em&gt; em cima do falecimento de Jobs, mas nada se fala de Ritchie, tão importante quanto. Ou pior… vi programadores que &lt;strong&gt;não sabem&lt;/strong&gt; quem foi Dennis Ritchie!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://twitter.com/#!/MonteGasppa/status/124791574021423104"&gt;Como eu disse&lt;/a&gt;, um programador que não conheça Dennis Ritchie, &lt;a href="http://pt.wikipedia.org/wiki/Edsger_Dijkstra"&gt;Dijkstra&lt;/a&gt; e &lt;a href="http://pt.wikipedia.org/wiki/Donald_Knuth"&gt;Knuth&lt;/a&gt; precisa mudar de profissão ou tomar muita porrada.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-491628860766930934?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/491628860766930934/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=491628860766930934' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/491628860766930934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/491628860766930934'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2011/10/rip-dennis-ritchie.html' title='R.I.P. Dennis Ritchie'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-x9TCS45yyeU/Tpl2liNRBhI/AAAAAAAAAb4/K2MGMW1LDO0/s72-c/dennis-ritchie.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-7329846713837700451</id><published>2011-09-14T22:52:00.014-03:00</published><updated>2011-09-15T08:32:55.293-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Falsa indução ou a falácia da metodologia infalível</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 55px; height: 55px; border: none;" src="http://2.bp.blogspot.com/_rGfO7DAuOSE/SwSZGIY_eXI/AAAAAAAAATA/Gh-qDqdTMX0/s200/glider.png" alt="Glider" /&gt; Reza a lenda que um código bem testado é um código sem &lt;em&gt;bugs&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Além de não acreditar em código sem &lt;em&gt;bugs&lt;/em&gt;, ainda há um problema com a definição de «bem testado».&lt;br /&gt;&lt;br /&gt;Hoje em dia os evangelistas das novas &lt;del&gt;velhas&lt;/del&gt; metodologias de programação defendem que a experiência profissional seja secundária – quiçá irrelevante – caso as metodologias &lt;em&gt;agile&lt;/em&gt; sejam corretamente aplicadas, e uma das regras de outro é &lt;strong&gt;entupir&lt;/strong&gt; o código de testes.&lt;br /&gt;&lt;br /&gt;Porém &lt;strong&gt;quantidade não é qualidade&lt;/strong&gt;. Não adianta encher o código de testes se você não tem &lt;em&gt;feeling&lt;/em&gt; sobre o que testar – e &lt;em&gt;feeling&lt;/em&gt; só se adquire com &lt;strong&gt;experiência profissional&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Há uma série de armadilhas prontas para pegar os incautos que se creem blindados pelas metodologias.&lt;br /&gt;&lt;br /&gt;Uma armadilha comum é a &lt;a href="http://www.daemon.com.br/wiki/index.php?title=Fal%C3%A1cias#Generaliza.C3.A7.C3.A3o_apressada_.28falsa_indu.C3.A7.C3.A3o.29"&gt;falsa indução&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Por exemplo, tenho um código que calcula a raiz quadrada e trinta testes para ele, todos passando:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;nosetests&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;..............................&lt;/em&gt;&lt;br /&gt;&lt;em&gt;----------------------------------------------------------------------&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Ran 30 tests in 0.013s&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;OK&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;No entanto, quando eu tento alguns valores:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;python&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) &lt;/em&gt;&lt;br /&gt;&lt;em&gt;[GCC 4.2.1 (Apple Inc. build 5646)] on darwin&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Type "help", "copyright", "credits" or "license" for more information.&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;from sqr import sqr&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;sqr(16) # 4&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;7&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;sqr(25) # 5&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;7&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;sqr(144) # 12&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;45&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;sqr(225) # 15&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;27&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;sqr(256) # 16&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;58&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Valores completamente loucos! Isso porque o código caiu em uma falsa indução:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;# coding: UTF-8&lt;br /&gt;&lt;br /&gt;from math import ceil&lt;br /&gt;&lt;br /&gt;__all__ = ['sqr']&lt;br /&gt;&lt;br /&gt;def sqr(num):&lt;br /&gt;    d = 10 ** int(ceil(len(str(num)) / 2.))&lt;br /&gt;    return (num % d) + (num // d)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;É claro que uma boa metodologia, como &lt;a href="http://pt.wikipedia.org/wiki/Test_Driven_Development"&gt;TDD&lt;/a&gt;, é um &lt;strong&gt;ferramenta poderosíssima&lt;/strong&gt; nas mãos de um programador experiente, mas pode se tornar uma arma de autodestruição nas mãos de um novato com excesso de confiança.&lt;br /&gt;&lt;br /&gt;Então repito o conselho de um autor que escreveu, mais ou menos isto: não aprenda a programar em dez horas ou em dez dias; aprenda a programar em &lt;strong&gt;dez anos&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;[]’jn&lt;br /&gt;Cacilhας, La Batalema&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;PS: Você pode baixar os testes de &lt;a href="http://cacilhas.info/falsa-inducao/tests.py"&gt;http://cacilhas.info/falsa-inducao/tests.py&lt;/a&gt;. Repare que se substituir:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;from sqr import sqr&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;por:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;from math import sqrt as sqr&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;os testes continuam passando.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-7329846713837700451?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/7329846713837700451/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=7329846713837700451' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/7329846713837700451'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/7329846713837700451'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2011/09/falsa-inducao.html' title='Falsa indução ou a falácia da metodologia infalível'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_rGfO7DAuOSE/SwSZGIY_eXI/AAAAAAAAATA/Gh-qDqdTMX0/s72-c/glider.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-5869984045162648836</id><published>2011-07-12T13:06:00.004-03:00</published><updated>2011-07-12T23:50:22.030-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Declarativa'/><title type='text'>Prolog</title><content type='html'>Certamente &lt;a href="http://pt.wikipedia.org/wiki/Prolog"&gt;Prolog&lt;/a&gt; não é meu forte… nunca fiz nada útil em Prolog e não conheço a linguagem tanto quanto gostaria, mas já tive meu &lt;em&gt;samadhi&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Prolog é uma linguagem de programação &lt;a href="http://pt.wikipedia.org/wiki/Programação_declarativa"&gt;declarativa&lt;/a&gt; de propósito geral, voltada para &lt;a href="http://pt.wikipedia.org/wiki/Inteligência_artificial"&gt;inteligência artificial&lt;/a&gt; e &lt;a href="http://pt.wikipedia.org/wiki/Lingüística_computacional"&gt;linguística computacional&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Seu nome significa &lt;em&gt;&lt;strong&gt;pro&lt;/strong&gt;grammation en &lt;strong&gt;log&lt;/strong&gt;ique&lt;/em&gt; e foi criada no começo da década de 1970 por um grupo liderado por &lt;a href="http://pt.wikipedia.org/wiki/Alain_Colmerauer"&gt;Alain Colmerauer&lt;/a&gt; em Marseille, França.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Predicados e domínio&lt;/h3&gt;&lt;br /&gt;A programação Prolog consiste em definir um conjunto de verdades chamadas &lt;strong&gt;fatos&lt;/strong&gt; e relações entre os fatos, chamadas &lt;strong&gt;regras&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;De um modo geral, fatos e regras são chamados &lt;strong&gt;predicados&lt;/strong&gt; e o conjunto de predicados do programa é chamado &lt;strong&gt;domínio&lt;/strong&gt; do problema.&lt;br /&gt;&lt;br /&gt;Um fato define uma afirmação, uma verdade:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;flor(cravo).&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Esta linha de código está dizendo «cravo é uma flor», e é um predicado do domínio.&lt;br /&gt;&lt;br /&gt;Regra é um predicado condicional:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;gosta(ana, X) :- flor(X).&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ana gosta de &lt;code&gt;X&lt;/code&gt; &lt;strong&gt;se&lt;/strong&gt; &lt;code&gt;X&lt;/code&gt; for uma flor, ou de forma mais precisa: se Ana gosta de &lt;code&gt;X&lt;/code&gt; implica que &lt;code&gt;X&lt;/code&gt; é um flor, ou seja, leia &lt;code&gt;:-&lt;/code&gt; como &lt;strong&gt;implica em&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Lembre-se que implicância é uma operação não recíproca.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Consultas&lt;/h3&gt;&lt;br /&gt;O uso de Prolog se dá através de consultas (&lt;em&gt;queries&lt;/em&gt;). Por exemplo, salve as duas linhas acima no arquivo &lt;code&gt;ana.pro&lt;/code&gt;, execute o &lt;a href="http://www.gprolog.org/"&gt;interpretador&lt;/a&gt; e digite:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;| ?-&lt;/em&gt; &lt;strong&gt;[ana].&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;compiling ~/ana.pro for byte code...&lt;/em&gt;&lt;br /&gt;&lt;em&gt;~/ana.pro compiled, 2 lines read - 419 bytes written, 14 ms&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;(1 ms) yes&lt;/em&gt;&lt;br /&gt;&lt;em&gt;| ?-&lt;/em&gt; &lt;strong&gt;gosta(ana, cravo).&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;yes&lt;/em&gt;&lt;br /&gt;&lt;em&gt;| ?-&lt;/em&gt; &lt;strong&gt;gosta(ana, gato).&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;no&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Tipos&lt;/h3&gt;&lt;br /&gt;Prolog possui quatro tipos: átomo, termo composto, número e lista. Um fato precisa ser um átomo ou um termo composto.&lt;br /&gt;&lt;ul&gt; &lt;li&gt;&lt;strong&gt;Átomo:&lt;/strong&gt; é uma constante. Representado por uma sequência de letras, números e &lt;em&gt;underscore&lt;/em&gt; iniciada por uma letra minúscula ou uma sequência entre plicas. Ex.: &lt;code&gt;cravo&lt;/code&gt;, &lt;code&gt;'ana.pro'&lt;/code&gt;, &lt;code&gt;'Cacilhας, La Batalema'&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Termo composto:&lt;/strong&gt; é uma estrutura complexa. Consiste em um funtor seguido por um ou mais parâmetros entre parêntesis. O funtor deve ser um átomo, os parâmetros podem ser de quaisquer tipos. Ex.: &lt;code&gt;gosta(ana, gato)&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Número:&lt;/strong&gt; exatamente o que diz. É representado por dígitos numéricos e ponto (para ponto flutuante.) Ex.: &lt;code&gt;123&lt;/code&gt;, &lt;code&gt;3.1415&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Lista:&lt;/strong&gt; é uma sequência de elementos de outros tipos. Os delimitadores de início e fim são &lt;code&gt;[]&lt;/code&gt; e os elementos são separados por vírgulas. O símbolo &lt;em&gt;pipe&lt;/em&gt; (&lt;code&gt;|&lt;/code&gt;) por ser usado para representar resto da lista. Ex.: &lt;code&gt;[a, b, c]&lt;/code&gt;, &lt;code&gt;[abc | SX]&lt;/code&gt; (&lt;code&gt;SX&lt;/code&gt; é uma lista).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;&lt;em&gt;String&lt;/em&gt;:&lt;/strong&gt; é um tipo especial de lista que contém apenas números inteiros entre 0 e 255. Ex.: &lt;code&gt;"ABC"&lt;/code&gt; ≡ &lt;code&gt;[65, 66, 67]&lt;/code&gt;.&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Incógnita&lt;/h3&gt;&lt;br /&gt;O equivalente a variável em Prolog é a incógnita, que consiste em um valor desconhecido, porém constante, representado por uma sequência similar ao átomo, mas iniciada por uma letra maiúscula.&lt;br /&gt;&lt;br /&gt;Por exemplo, em:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;gosta(ana, X) :- flor(X).&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;X&lt;/code&gt; é uma incógnita. A solução das consultas feitas acima é obtida encontrando o valor de &lt;code&gt;X&lt;/code&gt;, o que é responsabilidade do programa.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Exemplo&lt;/h3&gt;&lt;br /&gt;Um exemplo clássico de Prolog é a implementação de fatorial:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;factorial(0, 1).&lt;br /&gt;&lt;br /&gt;factorial(N, F) :-&lt;br /&gt;    N &amp;gt; 0,&lt;br /&gt;    N1 is N - 1,&lt;br /&gt;    factorial(N1, F1),&lt;br /&gt;    F is N * F1.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O que o código diz é que o fatorial de 0 é 1 e se o fatorial de &lt;code&gt;N&lt;/code&gt; é &lt;code&gt;F&lt;/code&gt; implica que:&lt;br /&gt;&lt;ul&gt; &lt;li&gt;&lt;code&gt;N&lt;/code&gt; é maior que 0 (já está coberto pelo predicado anterior);&lt;/li&gt; &lt;li&gt;&lt;code&gt;N1&lt;/code&gt; é igual a &lt;code&gt;N&lt;/code&gt; menos 1;&lt;/li&gt; &lt;li&gt;O fatorial de &lt;code&gt;N1&lt;/code&gt; é &lt;code&gt;F1&lt;/code&gt;;&lt;/li&gt; &lt;li&gt;E &lt;code&gt;F&lt;/code&gt; é igual a &lt;code&gt;N&lt;/code&gt; vezes &lt;code&gt;F1&lt;/code&gt;.&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Uso:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;| ?-&lt;/em&gt; &lt;strong&gt;[factorial].&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;compiling ~/factorial.pro for byte code...&lt;/em&gt;&lt;br /&gt;&lt;em&gt;~/factorial.pro compiled, 7 lines read - 941 bytes written, 14 ms&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;(1 ms) yes&lt;/em&gt;&lt;br /&gt;&lt;em&gt;| ?-&lt;/em&gt; &lt;strong&gt;factorial(5, X).&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;X = 120 ?&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;yes&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Um bom exemplo também é a implementação da solução da &lt;a href="http://pt.wikipedia.org/wiki/Torre_de_Hanói"&gt;torre de Hanói&lt;/a&gt;, mas vai fritar seu cérebro:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;hanoi(N) :- move(N, esquerda, direita, central).&lt;br /&gt;&lt;br /&gt;move(1, X, Y, _) :-&lt;br /&gt;    write('mova o disco da torre '),&lt;br /&gt;    write(X),&lt;br /&gt;    write(' para a torre '),&lt;br /&gt;    write(Y),&lt;br /&gt;    nl.&lt;br /&gt;&lt;br /&gt;move(N, X, Y, Z) :-&lt;br /&gt;    N &amp;gt; 1,&lt;br /&gt;    M is N - 1,&lt;br /&gt;    move(M, X, Z, Y),&lt;br /&gt;    move(1, X, Y, _),&lt;br /&gt;    move(M, Z, Y, X).&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;É claro que isso não é nem o começo. O objetivo é apenas causar água na boca.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-5869984045162648836?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/5869984045162648836/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=5869984045162648836' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5869984045162648836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5869984045162648836'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2011/07/prolog.html' title='Prolog'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-4456602552291564495</id><published>2011-03-13T23:08:00.010-03:00</published><updated>2011-04-29T22:27:57.547-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lua'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Decoradores em Lua</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 100px; height: 100px; border: none;" src="http://3.bp.blogspot.com/-tF7d2qXCZ4E/TX14xSZS7FI/AAAAAAAAAZs/Toa9yZ7NxL8/s200/at-char.jpg" alt="@" id="BLOGGER_PHOTO_ID_5583751901156142162" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Um recurso extremamente útil em &lt;a href="http://python.org/"&gt;Python&lt;/a&gt; é o uso de decoradores.&lt;br /&gt;&lt;br /&gt;Por exemplo, um decorador que &lt;em&gt;memoíze&lt;/em&gt; o resultado de uma função:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;def memo(func, buffer={}):&lt;br /&gt;    def wrapper(*args):&lt;br /&gt;        if args in buffer:&lt;br /&gt;            response = buffer[args]&lt;br /&gt;        else:&lt;br /&gt;            response = buffer[args] = func(*args)&lt;br /&gt;        return response&lt;br /&gt;&lt;br /&gt;    return wrapper&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Assim funções como o cálculo &lt;a href="http://pt.wikipedia.org/wiki/Recursividade"&gt;recursivo&lt;/a&gt; da &lt;a href="http://pt.wikipedia.org/wiki/N%C3%BAmero_de_Fibonacci"&gt;sequência de Fibonacci&lt;/a&gt; se tornam menos custosas:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;@memo&lt;br /&gt;def fibonacci(n):&lt;br /&gt;    if n &amp;lt; 2:&lt;br /&gt;        return 1&lt;br /&gt;    else:&lt;br /&gt;        return fibonacci(n - 2) + fibonacci(n - 1)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Observação: &lt;a href="http://en.wikipedia.org/wiki/Memoization"&gt;&lt;em&gt;memoização&lt;/em&gt;&lt;/a&gt; consome muita memória!&lt;br /&gt;&lt;br /&gt;É possível ver que, em Python, decoradores são extremamente fáceis de se implementar e usar, o que permite usos bastantes complexos, como a &lt;a href="http://pt.wikipedia.org/wiki/Programa%C3%A7%C3%A3o_orientada_a_aspecto"&gt;orientação a aspecto&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://lua.org/"&gt;Lua&lt;/a&gt; também suporta decoradores, mas de uma forma um pouco menos intuitiva, mais complexa e totalmente &lt;em&gt;macetada&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Para a criação de decoradores em Lua, é usada a sobrecarga do operador de concatenação, como sugerido na &lt;a href="http://lua-users.org/wiki/DecoratorsAndDocstrings"&gt;literatura de referência&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Para criarmos então o decorador de &lt;em&gt;memoização&lt;/em&gt;, precisamos de uma &lt;a href="http://www.lua.org/pil/13.html"&gt;metatabela&lt;/a&gt; que sobrecarregue o operador:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;local mt = {&lt;br /&gt;    __concat = function(self, func)&lt;br /&gt;        return function(...)&lt;br /&gt;            local response&lt;br /&gt;            local args = serialize(...)&lt;br /&gt;            if self[args] then&lt;br /&gt;                response = self[args]&lt;br /&gt;            else&lt;br /&gt;                response = func(...)&lt;br /&gt;                self[args] = response&lt;br /&gt;            end&lt;br /&gt;            return response&lt;br /&gt;        end&lt;br /&gt;    end,&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A função &lt;code&gt;serialize()&lt;/code&gt; não existe, então temos de criá-la:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;local function serialize(...)&lt;br /&gt;    local response = ""&lt;br /&gt;    local i, v&lt;br /&gt;    for i, v in ipairs {...} do&lt;br /&gt;        response =&lt;br /&gt;            response .. "[" .. ("%g"):format(i) .. "] = " ..&lt;br /&gt;            ("%g"):format(v) .. ", "&lt;br /&gt;    end&lt;br /&gt;    return response&lt;br /&gt;end&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora criamos o decorador:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;function memo()&lt;br /&gt;    return setmetatable({}, mt)&lt;br /&gt;end&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Isso tudo pode ser colocado em módulo, chamado &lt;code&gt;memo.lua&lt;/code&gt; por exemplo. Na última linha do módulo coloque:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;return memo&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora, para usar o decorador:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;require "memo"&lt;br /&gt;&lt;br /&gt;fibonacci =&lt;br /&gt;    memo() ..&lt;br /&gt;    function(n)&lt;br /&gt;        if n &amp;lt; 2 then&lt;br /&gt;            return 1&lt;br /&gt;        else&lt;br /&gt;            return fibonacci(n - 2) + fibonacci(n - 1)&lt;br /&gt;        end&lt;br /&gt;    end&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O uso do decorador está na linha: &lt;code&gt;memo()&amp;nbsp;..&lt;/code&gt; – a sintaxe não é tão elegante quanto a de Python – &lt;code&gt;@memo&lt;/code&gt; –, mas funciona da mesma forma, inclusive a criação de cadeias de decoradores.&lt;br /&gt;&lt;br /&gt;A criação de decoradores em Lua também não é tão intuitiva e simples quanto em Python, em função da diferença de filosofias entre as duas linguagens, mas com o hábito se torna um recurso poderoso.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-4456602552291564495?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/4456602552291564495/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=4456602552291564495' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/4456602552291564495'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/4456602552291564495'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2011/03/decoradores-em-lua.html' title='Decoradores em Lua'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-tF7d2qXCZ4E/TX14xSZS7FI/AAAAAAAAAZs/Toa9yZ7NxL8/s72-c/at-char.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-4802297753746637876</id><published>2011-02-05T16:15:00.009-03:00</published><updated>2011-02-05T16:28:58.750-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><title type='text'>Álgebra Booleana e falácias</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 55px; height: 55px; border: none;" src="http://2.bp.blogspot.com/_rGfO7DAuOSE/SwSZGIY_eXI/AAAAAAAAATA/Gh-qDqdTMX0/s200/glider.png" alt="Glider" /&gt; Outro dia eu estava conversando com um &lt;a href="http://twitter.com/#!/identica_cesarb"&gt;amigo meu&lt;/a&gt; sobre um problema que nos incomoda bastante, que é o fato das pessoas não conhecerem nem o mínimo de lógica aplicada. Nem mesmo as operações básicas.&lt;br /&gt;&lt;br /&gt;Em função disso as pessoas são enganadas pelas mais triviais das falácias, como acidente, afirmação do consequente, negação do antecedente, &lt;em&gt;Red Herring&lt;/em&gt; e pressuposição aplicada a conjuntos de axiomas.&lt;br /&gt;&lt;br /&gt;Vejo tais falácias chulas nos mais diversos textos, geralmente usados para defender ideias da moda. Pensando nisso, eu e meu amigo decidimos que eu deveria escrever este artigo explicando o básico da &lt;a href="http://pt.wikipedia.org/wiki/Álgebra_booleana"&gt;Álgebra Booleana&lt;/a&gt;, que também é totalmente relevante para programadores.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Pensamento binário&lt;/h3&gt;&lt;br /&gt;A Álgebra Booleana é baseada no concento de verdades: cada proposição é uma afirmação que pode ser verdadeira ou falsa e é representada em sua forma mais simples por uma letra maiúscula.&lt;br /&gt;&lt;br /&gt;Quando uma proposição aparece sozinha, assume-se que ela é verdadeira.&lt;br /&gt;&lt;br /&gt;Por exemplo:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;    A&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Indica que a proposição A é verdadeira.&lt;br /&gt;&lt;br /&gt;O operador ¬ indica negação, então:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;    ¬A&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Indica que a negação da proposição A é verdadeira, ou seja, que a proposição A é falsa.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Operações booleanas&lt;/h3&gt;&lt;br /&gt;Assim como na Álgebra Elementar, a Álgebra Booleana possui operações, chamadas operações lógicas.&lt;br /&gt;&lt;br /&gt;As operações mais conhecidas são: E lógico (∧), OU lógico (∨), OU exclusivo (⊕), implicação (→) e equivalência (↔), além da negação (¬), que já vimos.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;E lógico&lt;/h3&gt;&lt;br /&gt;A operação E lógico relaciona duas proposições e a expressão formada é verdadeira se as duas proposições forem verdadeira, caso contrário é falsa.&lt;br /&gt;&lt;br /&gt;A tabela é:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;+---+---+-----+&lt;br /&gt;| A | B | A∧B |&lt;br /&gt;+---+---+-----+&lt;br /&gt;| V | V |  V  |&lt;br /&gt;| V | F |  F  |&lt;br /&gt;| F | V |  F  |&lt;br /&gt;| F | F |  F  |&lt;br /&gt;+---+---+-----+&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ou seja, a seguinte afirmação:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;    A∧¬B&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Indica que tanto A quanto ¬B são verdadeiros, ou, de modo mais simples, que A é verdadeiro e B é falso.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;OU lógico&lt;/h3&gt;&lt;br /&gt;A operação OU lógico relaciona duas proposições e a expressão resultante é verdadeira se qualquer uma das duas proposições for verdadeira, caso contrário é falsa.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;+---+---+-----+&lt;br /&gt;| A | B | A∨B |&lt;br /&gt;+---+---+-----+&lt;br /&gt;| V | V |  V  |&lt;br /&gt;| V | F |  V  |&lt;br /&gt;| F | V |  V  |&lt;br /&gt;| F | F |  F  |&lt;br /&gt;+---+---+-----+&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Por exemplo:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;    A∨B&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Indica que A é verdadeiro, B é verdadeiro ou ambos são, não permitindo que saibamos qual dos casos, nos obrigando a apelar a outra expressão para descobrir.&lt;br /&gt;&lt;br /&gt;Então:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;    A∨B&lt;br /&gt;    ¬A&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Sabemos então que A não é verdadeiro, restando apenas uma opção para validar a expressão, que é quando B é verdadeiro. Podemos escrever isso da seguinte forma:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;    A∨B&lt;br /&gt;    ¬A&lt;br /&gt;  ├ B&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O sinal ├ significa «cocluímos que…». Então, se A ou B é verdadeiro e A é falso, concluímos que B é verdadeiro.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Falácia do OU lógico&lt;/h3&gt;&lt;br /&gt;Repare na tabela que dizer que um dos elementos é verdadeiro não garante que o outro seja verdadeiro ou falso, ou seja, tanto V∨F quanto V∨V são verdadeiros. Daí concluir:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;    A∨B&lt;br /&gt;    A&lt;br /&gt;  ├ ¬B&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;É um &lt;strong&gt;erro&lt;/strong&gt;!&lt;br /&gt;&lt;br /&gt;Por exemplo, digamos que sabemos que alguém nadou na piscina, pois as bordas estavam molhadas. As suspeitas são Pedro e João. Sabemos que Pedro nadou na piscina, logo deduzimos que João não nadou.&lt;br /&gt;&lt;br /&gt;Ora! O fato de Pedro ter nadado na piscina não significa que João não tenha nadado também.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;OU exclusivo&lt;/h3&gt;&lt;br /&gt;Esta operação é o OU a que estamos mais habituados na linguagem comum. Ou uma proposição é verdadeira, ou outra, mas não as duas:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;+---+---+-----+&lt;br /&gt;| A | B | A⊕B |&lt;br /&gt;+---+---+-----+&lt;br /&gt;| V | V |  F  |&lt;br /&gt;| V | F |  V  |&lt;br /&gt;| F | V |  V  |&lt;br /&gt;| F | F |  F  |&lt;br /&gt;+---+---+-----+&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Geralmente não tem consequências maiores, a menos quando o OU lógico é confundido com o OU exclusivo, como na falácia anterior.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Implicação&lt;/h3&gt;&lt;br /&gt;A implicação é a operação lógica mais explorada pelos maliciosos que pretendem enganar os desavisados.&lt;br /&gt;&lt;br /&gt;Funciona da seguinte forma: se a primeira proposição for verdadeira, a segunda também será, caso contrário nada se sabe da segunda proposição.&lt;br /&gt;&lt;br /&gt;A tabela diz o seguinte:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;+---+---+-----+&lt;br /&gt;| A | B | A→B |&lt;br /&gt;+---+---+-----+&lt;br /&gt;| V | V |  V  |&lt;br /&gt;| V | F |  F  |&lt;br /&gt;| F | V |  V  |&lt;br /&gt;| F | F |  V  |&lt;br /&gt;+---+---+-----+&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Então a conclusões que podemos tirar são:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;    A→B&lt;br /&gt;    A&lt;br /&gt;  ├ B&lt;br /&gt;&lt;br /&gt;    A→B&lt;br /&gt;    ¬B&lt;br /&gt;  ├ ¬A&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Afirmação do consequente&lt;/h3&gt;&lt;br /&gt;É quando se usa a consequência para afirmar o antecedente:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;    A→B&lt;br /&gt;    B&lt;br /&gt;  ├ A&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Veja na tabela que tanto V→V quanto F→V são verdadeiros, assim afirmando o consequente não é possível dizer nada do antecedente. É uma &lt;strong&gt;falácia&lt;/strong&gt;!&lt;br /&gt;&lt;br /&gt;Por exemplo (da &lt;a href="http://pt.wikipedia.org/wiki/Falácia"&gt;Wikipédia&lt;/a&gt;): onde há carros, há poluição. Portanto, se há poluição, deve haver carros.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Negação do antecedente&lt;/h3&gt;&lt;br /&gt;É quando se usa a negação do antecedente para negar a consequência:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;    A→B&lt;br /&gt;    ¬A&lt;br /&gt;  ├ ¬B&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Veja na tabela que tanto F→V quanto F→F são verdadeiros, então se o antecedente for falso, nada se sabe da consequência.&lt;br /&gt;&lt;br /&gt;Por exemplo: se o rio for fundo, é possível que haja crocodilos. Como o rio não é fundo, não deve haver crocodilos.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Equivalência&lt;/h3&gt;&lt;br /&gt;A equivalência diz que as duas proposições são falsas ou que as duas são verdadeiras:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;+---+---+-----+&lt;br /&gt;| A | B | A↔B |&lt;br /&gt;+---+---+-----+&lt;br /&gt;| V | V |  V  |&lt;br /&gt;| V | F |  F  |&lt;br /&gt;| F | V |  F  |&lt;br /&gt;| F | F |  V  |&lt;br /&gt;+---+---+-----+&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Seu perigo é quando a operação de implicação é confundida com ela.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Acidente&lt;/h3&gt;&lt;br /&gt;Acidente consiste em tomar o todo pela parte. Se há religiosos fanáticos, então todo religioso é fanático; ou: se há ateus não fanáticos, então nenhum ateu é fanático. Conclusões &lt;strong&gt;erradas&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;As operações envolvidas são um pouco mais complexas, ∃ (existe) e ∀ (para todo). Não vou entrar nesse mérito, já que foge ao escopo do artigo.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;em&gt;Red Herring&lt;/em&gt;&lt;/h3&gt;&lt;br /&gt;Consiste em distrair o interlocutor com afirmações (geralmente verdadeiras) que não têm relação de consequência com a conclusão.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;    A&lt;br /&gt;    B&lt;br /&gt;    C&lt;br /&gt;    D&lt;br /&gt;  ├ E&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Por exemplo: este prédio sofre muita infiltração devido à grande quantidade de pinturas de paisagem oceânica pelas paredes.&lt;br /&gt;&lt;br /&gt;Costuma ser muito usada em combinação com as falácias de afirmação do consequente e de negação do antecedente, para que o interlocutor se distraia e não as perceba.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Pressuposição de axiomas&lt;/h3&gt;&lt;br /&gt;A pressuposição é a falácia onde uma verdade não comprovada é pressuposta para validar uma consequência:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;    A→B&lt;br /&gt;  ├ B&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Mas geralmente é óbvia demais, então é usada com conjuntos de axiomas.&lt;br /&gt;&lt;br /&gt;Axiomas são afirmações que se intervalidam, garantindo que ou todas são corretas, ou todas são falsas:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;    A→B&lt;br /&gt;    B→C&lt;br /&gt;    C→D&lt;br /&gt;    D→A&lt;br /&gt;  ├ A&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;É interessante lembrar que, ao contrário do que os defensores ferrenhos da onisciência da Ciência Humana dizem, &lt;strong&gt;o conhecimento científico oficial é baseado mais em conjuntos de axiomas&lt;/strong&gt; – e até alguns postulados – do que em observação e prática.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;--&lt;/h3&gt;&lt;br /&gt;Fica então a dica: não se deixe enganar por falácias!&lt;br /&gt;&lt;br /&gt;Você pode encontrar mais sobre falácias na &lt;a href="http://pt.wikipedia.org/wiki/Falácia"&gt;Wikipédia&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;E a &lt;a href="http://pt.wikipedia.org/wiki/Álgebra_booleana"&gt;Álgebra Booleana&lt;/a&gt; é amplamente utilizada na programação.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-4802297753746637876?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/4802297753746637876/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=4802297753746637876' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/4802297753746637876'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/4802297753746637876'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2011/02/algebra-booleana-e-falacias.html' title='Álgebra Booleana e falácias'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_rGfO7DAuOSE/SwSZGIY_eXI/AAAAAAAAATA/Gh-qDqdTMX0/s72-c/glider.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-3894813106601393690</id><published>2010-11-27T19:01:00.015-03:00</published><updated>2010-11-27T19:15:41.251-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WSGI'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Flask</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair;width: 100px; height: 89px; border: none;" src="http://1.bp.blogspot.com/_rGfO7DAuOSE/TPGAgdCYpJI/AAAAAAAAAX8/dQxFXjFw58Q/s200/flask.jpg" alt="Flask" id="BLOGGER_PHOTO_ID_5544353911308592274" /&gt; Há diversos &lt;em&gt;frameworks&lt;/em&gt; em &lt;a href="http://python.org/"&gt;Python&lt;/a&gt; para Web, &lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt;, &lt;a href="http://zope2.zope.org/"&gt;Zope&lt;/a&gt;, &lt;a href="http://web2py.com/"&gt;web2py&lt;/a&gt;, &lt;a href="http://wiki.python.org/moin/PythonWebsitePyramidDocs"&gt;Pyramid&lt;/a&gt; e &lt;a href="http://turbogears.org/"&gt;TurboGears&lt;/a&gt; e &lt;a href="http://pylonshq.com/"&gt;Pylons&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Venho aqui para falar de um &lt;em&gt;microframework&lt;/em&gt; chamado &lt;a href="http://flask.pocoo.org/"&gt;Flask&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Simples, flexível e poderoso, é capaz de manter desde o projeto mais simples até CMS no estilo Django ou grandes aplicações como em Pylons.&lt;br /&gt;&lt;br /&gt;A instalação é também extremamente simples, já que se encontra no &lt;a href="http://pypi.python.org/pypi"&gt;PyPI&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;easy_install Flask&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Como exemplo vou mostrar uma aplicação ao estilo Flask, registrando as URLs com decorador &lt;code&gt;route&lt;/code&gt;, mas para aplicações mais complexas sugiro criar um arquivo &lt;code&gt;url_rules.py&lt;/code&gt; que importe o objeto aplicação e use o método &lt;code&gt;add_url_rule&lt;/code&gt; em vez do decorador.&lt;br /&gt;&lt;br /&gt;Nossa aplicação simples exibirá o conteúdo dos arquivos em &lt;code&gt;/proc/&lt;/code&gt; dos sistemas Unix (por falta de ideia melhor).&lt;br /&gt;&lt;br /&gt;Podemos começar importanto os recursos necessários:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;from flask import Flask, make_response&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt; &lt;li&gt;&lt;code&gt;Flask&lt;/code&gt;: classe da aplicação&lt;/li&gt; &lt;li&gt;&lt;code&gt;make_response&lt;/code&gt;: função capaz de criar um objeto de resposta HTTP&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Para a leitura dos arquivos e diretórios vamos precisar do módulo &lt;code&gt;os&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;import os&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Vamos agora criar duas funções, uma que retorne a listagem de arquivos para um diretório e outra que retorne o conteúdo de um arquivo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;def list_dir(path):&lt;br /&gt;    filelist = os.listdir(path)&lt;br /&gt;    filelist.sort()&lt;br /&gt;    return '\n'.join(filelist)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;def read_file(path):&lt;br /&gt;    data = 'NO DATA'&lt;br /&gt;    with open(path, 'r') as fd:&lt;br /&gt;        data = fd.read()&lt;br /&gt;    return data&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora é possível criar a aplicação:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;app = Flask(__name__)&lt;br /&gt;app.debug = True&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Podemos então criar uma função que receba o caminho do arquivo/diretório a ser lido e retorne para o navegador.&lt;br /&gt;&lt;br /&gt;Caso seja necessário editar os cabeçalhos ou lidar com qualquer peculiaridade do objeto de resposta HTTP, é possível instanciá-lo manualmente. Caso contrário, retornar uma simples &lt;em&gt;string&lt;/em&gt; já faz com que ela seja entendida como o conteúdo do objeto.&lt;br /&gt;&lt;br /&gt;Se uma tupla for retornada, o primeiro valor será o conteúdo e o segundo o &lt;em&gt;status&lt;/em&gt; de retorno.&lt;br /&gt;&lt;br /&gt;Sabendo disso, podemos definir a função:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;@app.route('/&amp;lt;path:filename&amp;gt;/')&lt;br /&gt;def read_proc(filename):&lt;br /&gt;    real_path = os.path.join('/proc', filename)&lt;br /&gt;    data = 'NO DATA'&lt;br /&gt;&lt;br /&gt;    try:&lt;br /&gt;        if os.path.isfile(real_path):&lt;br /&gt;            data = read_file(real_path)&lt;br /&gt;&lt;br /&gt;        elif os.path.isdir(real_path):&lt;br /&gt;            data = list_dir(real_path)&lt;br /&gt;&lt;br /&gt;        else:&lt;br /&gt;            return 'NOT FOUND', 404&lt;br /&gt;&lt;br /&gt;        # Criando HTTP response apenas para editar headers&lt;br /&gt;        response = make_response(data)&lt;br /&gt;        response.headers['Content-Type'] = 'text/plain'&lt;br /&gt;        return response&lt;br /&gt;&lt;br /&gt;    except IOError:&lt;br /&gt;        # Você não pode ler este arquivo/diretório!&lt;br /&gt;        return 'BAD REQUEST', 400&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A rota indica que o argumento &lt;em&gt;filename&lt;/em&gt; receberá como parâmetro toda a URL passada (&lt;code&gt;path:&lt;/code&gt; indica uma &lt;em&gt;string&lt;/em&gt; com &lt;code&gt;/&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;Para a raiz da aplicação, poderíamos usar as funções &lt;code&gt;redirect&lt;/code&gt; e &lt;code&gt;url_for&lt;/code&gt;, por exemplo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;@app.route('/')&lt;br /&gt;def index():&lt;br /&gt;    return redirect(url_for('read_proc', filename='cpuinfo'))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O que redirecionaria para a URL referente à função &lt;code&gt;read_proc&lt;/code&gt;, passando &lt;code&gt;'cpuinfo'&lt;/code&gt; como parâmetro, mas faz mais sentido retornar o resultado da função:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;@app.route('/')&lt;br /&gt;def index():&lt;br /&gt;    return read_proc('')&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora só falta colocar a aplicação para rodar:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;if __name__ == '__main__':&lt;br /&gt;    app.run(host='0.0.0.0')&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Execute o &lt;em&gt;script&lt;/em&gt; e acesse no navegador: &lt;a href="http://localhost:5000/"&gt;http://localhost:5000/&lt;/a&gt; – você verá a listagem do diretório &lt;code&gt;/proc/&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Acesse no navegador: &lt;a href="http://localhost:5000/cpuinfo/"&gt;http://localhost:5000/cpuinfo/&lt;/a&gt; e você verá o conteúdo do arquivo &lt;code&gt;/proc/cpuinfo&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Pretendo em uma próxima oportunidade demonstrar com construir uma estrutura mais complexa usando um arquivo com roteamente em vez de decorador.&lt;br /&gt;&lt;br /&gt;Para mais diversão, leia a &lt;a href="http://flask.pocoo.org/docs/"&gt;documentação&lt;/a&gt; e fascine-se também com a quantidade de vezes que a expressão «&lt;em&gt;you don’t have to deal with that&lt;/em&gt;» se repete.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-3894813106601393690?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/3894813106601393690/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=3894813106601393690' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/3894813106601393690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/3894813106601393690'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/11/flask.html' title='Flask'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_rGfO7DAuOSE/TPGAgdCYpJI/AAAAAAAAAX8/dQxFXjFw58Q/s72-c/flask.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-816372763511882311</id><published>2010-09-02T22:00:00.003-03:00</published><updated>2010-09-02T22:12:12.471-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><title type='text'>Torne-se excelente</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 55px; height: 55px; border: none;" src="http://2.bp.blogspot.com/_rGfO7DAuOSE/SwSZGIY_eXI/AAAAAAAAATA/Gh-qDqdTMX0/s200/glider.png" alt="Glider" /&gt; Este é um &lt;a href="http://gist.github.com/556029"&gt;artigo&lt;/a&gt; que meu amigo &lt;a href="http://twitter.com/argentinomota"&gt;Argentino&lt;/a&gt; me apresentou, do &lt;a href="http://c2.com/cgi/wiki?KlausWuestefeld"&gt;Klaus Wuestefeld&lt;/a&gt;, autor do manifesto da &lt;a href="http://c2.com/cgi/wiki?SovereignComputing"&gt;Computação Soberana&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;O artigo original – ou pelo menos o endereço que me foi apresentado – se encontra no &lt;a href="http://gist.github.com/556029"&gt;GitHub&lt;/a&gt; e aconselho todos a lerem.&lt;br /&gt;&lt;br /&gt;Mas antes, no artigo original os &lt;a href="http://gist.github.com/556029#comments"&gt;comentários&lt;/a&gt; tenderam para discussão sobre a importância do curso superior. &lt;strong&gt;O foco do texto não é esse!&lt;/strong&gt; Não é criticar a faculdade ou sua importância. O foco é mais na prioridade que damos às coisas.&lt;br /&gt;&lt;br /&gt;Em outras palavras: um curso académico é importante, mas possui menor prioridade do que a experiência profissional, ainda mais na Computação, curso que no Brasil ainda não está academicamente bem definido e em muitas faculdades tende a ser regido por interesses empresariais no lugar de pelo conhecimento.&lt;br /&gt;&lt;br /&gt;Segue o artigo:&lt;br /&gt;&lt;blockquote&gt;&lt;h3&gt;Torne-se excelente&lt;/h3&gt;&lt;br /&gt;Seja realmente bom em alguma coisa. Não fique só choramingando ou querendo progredir às custas dos outros. Não pense que, porque você sentou 4 anos numa faculdade ouvindo um professor falar sobre &lt;em&gt;software&lt;/em&gt;, você sabe alguma coisa. Jogador de futebol não aprende a jogar bola tendo aula. Ele pratica. Instrumentistas geniais não aprendem a tocar tendo aula. Eles praticam. Pratique. Chegue em casa depois do trabalho e da aula e pratique. No final de semana, pratique.&lt;br /&gt;&lt;br /&gt;Crie seu próprio vírus, seu proprio jogo, seu proprio SO, seu proprio gerenciador de janelas, seu proprio &lt;em&gt;webserver&lt;/em&gt;, sua propria VM, qualquer coisa. Várias coisas.&lt;br /&gt;&lt;br /&gt;Não precisa ser só programação. Pode ser &lt;em&gt;networking&lt;/em&gt;, vendas, etc. Só precisa ser bom mesmo. Tenha paixão pela coisa.&lt;br /&gt;&lt;br /&gt;As melhores práticas do mercado são polinizadas primeiro nos projetos de &lt;em&gt;software&lt;/em&gt; livre. Aprenda com eles.&lt;br /&gt;&lt;br /&gt;Discípulo, Viajante, Mestre: Primeiro seja um discípulo, tenha mestres locais, aprenda alguma coisa com alguem realmente bom, qualquer estilo. Depois viaje, encontre outros mestres e aprenda o estilo deles. Por fim, tenha o seu estilo, tenha discípulos, seja um mestre.&lt;br /&gt;&lt;br /&gt;Vou fazer o curso da Mary Poppendieck em SP semana que vem e quando tiver o curso de Scrumban do Alisson e do Rodrigo quero fazer também.&lt;br /&gt;&lt;br /&gt;«Torne-se excelente» também pode ser chamado de «Melhoria Continua» ou &lt;em&gt;Learning&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Não seja deslumbrado&lt;/h3&gt;&lt;br /&gt;Desenvolvimento de &lt;em&gt;software&lt;/em&gt; é a mesma coisa há 60 anos: modelo imperativo. Há 30 anos: orientação a objetos. Bancos de dados relacionais: 30 anos. («Web», por exemplo, não é uma tecnologia ou um paradigma. É meramente um conjunto de restrições sobre como desenvolver e distribuir seu &lt;em&gt;software&lt;/em&gt;).&lt;br /&gt;&lt;br /&gt;Não corra atras da ultima &lt;em&gt;buzzword&lt;/em&gt; do mercado. Busque a essência, os fundamentos.&lt;br /&gt;&lt;br /&gt;Busque na &lt;a href="http://pt.wikipedia.org/wiki/Página_principal"&gt;Wikipédia&lt;/a&gt; e Grokke: &lt;a href="http://pt.wikipedia.org/wiki/Algoritmo"&gt;determinismo&lt;/a&gt;, &lt;a href="http://pt.wikipedia.org/wiki/Complexidade_computacional"&gt;complexidade de algoritmos &lt;code&gt;O()&lt;/code&gt;&lt;/a&gt;, &lt;a href="http://pt.wikipedia.org/wiki/Máquina_de_Turing"&gt;problema de parada de Turing&lt;/a&gt;. Pronto, pode largar a faculdade. Falando sério.&lt;br /&gt;&lt;br /&gt;Trabalhe com &lt;em&gt;software&lt;/em&gt; livre. Não dê ouvidos a grandes empresas, grandes instituições ou grandes nomes só porque são grandes.&lt;br /&gt;&lt;br /&gt;Você acha que vai aprender mais, ter mais &lt;em&gt;networking&lt;/em&gt; e mais chance de alocação no mercado trabalhando em par comigo no &lt;a href="http://sovereigncomputing.net/wiki/;jsessionid=7FDFAAA2C4D20ADBCA4FF677D03C044E"&gt;Sneer&lt;/a&gt; por um ano, 8h por semana, ou passando 4 anos na faculdade, 20h por semana, pagando sei lá quanto por mês?&lt;br /&gt;&lt;br /&gt;Você acha que vai aprender mais trabalhando em par com o &lt;a href="http://docs.codehaus.org/login.action?os_destination=/display/~bamboo"&gt;Bamboo&lt;/a&gt; 6 meses na linguagem &lt;a href="http://boo.codehaus.org/"&gt;Boo&lt;/a&gt; e na &lt;em&gt;engine&lt;/em&gt; do Unity ou fazendo um ano de pós em «a &lt;em&gt;buzzword&lt;/em&gt; da moda»?&lt;br /&gt;&lt;br /&gt;«Não seja deslumbrado» também é conhecido como &lt;em&gt;Coolness&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Mantenha-se Móvel&lt;/h3&gt;&lt;br /&gt;Com a demanda que temos hoje no mercado, se você é desenvolvedor de &lt;em&gt;software&lt;/em&gt; e não consegue negociar um contrato com uma empresa onde você é pago por hora e pode trabalhar quantas horas quiser com um mínimo de meio período, você precisa rever a sua vida.&lt;br /&gt;&lt;br /&gt;É melhor ter dois empregos de meio período que um de período integral, porque você pode largar um deles a qualquer momento.&lt;br /&gt;&lt;br /&gt;Você nunca vai conseguir nada melhor se não tiver tempo, se não tiver disponibilidade pra pegar algo melhor quando aparecer.&lt;br /&gt;&lt;br /&gt;Você sustenta seus pais e 7 irmãos? Não. Então pare de ser ganancioso e medroso no curto prazo, para de pagar &lt;em&gt;facu&lt;/em&gt;, mestrado, pós, MBA, sei-lá-o-quê e vai aprender e empreender.&lt;br /&gt;&lt;br /&gt;Trabalhe remoto. Não é o mais fácil, mas é perfeitamente possível.&lt;br /&gt;&lt;br /&gt;Não fique reclamando que está trabalhando demais. Aumente seu preço e trabalhe menos.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Emparceire-se Promiscuamente&lt;/h3&gt;&lt;br /&gt;Participe de &lt;em&gt;dojos&lt;/em&gt;, de congressos, de projetos de &lt;em&gt;software&lt;/em&gt; livre. Tenha amigos, colegas, conhecidos. Seja conhecido. Não faça ruído em seis  projetos e doze fóruns. Ajude de verdade em um ou dois projetos de cada vez. Ao longo do tempo, você terá ajudado em varios projetos, trabalhado em várias empresas.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Mentalidade de Abundância&lt;/h3&gt;&lt;br /&gt;Ajude seus amigos sem cobrar (a «camaradagem» do Vinícius). Dê palestras gratuitas. Cursos gratuitos. Participe de projetos de &lt;em&gt;software&lt;/em&gt; livre.&lt;br /&gt;&lt;br /&gt;Pare as vezes uma tarde pra receber um amigo seu e explicar seu projeto. Vá visitar seus amigos nos projetos deles. Viaje com algum amigo seu pra visitar um cliente dele, só pra conversar e fazer companhia.&lt;br /&gt;&lt;br /&gt;Você tem um espaço onde dá cursos? É uma Aspercom, Caelum da vida? Chama os &lt;em&gt;brothers&lt;/em&gt; para dar curso. Porra, bola um modelo em que as pessoas podem se inscrever para cursos variados, pagando um sinal, e mantém tipo uma agenda pré-combinada: «Será numa terça e quinta à noite, avisadas com duas semanas de antecedencia». Se rolar, beleza, se depois de meses não der quórum, devolve o sinal. Pode ser curso de Prevayler, de Kanban, de Scrum, de Lean, de Comp Soberana, de Restfulie, de Cucumber, de Rails, de Teste Automatizado Mega-Avançado, qualquer coisa.&lt;br /&gt;&lt;br /&gt;Chame amigos seus pra dar curso em dupla com você. Divida clientes. Divida projetos, mesmo que não precise de ajuda.&lt;br /&gt;&lt;br /&gt;Dizia o pai de um &lt;em&gt;brother&lt;/em&gt; meu de infância: «Tudo que custa dinheiro é barato».&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Busque modelos de custo zero&lt;/h3&gt;&lt;br /&gt;Trabalhe em coisas que tem custo administrativo/ burocrático/ manutenção zero. Por menos ganho que tragam, depois de prontas, estarão tendo uma relação custo/benefício infinitamente vantajosa.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Ganhe notoriedade&lt;/h3&gt;&lt;br /&gt;Faça coisas massa. Participe de projetos de &lt;em&gt;software&lt;/em&gt; livre. Dê palestras gratuitas. Promova eventos (&lt;em&gt;dojos&lt;/em&gt;, debates, grupos de usuários, etc).&lt;br /&gt;&lt;br /&gt;By Dairton Bassi:&lt;br /&gt;&lt;h3&gt;Não tenha medo!&lt;/h3&gt;&lt;br /&gt;Meta a cara. Arrisque empreender. Arrisque inovar. O que você tem a perder? No máximo um emprego, mas isso pode ser revertido facilmente em um mercado aquecido como o atual. O pior que pode acontecer é não dar certo. Mesmo assim você terá aprendido muito mais do que batendo cartão.&lt;br /&gt;&lt;br /&gt;Saia da zona de conforto. Se o seu trabalho estiver fácil e sob controle, isso significa que ele não está mais agregando para a sua evolução técnica e pessoal. &lt;br /&gt;&lt;br /&gt;Não desperdice a chance de trocar de função se a nova oportunidade for mais desafiadora. Isso fará você crescer tecnicamente e o preparará para desafios maiores ainda. Conhecer pessoas novas é tão importante quanto manter-se em contato com código.&lt;br /&gt;&lt;br /&gt;Não se detenha por insegurança ou pela sensação de despreparo. Como você acha que vai ganhar experiência em alguma coisa se sempre adiá-la?&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-816372763511882311?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/816372763511882311/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=816372763511882311' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/816372763511882311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/816372763511882311'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/09/torne-se-excelente.html' title='Torne-se excelente'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_rGfO7DAuOSE/SwSZGIY_eXI/AAAAAAAAATA/Gh-qDqdTMX0/s72-c/glider.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-8659995407782757183</id><published>2010-08-31T10:24:00.000-03:00</published><updated>2010-08-31T10:25:30.449-03:00</updated><title type='text'>Blogagem Coletiva em repúdio ao AI5 Digital – 31/08</title><content type='html'>&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: crosshair; width: 222px; height: 400px; border: none;" src="http://1.bp.blogspot.com/_rGfO7DAuOSE/THz_4NmafyI/AAAAAAAAAXk/-YTEvrlqtg4/s400/meganao.jpg" alt="AI5 Digital" id="BLOGGER_PHOTO_ID_5511561385183182626" /&gt;&lt;br /&gt;&lt;br /&gt;Veja também no &lt;em&gt;blog&lt;/em&gt; do &lt;a href="http://gutocarvalho.net/wordpress/archives/2153"&gt;gutocarvalho.net&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;&lt;h3&gt;Blogagem Coletiva em repúdio ao AI5 Digital – 31/08&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Amigos, os adoradores do &lt;a href="http://meganao.wordpress.com/o-mega-nao/o-que-combatemos/"&gt;AI5Digital&lt;/a&gt; e da ditadura,  os amantes do vigilantismo, os defensores dos direitos econômicos em detrimento dos direitos civis que formam o &lt;a href="http://entropia.blog.br/2010/04/23/acta-e-o-tripe-do-atraso/"&gt;tripé do atraso&lt;/a&gt;, estão se movimentando para aprovar o famigerado e monstruoso AI5Digital que há muito deveria ter sido fulminado, destruído e acabado.&lt;br /&gt;&lt;br /&gt;A turma do Grande Irmão: Azeredo, Febraban, Fecomercio e outros do mesmo quilate estão fazendo uma força tremenda para nos empurrar o AI5Digital guela abaixo de qualquer forma, vamos aos fatos:&lt;br /&gt;&lt;ol&gt; &lt;li&gt;A mídia continua repetindo o &lt;a href="http://entropia.blog.br/2009/01/10/mantras-da-irracionalidade/"&gt;Mantra da Irracionalidade&lt;/a&gt; contra a Internet&lt;/li&gt; &lt;li&gt;No dia 05/08/10  O Deputado Pinto Itamaraty do PSDB apresentou &lt;a href="http://www.camara.gov.br/internet/sileg/Prop_Detalhe.asp?id=15028"&gt;parecer favorável ao AI5Digital&lt;/a&gt;, ignorando todos os argumentos e movimentos sociais dos últimos três anos.&lt;/li&gt; &lt;li&gt;Seis dias depois aparece uma matéria dizendo que os Deputados buscarão acordo para votar a lei de crimes na Internet.&lt;/li&gt; &lt;li&gt;E agora um evento para lá de esquisito organizado pela revista &lt;a href="http://www.decisionreport.com.br/"&gt;Decision Report&lt;/a&gt;, uma publicação que parece estar à serviço do Azeredo e do vigilantismo, se anuncia para o dia 31/08 com o título oportuno (para o tripé do atraso) de: &lt;a href="http://www.decisionreport.com.br/meeting/CrimesEletronicos/presen%C3%A7a/confirmados.html"&gt;Crimes Eletrônicos – A urgência da lei&lt;/a&gt;. O curioso e que este evento conta com 19 palestrantes para falarem em 2:30h, o que dá um pouco mais de 7 minutos para cada um.&lt;/li&gt; &lt;/ol&gt;&lt;br /&gt;Por estas e por outras que estamos convocando uma blogagem coletiva para o dia 31/08/10, justamente no dia do tal evento à serviço do Azeredo e do AI5digital, vamos fazer uma blogagem coletiva contra o AI5Digital para lembrar a todos que queremos a Internet como um espaço livre e democrático!!!&lt;br /&gt;&lt;br /&gt;Fonte:&lt;br /&gt;&lt;a href="http://meganao.wordpress.com/2010/08/27/blogagem-coletiva-de-repudio-ao-ai5-digital/"&gt;http://meganao.wordpress.com/2010/08/27/blogagem-coletiva-de-repudio-ao-ai5-digital/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Participe do MEGANÃO, acesse agora:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://meganao.wordpress.com/o-mega-nao/quem-esta-participando/"&gt;http://meganao.wordpress.com/o-mega-nao/quem-esta-participando/&lt;/a&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-8659995407782757183?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/8659995407782757183/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=8659995407782757183' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8659995407782757183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8659995407782757183'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/08/blogagem-coletiva-em-repudio-ao-ai5.html' title='Blogagem Coletiva em repúdio ao AI5 Digital – 31/08'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_rGfO7DAuOSE/THz_4NmafyI/AAAAAAAAAXk/-YTEvrlqtg4/s72-c/meganao.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-3250070090748357702</id><published>2010-08-26T22:24:00.018-03:00</published><updated>2011-07-24T13:31:58.636-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='Declarativa'/><category scheme='http://www.blogger.com/atom/ns#' term='Prolog'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='Funcional'/><title type='text'>Paradigmas de programação</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 55px; height: 55px; border: none;" src="http://2.bp.blogspot.com/_rGfO7DAuOSE/SwSZGIY_eXI/AAAAAAAAATA/Gh-qDqdTMX0/s200/glider.png" alt="Glider" /&gt; Muito mais empolgante do que aprender uma nova linguagem de programação é aprender um novo &lt;strong&gt;paradigma de programação&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;A parte mais louca é perceber como o paradigma funciona. Isso acontece de modo intuitivo, muito parecido com como quando se aprende uma língua nova: nada faz sentido no começo, tudo é muito mecânico; de repente um estalo e tudo faz sentido!&lt;br /&gt;&lt;br /&gt;Há muitos paradigmas de programação, &lt;a href="http://kodumaro.blogspot.com/2007/03/conceitos-bsicos-de-programao.html"&gt;já andei falando disso antes&lt;/a&gt;, mas muitos são variações dos mesmos tipos básicos: paradigmas imperativo, funcional e declarativo.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Programação imperativa&lt;/h3&gt;&lt;br /&gt;É o primeiro paradigma com o qual a maioria dos programadores trava contato.&lt;br /&gt;&lt;br /&gt;Na programação imperativa, o programa se parece com uma receita de bolo: uma sequência de ordens, chamadas comandos ou instruções (&lt;em&gt;statements&lt;/em&gt; em inglês), que devem ser executadas.&lt;br /&gt;&lt;br /&gt;A partir desse conceito, derivam diversos paradigmas secundários. O principal é a programação estruturada ou procedimental (&lt;em&gt;procedural&lt;/em&gt; em inglês), onde os comandos são organizados em grupos, chamados funções, que podem ser evocados em momentos diferentes.&lt;br /&gt;&lt;br /&gt;As funções podem receber ou não parâmetros, que alteram seu comportamento, e podem retornar valores. Em algumas linguagens, quando o grupo de comandos não recebe parâmetros nem retorna valores, ele é chamado subrotina.&lt;br /&gt;&lt;br /&gt;Para exemplificar o funcionamento da programação imperativa, vamos implementar &lt;a href="http://pt.wikipedia.org/wiki/Fatorial"&gt;fatorial&lt;/a&gt; em &lt;a href="http://pt.wikipedia.org/wiki/C_(linguagem_de_programação)"&gt;C&lt;/a&gt; – mais simples impossível.&lt;br /&gt;&lt;br /&gt;Para quem não sabe, fatorial consiste em uma função recursiva cuja parada é:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;0! = 1&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E o passo é:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;n! = n * (n - 1)!&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Outra forma de entender é reiterativamente:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;n! = 1 * 1 * 2 * 3 * … * (n - 2) * (n - 1) * n&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Vamos implementar a função reiterativa em C para ilustrar melhor o paradigma:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int factorial(int);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int main(int argc, char **argv) {&lt;br /&gt;    printf("O fatorial de 5 é %d&amp;#92;n", factorial(5));&lt;br /&gt;    return EXIT_SUCCESS;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int factorial(int x) {&lt;br /&gt;    int result = 1;&lt;br /&gt;    int i;&lt;br /&gt;    for (i=1; i&amp;lt;=x; ++i)&lt;br /&gt;        result *= i;&lt;br /&gt;    return result;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Cada comando é uma ordem dada ao sistema: atribua 1 à variável &lt;code&gt;result&lt;/code&gt;; para cada &lt;code&gt;i&lt;/code&gt; de 1 até o valor do argumento &lt;code&gt;x&lt;/code&gt;, multiplique o valor de &lt;code&gt;result&lt;/code&gt; pelo valor de &lt;code&gt;i&lt;/code&gt;; retorne o valor de &lt;code&gt;result&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;São ordens dadas ao sistema.&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update 2011-07-24]&lt;/tt&gt;&lt;br /&gt;Na programação imperativa, é muito comum a manipulação de &lt;strong&gt;alterações de estado&lt;/strong&gt;, daí o uso de &lt;strong&gt;variáveis&lt;/strong&gt; – contentores (ou &lt;em&gt;slots&lt;/em&gt;) que podem sofrer alterações de valor ao longo da existência do processo em execução.&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Orientação a objetos&lt;/h3&gt;&lt;br /&gt;Orientação a objetos não passa de um variante da programação imperativa, mas um variante digno de citação.&lt;br /&gt;&lt;br /&gt;Na orientação a objetos, as ordens não são dadas a um sistema abstrato, mas objetos recebem as ordens e as executam.&lt;br /&gt;&lt;br /&gt;O conceito de objeto é bem genérico: qualquer coisa pode ser um objeto, um número, uma janela na tela, uma coleção…&lt;br /&gt;&lt;br /&gt;Na orientação a objetos as ordens dadas a um objeto são chamadas mensagens e a definição de como o objeto reage a cada mensagem é chamada método.&lt;br /&gt;&lt;br /&gt;O exemplo será a versão recursiva de fatorial implementada em &lt;a href="http://smalltalk.org/"&gt;Smalltalk&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;!Integer methodsFor: 'mathematical functions'!&lt;br /&gt;&lt;br /&gt;    factorial&lt;br /&gt;        self = 0 ifTrue: [↑ 1].&lt;br /&gt;        self &gt; 0 ifTrue: [↑ self * (self - 1) factorial].&lt;br /&gt;        self error: 'Not valid for negative integers'.&lt;br /&gt;    !&lt;br /&gt;!!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Transcript&lt;br /&gt;    show: 'O fatorial de 5 é ';&lt;br /&gt;    show: 5 factorial printString;&lt;br /&gt;    cr.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update 2011-07-16]&lt;/tt&gt;&lt;br /&gt;Atualizei o código em Smalltalk segundo implementação da máquina virtual &lt;a href="http://www.pharo-project.org/home"&gt;Pharo&lt;/a&gt;.&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;O princípio é parecido com o anterior, mas em vez de dar uma ordem ao sistema – calcule o fatorial de 5 –, é dada ao próprio número – número 5, qual seu fatorial?&lt;br /&gt;&lt;br /&gt;Observação: a orientação a objetos pode ser aplicada também à programação funcional.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Programação funcional&lt;/h3&gt;&lt;br /&gt;Enquanto na programação imperativa ordens são dadas ao sistema ou a objetos, no paradigma funcional são definidas funções, como as matemáticas, e o programa nasce da interação entre as funções: o resultado de umas funções é passado como parâmetro para outras.&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update 2011-07-24]&lt;/tt&gt;&lt;br /&gt;Na programação funcional, o estado do sistema tende a ser constante, havendo apenas a troca de informação por parâmetros. Assim é comum que não haja variáveis, mas &lt;strong&gt;incógnitas&lt;/strong&gt; constantes, que não sofrem (ou não devem sofrer) alteração de valor ao longo da execução do programa.&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;O mesmo exemplo, fatorial, em &lt;a href="http://clisp.cons.org/"&gt;Common Lisp&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(defun factorial ((x integer))&lt;br /&gt;    (if (zerop x)&lt;br /&gt;        1&lt;br /&gt;        (* x (factorial (- x 1)))))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(format t "~%O fatorial de 5 é ~A~&amp;amp;" (factorial 5))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O conceito é ligeiramente difente: a função &lt;code&gt;factorial&lt;/code&gt;, que recebe um parâmetro inteiro nomeado &lt;code&gt;x&lt;/code&gt;, é definida como o resultado da função &lt;code&gt;if&lt;/code&gt;; a função &lt;code&gt;if&lt;/code&gt; recebe como primeiro parâmetro o resultado da função &lt;code&gt;zerop&lt;/code&gt;, que é verdadeiro quando &lt;code&gt;x&lt;/code&gt; é igual a zero; o segundo parâmetro de &lt;code&gt;if&lt;/code&gt;, 1, é o resultado caso o primeiro parâmetro seja verdadeiro; o terceiro parâmetro é o resultado caso seja falso; o terceiro parâmetro é o resultado da função de multiplicação. Entendendo até aqui, o resto é autoexplicativo.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update 2011-06-19]&lt;/tt&gt;&lt;br /&gt;&lt;h3&gt;Bônus!&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Fatorial em &lt;a href="http://groups.csail.mit.edu/mac/projects/scheme/"&gt;Scheme&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(define (factorial x)&lt;br /&gt;  (if (zero? x)&lt;br /&gt;    1&lt;br /&gt;    (* x (factorial (- x 1)))))&lt;br /&gt;&lt;br /&gt;(display "O fatorial de 5 é ")&lt;br /&gt;(display (factorial 5))&lt;br /&gt;(newline)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E em &lt;a href="http://erlang.org/"&gt;Erlang&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;-module (fact).&lt;br /&gt;-export([factorial/1]).&lt;br /&gt;&lt;br /&gt;factorial(0) -&amp;gt; 1;&lt;br /&gt;factorial(X) -&amp;gt; X * factorial(X - 1).&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Salve como &lt;code&gt;fact.erl&lt;/code&gt;. No &lt;em&gt;prompt&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;1&amp;gt;&lt;/em&gt; &lt;strong&gt;c("fact.erl").&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;{ok,fact}&lt;/em&gt;&lt;br /&gt;&lt;em&gt;2&amp;gt;&lt;/em&gt; &lt;strong&gt;fact:factorial(5).&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;120&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Programação declarativa&lt;/h3&gt;&lt;br /&gt;Este paradigma é um dos mais complicados para &lt;em&gt;pescar&lt;/em&gt;…&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update 2011-07-24]&lt;/tt&gt;&lt;br /&gt;Na programação declaração o código diz &lt;strong&gt;o que&lt;/strong&gt; o programa deve fazer, &lt;strong&gt;não como&lt;/strong&gt;.&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;O programa consiste em uma lista de declarações de verdades.&lt;br /&gt;&lt;br /&gt;Nos paradigmas anteriores havia variáveis, que sofriam atribuições. Na programação declarativa há incógnitas, que não sofrem atribuições! O valor de cada incógnita é constante e inicialmente desconhecido. O que o programa faz é cruzar as consultas (&lt;em&gt;queries&lt;/em&gt;) com as declarações que formam o conjunto verdade para deduzir o valor das incógnitas.&lt;br /&gt;&lt;br /&gt;O exemplo consiste no fatorial implementado em &lt;a href="http://gprolog.org/"&gt;Prolog&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;factorial(0, 1).&lt;br /&gt;&lt;br /&gt;factorial(N, F) :-&lt;br /&gt;    N &amp;gt; 0,&lt;br /&gt;    N1 is N - 1,&lt;br /&gt;    factorial(N1, F1),&lt;br /&gt;    F is N * F1.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O que este conjunto verdade diz é que o fatorial de 0 é 1 e que o fatorial de &lt;code&gt;N&lt;/code&gt; é &lt;code&gt;F&lt;/code&gt; quando:&lt;br /&gt;&lt;ol&gt; &lt;li&gt;&lt;code&gt;N&lt;/code&gt; é maior que zero;&lt;/li&gt; &lt;li&gt;&lt;code&gt;N1&lt;/code&gt; é &lt;code&gt;N&lt;/code&gt; menos 1;&lt;/li&gt; &lt;li&gt;o fatorial de &lt;code&gt;N1&lt;/code&gt; é &lt;code&gt;F1&lt;/code&gt;;&lt;/li&gt; &lt;li&gt;e &lt;code&gt;F&lt;/code&gt; é igual a &lt;code&gt;N&lt;/code&gt; vezes &lt;code&gt;F1&lt;/code&gt;.&lt;/li&gt; &lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Para a consulta:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;| ?-&lt;/em&gt; &lt;strong&gt;[factorial].&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;fatorial.pro compiled, 7 lines read - 869 bytes written, 7 ms&lt;/em&gt;&lt;br /&gt;&lt;em&gt;(1 ms) yes&lt;/em&gt;&lt;br /&gt;&lt;em&gt;| ?-&lt;/em&gt; &lt;strong&gt;factorial(5, X),&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;write('O fatorial de 5 é '),&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;write(X),&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;nl.&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para entender como funciona, há um &lt;em&gt;applet&lt;/em&gt; em Java em um &lt;a href="http://www.csupomona.edu/~jrfisher/www/prolog_tutorial/2_2.html"&gt;tutorial&lt;/a&gt; que demonstra o chinês. É só encontrar o &lt;em&gt;applet&lt;/em&gt; na página, ir clicando em &lt;em&gt;Step&lt;/em&gt; e ver acontecer.&lt;br /&gt;&lt;br /&gt;&lt;del&gt;A linguagem declarativa da vez é &lt;a href="http://erlang.org/"&gt;Erlang&lt;/a&gt;.&lt;/del&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update 2011-06-19]&lt;/tt&gt;&lt;br /&gt;Na época deste artigo, em vez de estudar Erlang, perguntei por aí e fui informado que Erlang seria uma linguagem declarativa. Agora que tomei vergonha na cara e estudei um pouco, descobri que é uma linguagem funcional, extremamente similar a &lt;a href="http://haskell.org/haskellwiki/Haskell"&gt;Haskell&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Para experimentar Erlang, há o &lt;em&gt;applet&lt;/em&gt; &lt;a href="http://www.tryerlang.org/"&gt;Try Erlang&lt;/a&gt;.&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-3250070090748357702?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/3250070090748357702/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=3250070090748357702' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/3250070090748357702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/3250070090748357702'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/08/paradigmas-de-programacao.html' title='Paradigmas de programação'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_rGfO7DAuOSE/SwSZGIY_eXI/AAAAAAAAATA/Gh-qDqdTMX0/s72-c/glider.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-2729637074210315431</id><published>2010-08-16T22:24:00.004-03:00</published><updated>2010-08-17T09:18:06.414-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><title type='text'>Diversão com ANTLR</title><content type='html'>&lt;a href="http://antlr.org/"&gt;ANTLR&lt;/a&gt; – Another Tool for Language Recognition – é uma ferramenta para construção de analisadores léxico (&lt;em&gt;lexer&lt;/em&gt;) e sintático (&lt;em&gt;parser&lt;/em&gt;) de linguagens formais para JVM.&lt;br /&gt;&lt;br /&gt;A grosso modo, é uma ferramenta para implementação de linguagens de programação.&lt;br /&gt;&lt;br /&gt;E &lt;a href="http://www.antlr.org/works/"&gt;ANTLRWorks&lt;/a&gt; é um IDE gráfico para ANTLR.&lt;br /&gt;&lt;br /&gt;Para entender como funciona ANTLR, vou explicar o &lt;a href="http://www.antlr.org/wiki/display/ANTLR3/Expression+evaluator"&gt;exemplo&lt;/a&gt; do próprio sítio. Então instale o ANTLRWorks e mãos à obra!&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Avaliador de expressões&lt;/h3&gt;&lt;br /&gt;Quando iniciar o ANTLRWorks, crie uma gramática chamada &lt;code&gt;Expr.g&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;O código já vai aparecer com a seguinte linha:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;grammar Expr;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A ideia aqui é criar um interpretador que avalie expressões matemáticas simples, inclusive com variáveis.&lt;br /&gt;&lt;br /&gt;Para suportar variáveis, precisamos de algum lugar para armazenar seus valores. Para isso usamos Java:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;@header {&lt;br /&gt;    import java.util.Map;&lt;br /&gt;    import java.util.HashMap;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@members {&lt;br /&gt;    Map&amp;lt;String, Integer&amp;gt; memory = new HashMap&amp;lt;String, Integer&amp;gt;();&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Isso criará o contentor &lt;code&gt;memory&lt;/code&gt;, que é um mapa de chaves &lt;em&gt;string&lt;/em&gt; e valores inteiros.&lt;br /&gt;&lt;br /&gt;ANTLR funciona definindo regras. Nossa primeira regra é programa (&lt;code&gt;prog&lt;/code&gt;) e precisamos defini-la:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;prog:   stat+;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Então nosso programa é um grupo (&lt;code&gt;+&lt;/code&gt;) de comandos (&lt;code&gt;stat&lt;/code&gt;), o que nos leva à próxima regra.&lt;br /&gt;&lt;br /&gt;Definimos comando como:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;stat:   expr NEWLINE { System.out.println($expr.value); }&lt;br /&gt;    |   ID '=' expr NEWLINE&lt;br /&gt;        { memory.put($ID.text, new Integer($expr.value)); }&lt;br /&gt;    |   NEWLINE&lt;br /&gt;    ;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Calma, vou explicar!&lt;br /&gt;&lt;br /&gt;Um comando pode ser uma expressão (&lt;code&gt;expr&lt;/code&gt;) seguida de uma mudança de linha (&lt;code&gt;NEWLINE&lt;/code&gt;). Neste caso, será impresso na saída padrão (&lt;code&gt;System.out&lt;/code&gt;) o valor da expressão (&lt;code&gt;$expr.value&lt;/code&gt;);&lt;br /&gt;&lt;br /&gt;Um comando também pode ser (&lt;code&gt;|&lt;/code&gt; significa OU) um identificador (&lt;code&gt;ID&lt;/code&gt;) seguido de um sinal de igual (&lt;code&gt;'='&lt;/code&gt;), uma expressão e uma mudança de linha. Neste caso o valor da expressão (&lt;code&gt;$expr.value&lt;/code&gt;) será armazenado no contentor &lt;code&gt;memory&lt;/code&gt; na chave igual ao texto do identificador (&lt;code&gt;$ID.text&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;Um comando ainda pode ser uma mudança de linha, que não fará nada.&lt;br /&gt;&lt;br /&gt;Agora precisamos definir uma série de regras: &lt;code&gt;expr&lt;/code&gt;, &lt;code&gt;NEWLINE&lt;/code&gt; e &lt;code&gt;ID&lt;/code&gt;. Vamos começar por &lt;code&gt;expr&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;expr returns [int value]&lt;br /&gt;    :   e=multExpr { $value = $e.value; }&lt;br /&gt;        (   '+' e=multExpr { $value += $e.value; }&lt;br /&gt;        |   '-' e=multExpr { $value -= $e.value; }&lt;br /&gt;        )*&lt;br /&gt;    ;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Quer dizer que &lt;code&gt;expr&lt;/code&gt; retorna um valor inteiro (&lt;code&gt;int value&lt;/code&gt;) e consiste de uma expressão múltipla (&lt;code&gt;multExpr&lt;/code&gt;) seguido de nenhuma, uma ou mais repetições (&lt;code&gt;*&lt;/code&gt;) do que estiver entre parêntesis. O valor retornado é igual ao valor da expressão múltipla.&lt;br /&gt;&lt;br /&gt;A atribuição &lt;code&gt;e=&lt;/code&gt; é necessária por haver mais de uma ocorrência de &lt;code&gt;multExpr&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Entre parêntesis tempos o sinal de adição (&lt;code&gt;'+'&lt;/code&gt;) seguido de uma &lt;code&gt;multExpr&lt;/code&gt; ou (&lt;code&gt;|&lt;/code&gt;) um sinal de subtração (&lt;code&gt;'-'&lt;/code&gt;) seguido de uma &lt;code&gt;multExpr&lt;/code&gt;. No primeiro caso o valor da &lt;code&gt;multExpr&lt;/code&gt; é adicionado ao valor retornado, no segundo é subtraído.&lt;br /&gt;&lt;br /&gt;A regra &lt;code&gt;multExpr&lt;/code&gt; é definida como:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;multExpr returns [int value]&lt;br /&gt;    :   e=atom { $value = $e.value; } ('*' e=atom { $value *= $e.value; })*&lt;br /&gt;    ;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Uma &lt;code&gt;multExpr&lt;/code&gt; retorna um valor inteiro e consiste de um ou mais atómicos (&lt;code&gt;atom&lt;/code&gt;). Os valores dos atómicos são multiplicados.&lt;br /&gt;&lt;br /&gt;Definindo um atómico:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;atom returns [int value]&lt;br /&gt;    :   INT { $value = Integer.parseInt($INT.text); }&lt;br /&gt;    |   ID&lt;br /&gt;        {&lt;br /&gt;            Integer v = memory.get($ID.text);&lt;br /&gt;            if (v != null) $value = v.intValue();&lt;br /&gt;            else System.err.println("undefined variable " + $ID.text);&lt;br /&gt;        }&lt;br /&gt;    |   '(' expr ')' { $value = $expr.value; }&lt;br /&gt;    ;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Então um atómico pode ser um inteiro (&lt;code&gt;INT&lt;/code&gt;, o valor é o corpo do inteiro: &lt;code&gt;$INT.text&lt;/code&gt;), um identificador (&lt;code&gt;ID&lt;/code&gt;, o valor é o relacionado à chave no contentor &lt;code&gt;memory&lt;/code&gt; – se não existir, gera um erro) ou o resultado de uma expressão (&lt;code&gt;expr&lt;/code&gt;), que deve estar entre parêntesis.&lt;br /&gt;&lt;br /&gt;Falta definir as regras &lt;code&gt;ID&lt;/code&gt;, &lt;code&gt;INT&lt;/code&gt; e &lt;code&gt;NEWLINE&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;ID  :   ('a'..'z'|'A'..'Z')+;&lt;br /&gt;INT :   '0'..'9'+;&lt;br /&gt;NEWLINE:    '\r'? '\n';&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ou seja: identificador é uma sequência de letras, inteiro uma sequência de números e mudança de linha é CRLF ou LF.&lt;br /&gt;&lt;br /&gt;Para finalizar, para ignorar espaços em branco:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;WS  :   (' '|'\t')+ { skip(); };&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Testando&lt;/h3&gt;&lt;br /&gt;Para testar, clique em &lt;code&gt;Debug&lt;/code&gt; e preencha a caixa &lt;code&gt;Text&lt;/code&gt; com:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;x = 1&lt;br /&gt;y = 2&lt;br /&gt;3 * (x + y)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Os parêntesis e a mudança de linha na última linha são importantíssimos!&lt;br /&gt;&lt;br /&gt;Clique &lt;code&gt;Ok&lt;/code&gt; e divirta-se acompanhando o &lt;em&gt;debugger&lt;/em&gt;! Repare que, ao final da execução, vai mostrar &lt;code&gt;9&lt;/code&gt; na aba &lt;code&gt;Output&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-2729637074210315431?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/2729637074210315431/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=2729637074210315431' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/2729637074210315431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/2729637074210315431'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/08/antlr.html' title='Diversão com ANTLR'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-3714419893396756452</id><published>2010-06-09T22:15:00.007-03:00</published><updated>2010-06-10T11:52:42.634-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><title type='text'>Por que as empresas teimam em contratar programadores mercenários?</title><content type='html'>Recentemente li &lt;a href="http://www.paulgraham.com/pypar.html"&gt;The Python Paradox&lt;/a&gt;, de &lt;a href="http://www.paulgraham.com/"&gt;Paul Graham&lt;/a&gt;, e sua tradução &lt;a href="http://www.sounerd.com.br/index.php/component/content/article/191.html"&gt;O Paradoxo Python&lt;/a&gt; no &lt;a href="http://www.sounerd.com.br/"&gt;#!SouNerd&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;O texto faz todo sentido: quem aprende a fazer qualquer coisa por gosto tende a fazer melhor do que quem aprende a fazer por dinheiro. É uma verdade.&lt;br /&gt;&lt;br /&gt;Assim, quem aprende a programar porque gosta de programar tende a programar melhor do que quem aprende para ganhar dinheiro e a grande maioria de quem aprende a programar Java só o faz por dinheiro (claro que há lá suas exceções), enquanto quem aprende linguagens mais exóticas o faz por prazer.&lt;br /&gt;&lt;br /&gt;Então por que as empresas teimam em contratar programadores mercenários?&lt;br /&gt;&lt;br /&gt;Pensando sobre isso e observando a comunidade, pensei em uma resposta…&lt;br /&gt;&lt;br /&gt;Eu vejo três tipos de programadores, como três vértices de um triângulo cromático, e cada um está em uma região dessa área, mais próximo ou distante de cada vértice.&lt;br /&gt;&lt;br /&gt;Esses três tipos são: &lt;strong&gt;amador&lt;/strong&gt;, &lt;strong&gt;mercenário&lt;/strong&gt; e &lt;strong&gt;&lt;em&gt;empolgado&lt;/em&gt;&lt;/strong&gt; (por falta de palavra melhor).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Mercenário&lt;/h3&gt;&lt;br /&gt;O mercenário é aquele que quer dinheiro e lucro é tudo o que o impulsiona. Geralmente não tem escrúpulos e faz tudo o que lhe mandam. Seu mantra é: «Pagando bem, que mal tem?»&lt;br /&gt;&lt;br /&gt;Quem é 100% mercenário geralmente acaba largando a profissão por algo que dê mais dinheiro, mas basta estar um &lt;em&gt;pentelésimo&lt;/em&gt; mais para o centro do triângulo que permanece na profissão.&lt;br /&gt;&lt;br /&gt;Normalmente aprende uma linguagem que dê muitas opções de emprego – e que, por consequência, tenha de competir com muita gente –, como Java, C# ou PHP, e rejeita todas as demais. Quando as trata como inferiores, é apenas para tentar justificar a própria incompetência, resultante da falta de gosto pelo que faz.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Amador&lt;/h3&gt;&lt;br /&gt;O amador é aquele que gosta de verdade do que está fazendo, ele &lt;em&gt;ama&lt;/em&gt; programar, daí &lt;em&gt;amador&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Quem é 100% amador quase sempre se perde aprendendo coisas inúteis e não consegue ganhar dinheiro porque muitas vezes perde o foco do que precisa fazer, distraindo-se com besteiras.&lt;br /&gt;&lt;br /&gt;Normalmente aprende linguagens bem diferentes, que poucos sabem, como Lisp, Smalltalk ou Fortran – talvez LOLCODE –, e não é incomum que aprenda uma penca de linguagens, nesse caso, também os &lt;em&gt;hypes&lt;/em&gt;, como Python e Ruby.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;em&gt;Empolgado&lt;/em&gt;&lt;/h3&gt;&lt;br /&gt;O &lt;em&gt;empolgado&lt;/em&gt; é aquele que vai atrás de algum &lt;em&gt;hype&lt;/em&gt;, linguagem da moda. Há uns anos eram de Java, mas os &lt;em&gt;empolgados&lt;/em&gt; da atualidade querem Python e/ou Ruby.&lt;br /&gt;&lt;br /&gt;Quem é 100% &lt;em&gt;empolgado&lt;/em&gt; sabe tudo que acontece na comunidade, mas quase nada de programação. Conhece todas as metodologias em alta, sabe todos os macetes e &lt;em&gt;design patterns&lt;/em&gt; de sua linguagem que precisa para impressionar os iniciantes, mas não é lá muito eficiente. É tão preocupado com a auto-imagem e o que acontece na comunidade que se esquece que há todo um &lt;em&gt;background&lt;/em&gt; a ser aprendido por trás da Computação.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;**&lt;/h3&gt;&lt;br /&gt;&lt;center&gt;Felizmente (quase) ninguém é 100% alguma coisa.&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;Depois de toda esta dissertação, por que diabos as empresas mais engessadas preferem os mercenários?&lt;br /&gt;&lt;br /&gt;Por causa de seu mantra! Basta pagar o que o mercenário acha muito – o que muitas vezes é quase nada pra empresa – e ele faz qualquer coisa que mandarem, torna-se um cão bem adestrado. Essas empresas não querem eficiência, querem obediência.&lt;br /&gt;&lt;br /&gt;O que as empresas não veem é que esses cães não são tão ágeis quanto os gatos que pulam pelos telhados: aqueles que, apesar de em nenhum extremo, se encontram mais próximos do vértice do amador.&lt;br /&gt;&lt;br /&gt;Na verdade as metodologias ágeis &lt;strong&gt;não&lt;/strong&gt; são práticas de trabalho, mas técnicas sociais para atrair programadores que, apesar de ainda um pouco mercenários, sejam muito mais amadores – ser um pouco &lt;em&gt;empolgado&lt;/em&gt; também ajuda, já que as linguagens &lt;em&gt;hype&lt;/em&gt; facilitam pela grande mobilidade da comunidade. As empresas mais espertas e as &lt;em&gt;start-up&lt;/em&gt; viram isso e usam as metodologias ágeis para criar equipes enxutas e mais eficientes do que qualquer equipe de mercenários jamais conseguirá ser.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-3714419893396756452?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/3714419893396756452/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=3714419893396756452' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/3714419893396756452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/3714419893396756452'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/06/programadores-mercenarios.html' title='Por que as empresas teimam em contratar programadores mercenários?'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-8391171835075288363</id><published>2010-05-28T21:40:00.001-03:00</published><updated>2010-05-28T21:41:29.016-03:00</updated><title type='text'>DISQUS e perda dos comentários</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 100px; height: 100px; border: none;" src="http://3.bp.blogspot.com/_rGfO7DAuOSE/S4a0tjBLPbI/AAAAAAAAAUs/NqzC5P5s5c8/s200/kodumaro.jpg" alt="Twitter" /&gt; Gente,&lt;br /&gt;&lt;br /&gt;Devido a uma proliferação absurda de &lt;em&gt;spams&lt;/em&gt; nos comentários do &lt;a href="http://kodumaro.blogspot.com/"&gt;Kodumaro&lt;/a&gt;, implementei o serviço &lt;a href="http://disqus.com/"&gt;DISQUS&lt;/a&gt; para gerência dos mesmos.&lt;br /&gt;&lt;br /&gt;Infelizmente, parece que &lt;strong&gt;todos&lt;/strong&gt; os comentários antigos se perderam. =(&lt;br /&gt;&lt;br /&gt;Peço desculpas a todos, a implementação foi uma necessidade e a perda dos comentários um efeito colateral indesejado.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-8391171835075288363?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/8391171835075288363/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=8391171835075288363' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8391171835075288363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8391171835075288363'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/05/disqus-e-perda-dos-comentarios.html' title='DISQUS e perda dos comentários'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_rGfO7DAuOSE/S4a0tjBLPbI/AAAAAAAAAUs/NqzC5P5s5c8/s72-c/kodumaro.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-6774449757329279077</id><published>2010-04-22T21:56:00.009-03:00</published><updated>2010-04-26T21:20:26.751-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><title type='text'>Parrot VM</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 100px; height: 135px; border: none;" src="http://1.bp.blogspot.com/_rGfO7DAuOSE/S9Dwab5BGTI/AAAAAAAAAWE/5ez68G-DZOk/s200/parrot.jpg" alt="Parrot" id="BLOGGER_PHOTO_ID_5463130684954581298" /&gt; &lt;a href="http://www.parrot.org/"&gt;Parrot VM&lt;/a&gt; é a máquina virtual criada com base nas linguagens de programação &lt;a href="http://python.org/"&gt;Python&lt;/a&gt; e &lt;a href="http://www.perl.org/"&gt;Perl&lt;/a&gt; que proporciona o ambiente para a criação, a implementação e o uso de linguagens de programa. As linguagens suportadas pela máquina virtual estão listadas na &lt;a href="http://www.parrot.org/languages"&gt;página do projeto&lt;/a&gt;, com destaque para a curiosa e elegante linguagem tutorial &lt;a href="http://trac.parrot.org/parrot/browser/trunk/examples/languages/squaak"&gt;Squaak&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Um dos exemplos de Squaak é &lt;a href="http://trac.parrot.org/parrot/browser/trunk/examples/languages/squaak/examples/factorial.sq"&gt;&lt;code&gt;factorial.sq&lt;/code&gt;&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;# Copyright (C) 2008, Parrot Foundation.&lt;br /&gt;# $Id: factorial.sq 36833 2009-02-17 20:09:26Z allison $&lt;br /&gt;&lt;br /&gt;print("Please enter number: ")&lt;br /&gt;x = read()&lt;br /&gt;&lt;br /&gt;sub factorial(n)&lt;br /&gt;    ## test for &amp;lt; 2 because all numbers are represented by&lt;br /&gt;    ## floating-point numbers, and equality checks on those&lt;br /&gt;    ## do not work (yet?)&lt;br /&gt;    if n &amp;lt; 2 then&lt;br /&gt;        return 1&lt;br /&gt;    else&lt;br /&gt;        return n * factorial(n - 1)&lt;br /&gt;    end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;print("factorial of ", x, " is: ", factorial(x))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Voltando à Parrot VM, ela possui uma linguagem própria, um &lt;em&gt;assembly&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Seguem aqui dois exemplos de seu &lt;em&gt;assembly&lt;/em&gt;. Ambos gravam o que é digitado pelo usuário em um arquivo (&lt;code&gt;test.text&lt;/code&gt;) e depois exibem o conteúdo do arquivo. Simples.&lt;br /&gt;&lt;br /&gt;O objetivo de dois códigos é mostrar como pode ser feita a escrita e leitura em arquivo usando &lt;strong&gt;descritor de arquivo&lt;/strong&gt;, de modo totalmente procedimental (como em C), e usando &lt;strong&gt;manipulador de arquivo&lt;/strong&gt;, lançando mão da &lt;a href="http://pt.wikipedia.org/wiki/Orientação_a_objetos"&gt;orientação a objetos&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Descritor de arquivo (procedimental)&lt;/h3&gt;&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;.sub 'main' :main&lt;br /&gt;    .local string filename&lt;br /&gt;    .local string line&lt;br /&gt;    .local pmc STDIN&lt;br /&gt;    .local pmc fd&lt;br /&gt;&lt;br /&gt;    filename = 'test.text'&lt;br /&gt;    STDIN = getstdin&lt;br /&gt;&lt;br /&gt;    # Writing operation&lt;br /&gt;    fd = open filename, 'w'&lt;br /&gt;    print "&amp;gt; "&lt;br /&gt;    line = readline STDIN&lt;br /&gt;    print fd, line&lt;br /&gt;    close fd&lt;br /&gt;&lt;br /&gt;    # Reading operation&lt;br /&gt;    fd = open filename, 'r'&lt;br /&gt;    line = read fd, 10240&lt;br /&gt;    print line&lt;br /&gt;    close fd&lt;br /&gt;.end&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Manipulador de arquivo (OO)&lt;/h3&gt;&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;.sub 'main' :main&lt;br /&gt;    .local string filename&lt;br /&gt;    .local string line&lt;br /&gt;    .local pmc STDIN&lt;br /&gt;    .local pmc file_handle&lt;br /&gt;&lt;br /&gt;    filename = 'test.text'&lt;br /&gt;    STDIN = getstdin&lt;br /&gt;    file_handle = new 'FileHandle'&lt;br /&gt;&lt;br /&gt;    # Writing operation&lt;br /&gt;    file_handle.'open'(filename, 'w')&lt;br /&gt;    file_handle.'encoding'('utf-8')&lt;br /&gt;    print "&amp;gt; "&lt;br /&gt;    line = readline STDIN&lt;br /&gt;    file_handle.'print'(line)&lt;br /&gt;    file_handle.'close'()&lt;br /&gt;&lt;br /&gt;    # Reading operation&lt;br /&gt;    file_handle.'open'(filename, 'r')&lt;br /&gt;    line = file_handle.'readall'()&lt;br /&gt;    print line&lt;br /&gt;    file_handle.'close'()&lt;br /&gt;.end&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-6774449757329279077?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/6774449757329279077/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=6774449757329279077' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/6774449757329279077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/6774449757329279077'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/04/parrot.html' title='Parrot VM'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_rGfO7DAuOSE/S9Dwab5BGTI/AAAAAAAAAWE/5ez68G-DZOk/s72-c/parrot.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-5117311891861471270</id><published>2010-04-11T09:50:00.009-03:00</published><updated>2010-12-30T00:13:05.633-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><title type='text'>Coleções com Smalltalk</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 100px; height: 74px; border: none;" src="http://1.bp.blogspot.com/_rGfO7DAuOSE/S8EV0SuA38I/AAAAAAAAAVs/XZ9iJFxszMc/s200/balloon_smalltalk.jpg" alt="Smalltalk" /&gt; Dando seguimento a uma &lt;a href="http://kodumaro.blogspot.com/search/label/Smalltalk"&gt;série de artigos&lt;/a&gt; sobre &lt;a href="http://smalltalk.gnu.org/"&gt;GNU Smalltalk&lt;/a&gt;, este artigo demonstra alguns recursos de coleção (&lt;em&gt;arrays&lt;/em&gt; e dicionários).&lt;br /&gt;&lt;br /&gt;A classe base para coleções é &lt;code&gt;Collection&lt;/code&gt;, filha de &lt;code&gt;Iterable&lt;/code&gt;. As demais classes, como &lt;code&gt;Array&lt;/code&gt;, &lt;code&gt;Dictionary&lt;/code&gt;, &lt;code&gt;Bag&lt;/code&gt; e &lt;code&gt;Set&lt;/code&gt;, são herdeiras diretas ou indiretas de &lt;code&gt;Collection&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Para criar um instância vazia de qualquer subclasse de &lt;code&gt;Collection&lt;/code&gt;, você pode usar a mensagem &lt;code&gt;#new&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;code&gt;Array&lt;/code&gt;&lt;/h3&gt;&lt;br /&gt;Há duas sintaxes para instanciação de &lt;code&gt;Array&lt;/code&gt;, uma literal e outra programável.&lt;br /&gt;&lt;br /&gt;A sintaxe literal suporta apenas dados literais: inicia-se com &lt;code&gt;#(&lt;/code&gt;, os elementos são separados por &lt;em&gt;blanks&lt;/em&gt; (espaços, tabulações, mudanças de linha) e é fechado com &lt;code&gt;)&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Por exemplo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#(1 2 3)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A limitação dessa sintaxe é que ela só suporta valores literais, não suporta qualquer forma de código (bloco, variável, construtor, etc…). Portanto, não é recomendável.&lt;br /&gt;&lt;br /&gt;A sintaxe recomendada para criação de &lt;em&gt;array&lt;/em&gt; com código é &lt;code&gt;{}&lt;/code&gt;, pois a sintaxe literal suporta apenas literais. A sintaxe com suporte a código se inicia com &lt;code&gt;{&lt;/code&gt;, os elementos são separados por ponto (&lt;code&gt;.&lt;/code&gt;) seguido de &lt;em&gt;blank&lt;/em&gt; e é fechado por &lt;code&gt;}&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Por exemplo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;| anArray b |&lt;br /&gt;&lt;br /&gt;b := 2.&lt;br /&gt;anArray := {&lt;br /&gt;    1.&lt;br /&gt;    b.&lt;br /&gt;    [3] value.&lt;br /&gt;}.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O principal seletor para leitura de elementos em um &lt;em&gt;array&lt;/em&gt; é &lt;code&gt;#at:ifAbsent:&lt;/code&gt;, que recebe como primeiro parâmetro o índice e como segundo um bloco que retorna o valor em caso se ausência.&lt;br /&gt;&lt;br /&gt;Por exemplo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;anArray at: 2 ifAbsent: [0]&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Retorna o elemento de índice 2 ou, em caso de não existir, retorna zero (&lt;code&gt;[0]&amp;nbsp;value&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;code&gt;Dictionary&lt;/code&gt;&lt;/h3&gt;&lt;br /&gt;Essa classe representa um dicionário ou &lt;em&gt;hash&lt;/em&gt;, ou seja, uma coleção de pares chave-valor.&lt;br /&gt;&lt;br /&gt;Por exemplo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;| aDict |&lt;br /&gt;&lt;br /&gt;aDict := Dictionary from: {&lt;br /&gt;    #a -&amp;gt; 1.&lt;br /&gt;    #b -&amp;gt; 2.&lt;br /&gt;    #c -&amp;gt; 3.&lt;br /&gt;}.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Se usar &lt;a href="http://squeak.org/"&gt;Squeak&lt;/a&gt; ou &lt;a href="http://code.google.com/p/pharo/"&gt;Pharo&lt;/a&gt;, a mensagem de criação é &lt;code&gt;#newFrom:&lt;/code&gt; em vez de &lt;code&gt;#from:&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Também aceita a mensagem &lt;code&gt;#at:ifAbsent:&lt;/code&gt;, que recebe como primeiro parâmetro a chave e como segundo um bloco que retorna o valor em caso de ausência. Ainda responde à mensagem &lt;code&gt;#at:&lt;/code&gt;, que recebe apenas a chave e, em caso de ausência, levanta uma exceção &lt;code&gt;NotFound&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;A mensagem para inserir um novo par é &lt;code&gt;#add:&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;aDict add: (#d -&amp;gt; 4).&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para alterar o valor de uma chave use &lt;code&gt;#at:put:&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;aDict at: #a put: 5.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Também funciona para adicionar novo par.&lt;br /&gt;&lt;br /&gt;Para remover um par pela chave basta usar a mensagem &lt;code&gt;#removeKey:&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;aDict removeKey: #a.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;À mensagem &lt;code&gt;#keys&lt;/code&gt; responde uma lista – uma instância de &lt;code&gt;Set&lt;/code&gt;, de fato – das chaves dos pares, já o seletor &lt;code&gt;#keysAndValuesDo:&lt;/code&gt; executa um bloco para cada par:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;aDict keysAndValuesDo: [ :key :value |&lt;br /&gt;    Transcript&lt;br /&gt;        show: key printString;&lt;br /&gt;        tab;&lt;br /&gt;        show: value printString;&lt;br /&gt;        cr.&lt;br /&gt;].&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;code&gt;Set&lt;/code&gt;&lt;/h3&gt;&lt;br /&gt;&lt;code&gt;Set&lt;/code&gt; é um &lt;em&gt;array&lt;/em&gt; onde cada elemento é único, ou seja, não se repete. Para criar uma instância de &lt;code&gt;Set&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;| aSet |&lt;br /&gt;&lt;br /&gt;aSet := #(1 2 3 4 5) asSet.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para remover um elemento, use a mensagem &lt;code&gt;#remove:&lt;/code&gt; e para adicionar &lt;code&gt;#add:&lt;/code&gt;. Se o elemento adicionado já existir, nada acontece.&lt;br /&gt;&lt;br /&gt;Para listar o conteúdo há a mensagem &lt;code&gt;#do:&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;aSet do: [ :e |&lt;br /&gt;    Transcript show: e printString; cr.&lt;br /&gt;].&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;code&gt;Bag&lt;/code&gt;&lt;/h3&gt;&lt;br /&gt;&lt;code&gt;Bag&lt;/code&gt; é exatamente o que o nome diz: um saco de elementos. Você pode ir jogando o que quiser lá dentro e os elementos vão sendo armazenados desordenadamente.&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;| aBag |&lt;br /&gt;&lt;br /&gt;aBag := #(1 2 3 4 5) asBag.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Os principais seletores são &lt;code&gt;#add:&lt;/code&gt;, &lt;code&gt;#remove:&lt;/code&gt; e &lt;code&gt;#do:&lt;/code&gt;, que funcionam de modo similar aos seletores de &lt;code&gt;Set&lt;/code&gt;, mas permite duplicação de elementos.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conclusão&lt;/h3&gt;&lt;br /&gt;Há uma série de outras classes filhas de &lt;code&gt;Collection&lt;/code&gt;, como &lt;code&gt;OrderedCollection&lt;/code&gt;, &lt;code&gt;SortedCollection&lt;/code&gt; e &lt;code&gt;LinkedList&lt;/code&gt;, e muitos outros seletores úteis.&lt;br /&gt;&lt;br /&gt;Para mais informações, execute &lt;code&gt;gst-blox&lt;/code&gt;, acesse &lt;code&gt;Smalltalk&lt;/code&gt;→&lt;code&gt;Class Hierarchy Browser&lt;/code&gt;. Na nova janela, clique em &lt;code&gt;Class&lt;/code&gt;→&lt;code&gt;Search&lt;/code&gt; e faça uma busca por &lt;code&gt;Collection&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;De classe em classe, navegue pelos métodos e veja como cada classe responde a cada mensagem.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;small&gt;PS: Referência: &lt;a href="http://www.jmcsweeney.co.uk/computing/m206/collections_intro.php"&gt;M206 Computing: An Object-oriented Approach&lt;/a&gt;&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-5117311891861471270?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/5117311891861471270/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=5117311891861471270' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5117311891861471270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5117311891861471270'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/04/colecoes-com-smalltalk.html' title='Coleções com Smalltalk'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_rGfO7DAuOSE/S8EV0SuA38I/AAAAAAAAAVs/XZ9iJFxszMc/s72-c/balloon_smalltalk.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-8757989863909827719</id><published>2010-04-04T15:51:00.004-03:00</published><updated>2010-04-10T21:22:29.469-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Smalltalk'/><title type='text'>Quem ama BLOXeia!</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 100px; height: 74px; border: none;" src="http://1.bp.blogspot.com/_rGfO7DAuOSE/S8EV0SuA38I/AAAAAAAAAVs/XZ9iJFxszMc/s200/balloon_smalltalk.jpg" alt="Smalltalk" id="BLOGGER_PHOTO_ID_5455995033140168946" /&gt; &lt;a href="http://smalltalk.gnu.org/"&gt;GNU Smalltalk&lt;/a&gt; é a implementação &lt;a href="http://smalltalk.org/"&gt;Smalltalk&lt;/a&gt; da &lt;a href="http://www.fsf.org/"&gt;Free Software Foundation&lt;/a&gt; para o sistema operacional &lt;a href="http://www.gnu.org/"&gt;GNU&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Para interface gráfica, ele oferece o módulo &lt;a href="http://www.gnu.org/software/smalltalk/manual/html_node/Blox.html"&gt;BLOX&lt;/a&gt;. Sua IDE pode ser iniciada pelo comando:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;gst-blox&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Caso queira navegar pelas classes de sua própria imagem – &lt;code&gt;dev.im&lt;/code&gt; por exemplo –, use:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;gst-blox -I dev.im&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Este artigo apresentará um exemplo extremamente simples de uso programático do BLOX para criar interface gráfica com o usuário, baseado no código encontrado no &lt;a href="http://smalltalk.gnu.org/wiki/graphical-user-interfaces"&gt;tutorial&lt;/a&gt; oficial.&lt;br /&gt;&lt;br /&gt;Primeiro vamos criar a imagem contendo o módulo BLOX:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;gst-load -iI blox-sample.im Blox&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Crie um arquivo fonte &lt;code&gt;blox-sample.st&lt;/code&gt; onde vamos trabalhar.&lt;br /&gt;&lt;br /&gt;Declare as variáveis que usaremos:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;| win con lab bt |&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora crie a janela principal com o título &lt;code&gt;Example&lt;/code&gt; e seu &lt;em&gt;container&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;" Main window "&lt;br /&gt;win := BLOX.BWindow new: 'Example'.&lt;br /&gt;con := BLOX.BContainer new: win.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para definar as dimensões da janela e a &lt;em&gt;callback&lt;/em&gt; do botão de fechamento:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;" Main window's geometry and close button "&lt;br /&gt;win&lt;br /&gt;    width: 200 height: 50;&lt;br /&gt;&lt;br /&gt;    callback: [&lt;br /&gt;        BLOX.Blox terminateMainLoop.&lt;br /&gt;        true.&lt;br /&gt;    ] message: #value.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A &lt;em&gt;callback&lt;/em&gt; encerrará o ciclo principal. &lt;em&gt;Callbacks&lt;/em&gt; de janelas precisam ter a última saída &lt;code&gt;true&lt;/code&gt; (quando a janela deve ser fechada) ou &lt;code&gt;false&lt;/code&gt; (quando a janela não deve ser fechada).&lt;br /&gt;&lt;br /&gt;Podemos então configurar a geometria padrão para &lt;em&gt;widgets&lt;/em&gt; filhos:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;" Geometry management "&lt;br /&gt;con&lt;br /&gt;    setVerticalLayout: true;&lt;br /&gt;    defaultHeight: 50;&lt;br /&gt;    defaultWidth: 200.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora, para criar um rótulo (&lt;em&gt;label&lt;/em&gt;) e um botão:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;lab := BLOX.BLabel new: con label: 'Waiting...'.&lt;br /&gt;bt := BLOX.BButton new: con label: 'Click me'.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O rótulo exibirá seu texto centralizado, com fundo azul e cor de texto branco:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;" Label setup "&lt;br /&gt;lab&lt;br /&gt;    alignment: #TopCenter;&lt;br /&gt;    backgroundColor: #blue;&lt;br /&gt;    foregroundColor: #white.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A &lt;em&gt;callback&lt;/em&gt; que responde ao evento clique no botão:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;" Button callback "&lt;br /&gt;bt&lt;br /&gt;    callback: [&lt;br /&gt;        lab label: 'HELLO WORLD!'.&lt;br /&gt;    ] message: #value.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para exibir a janela:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;" Show window "&lt;br /&gt;win map.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Por último devemos iniciar o ciclo principal (&lt;em&gt;mainloop&lt;/em&gt;):&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;" Start mainloop "&lt;br /&gt;BLOX.Blox dispatchEvents: win.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Se quiser, é possível exibir uma mensagem indicando o fim do programa:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;Transcript&lt;br /&gt;    show: 'Finished';&lt;br /&gt;    cr.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Resta apenas executar a aplicação:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;gst -I blox-sample.im -f blox-sample.st&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Outra opção ao BLOX é &lt;a href="http://bioskop.fr/gtk_tutorial/"&gt;Gtk+&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-8757989863909827719?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/8757989863909827719/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=8757989863909827719' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8757989863909827719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8757989863909827719'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/04/blox.html' title='Quem ama BLOXeia!'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_rGfO7DAuOSE/S8EV0SuA38I/AAAAAAAAAVs/XZ9iJFxszMc/s72-c/balloon_smalltalk.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-5146623031183627016</id><published>2010-04-03T16:26:00.006-03:00</published><updated>2010-04-10T21:21:49.192-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Smalltalk'/><title type='text'>SUnit</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 100px; height: 74px; border: none;" src="http://1.bp.blogspot.com/_rGfO7DAuOSE/S8EV0SuA38I/AAAAAAAAAVs/XZ9iJFxszMc/s200/balloon_smalltalk.jpg" alt="Smalltalk" id="BLOGGER_PHOTO_ID_5458668211471966146" /&gt; &lt;a href="http://smalltalk.org/"&gt;Smalltalk&lt;/a&gt; possui um ótimo arcabouço de teste unitário chamado &lt;a href="http://www.gnu.org/software/smalltalk/manual/html_node/SUnit.html"&gt;SUnit&lt;/a&gt; – Smalltalk Unit Test Suite. Porém sua documentação é um tanto fraca.&lt;br /&gt;&lt;br /&gt;Segue aqui um pequeno tutorial de uso do SUnit. Veja que não é necessariamente a forma correta de usá-lo. Usaremos &lt;a href="http://smalltalk.gnu.org/"&gt;GNU Smalltalk&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Imagine que queremos implementar um método em &lt;code&gt;Integer&lt;/code&gt; que retorna se o número é primo ou não. Podemos primeiro criar um &lt;em&gt;test case&lt;/em&gt; para verificar seu funcionamento.&lt;br /&gt;&lt;br /&gt;Para isso, crie um arquivo &lt;code&gt;test-is-prime.st&lt;/code&gt; e defina a seguinte classe:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;TestCase subclass: #TestIsPrime&lt;br /&gt;    instanceVariableNames: ''&lt;br /&gt;    classVariableNames: ''&lt;br /&gt;    poolDictionaries: ''&lt;br /&gt;    category: 'Unit Test'&lt;br /&gt;!&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A classe &lt;code&gt;TestIsPrime&lt;/code&gt; é filha de &lt;code&gt;TestCase&lt;/code&gt; e, para nosso fim atual, não precisará de atributos.&lt;br /&gt;&lt;br /&gt;Precisaremos de um método de classe que execute os testes, para que não precisemos criar uma &lt;code&gt;TestSuite&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;!TestIsPrime class methodsFor: 'running'!&lt;br /&gt;&lt;br /&gt;    run&lt;br /&gt;        (self testSelectors) do: [ :test |&lt;br /&gt;            self run: test.&lt;br /&gt;        ].&lt;br /&gt;    !&lt;br /&gt;!&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Podemos agora criar a categoria &lt;code&gt;accessing&lt;/code&gt; para os testes:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;!TestIsPrime methodsFor: 'accessing'!&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O primeiro teste pode ser para determinar se números negativos retornam um erro quando se tenta determinar sua primalidade:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;testNegative&lt;br /&gt;    self should: [ -1 isPrime ] raise: ArithmeticError.&lt;br /&gt;!&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Não esqueça de indentar!&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update 2010-04-04]&lt;/tt&gt;&lt;br /&gt;A indentação aqui tem objetivo exclusivo de manter a clareza do código.&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;O método &lt;code&gt;#should:raise:&lt;/code&gt; executa um bloco e asserta que uma exceção será levantada, neste caso &lt;code&gt;ArithmeticError&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Podemos fazer o mesmo para zero:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;testZero&lt;br /&gt;    self should: [ 0 isPrime ] raise: ArithmeticError.&lt;br /&gt;!&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Já para o número um, é preciso assertar que ele não é primo, ou seja, retorne falso:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;testOne&lt;br /&gt;    self shouldnt: [ 1 isPrime ].&lt;br /&gt;!&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O método &lt;code&gt;#shouldnt:&lt;/code&gt; executa um bloco esperando pelo retorno falso.&lt;br /&gt;&lt;br /&gt;Mas quando chegarmos ao dois, ele é primo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;testTwo&lt;br /&gt;    self should: [ 2 isPrime ].&lt;br /&gt;!&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O método &lt;code&gt;#should:&lt;/code&gt; executa um bloco esperando pelo retorno verdadeiro.&lt;br /&gt;&lt;br /&gt;Você pode fazer isso indefinidamente se quiser:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;testSomeOtherValues&lt;br /&gt;    self should: [ 3 isPrime ].&lt;br /&gt;    self shouldnt: [ 4 isPrime ].&lt;br /&gt;    self should: [ 5 isPrime ].&lt;br /&gt;    self shouldnt: [ 6 isPrime ].&lt;br /&gt;    self should: [ 7 isPrime ].&lt;br /&gt;    self shouldnt: [ 8 isPrime ].&lt;br /&gt;    self shouldnt: [ 9 isPrime ].&lt;br /&gt;    self shouldnt: [ 10 isPrime ].&lt;br /&gt;    self should: [ 11 isPrime ].&lt;br /&gt;!&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Quando cançar, encerre a lista de métodos da categoria com a linha:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;!&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ou, se preferir ser mais explícito:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;!!&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;No final, adicione uma linha para executar os testes:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;TestIsPrime run.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para rodar os testes, copie a imagem contendo seu código para, por exemplo, &lt;code&gt;test.im&lt;/code&gt; e acrescente o SUnit com o seguinte comando:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;gst-load -I test.im SUnit&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora, com a imagem preparada, você pode executar os testes:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;gst-sunit -I test.im -f test-is-prime.st&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Se tudo correr bem, nada acontecerá, caso contrário você poderá receber uma mensagem do tipo:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;TestIsPrime&amp;gt;&amp;gt;#testSomeOtherValues ..&lt;/em&gt;&lt;br /&gt;&lt;em&gt;FAILURE: Assertion failed&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Onde &lt;code&gt;TestIsPrime&amp;gt;&amp;gt;#testSomeOtherValues&lt;/code&gt; significa que falhou o teste contido no método &lt;code&gt;#testSomeOtherValues&lt;/code&gt; da classe &lt;code&gt;TestIsPrime&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-5146623031183627016?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/5146623031183627016/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=5146623031183627016' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5146623031183627016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5146623031183627016'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/04/sunit.html' title='SUnit'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_rGfO7DAuOSE/S8EV0SuA38I/AAAAAAAAAVs/XZ9iJFxszMc/s72-c/balloon_smalltalk.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-5583994010468749089</id><published>2010-03-05T15:23:00.004-03:00</published><updated>2010-03-05T15:35:39.327-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Evento'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python é capa da TIdigital de Março</title><content type='html'>Gente,&lt;br /&gt;&lt;br /&gt;Segunda-feira todo mundo correndo pras bancas!&lt;br /&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: crosshair; width: 242px; height: 324px; border: none;" src="http://2.bp.blogspot.com/_rGfO7DAuOSE/S5FMbrCQXTI/AAAAAAAAAU0/qDMM34DzHyo/s320/capapython.jpg" alt="TIdigital Março" id="BLOGGER_PHOTO_ID_5445217462760004914" /&gt;&lt;br /&gt;&lt;br /&gt;Em março, &lt;a href="http://python.org/"&gt;Python&lt;/a&gt; em foco na revista TIdigital.&lt;br /&gt;&lt;br /&gt;Fonte: &lt;a href="http://pythonrio.org/python-e-capa-da-ti-digital-de-marco"&gt;PythOn Rio&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhας, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-5583994010468749089?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/5583994010468749089/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=5583994010468749089' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5583994010468749089'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5583994010468749089'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/03/python-e-capa-da-tidigital-de-marco.html' title='Python é capa da TIdigital de Março'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_rGfO7DAuOSE/S5FMbrCQXTI/AAAAAAAAAU0/qDMM34DzHyo/s72-c/capapython.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-8349320847110518626</id><published>2010-02-27T14:44:00.001-03:00</published><updated>2010-03-11T15:31:50.410-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='ECMA'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>MongoDB</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; border: none;" src="http://4.bp.blogspot.com/_rGfO7DAuOSE/S4lVpD9rPyI/AAAAAAAAAUw/jCU1Qk1BbCU/s1600/mongodb.jpg" alt="Logo" /&gt; Há atualmente na Computação uma onda de adoção de &lt;a href="http://pt.wikipedia.org/wiki/NoSQL"&gt;bancos de dados não-relacionais, comumente chamados NoSQL&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;O foco principal dos bancos NoSQL atuais é a &lt;a href="http://en.wikipedia.org/wiki/Document-oriented_database"&gt;orientação a documentos&lt;/a&gt;, uma variação &lt;em&gt;hash&lt;/em&gt; da &lt;a href="http://pt.wikipedia.org/wiki/Banco_de_dados_orientado_a_objetos"&gt;orientação a objetos&lt;/a&gt; e alternativa aos &lt;a href="http://pt.wikipedia.org/wiki/Banco_de_dados_relacional"&gt;RDBMSs&lt;/a&gt;, que dominaram a orientação dos gerenciadores de banco de dados por décadas.&lt;br /&gt;&lt;br /&gt;O principal banco NoSQL é o &lt;a href="http://couchdb.apache.org/"&gt;CouchDB&lt;/a&gt;, DBMS do Projeto Apache baseado em &lt;a href="http://ftp.sunet.se/pub/lang/erlang/"&gt;Erlang&lt;/a&gt;, porém há uma alternativa bem mais simples e aparentemente tão poderosa quanto: &lt;a href="http://www.mongodb.org/"&gt;MongoDB&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;MongoDB combina os melhores funcionalidades de orientação a documentos, &lt;em&gt;hashes&lt;/em&gt; e RDBMSs. É um banco de dados orientado a documentos, escalável, livre de esquema, de alto desempenho e código aberto escrito em &lt;a href="http://www.cplusplus.com/"&gt;C++&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Este artigo dá continuidade ao &lt;a href="http://montegasppa.blogspot.com/2010/02/mongodb.html"&gt;artigo nas Reflexões de Monte Gasppa e Giulia C.&lt;/a&gt; sobre a instalação do MongoDB. Aqui você poderá ver um pouquinho do uso de um banco de dados orientado a documentos.&lt;br /&gt;&lt;br /&gt;Este artigo é baseado na &lt;a href="http://www.mongodb.org/display/DOCS/Tutorial"&gt;documentação oficial&lt;/a&gt; e entende que você instalou o MongoDB segundo descrito nas &lt;a href="http://montegasppa.blogspot.com/2010/02/mongodb.html"&gt;Reflexões de Monte Gasppa e Giulia C.&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conexão na base de dados&lt;/h3&gt;&lt;br /&gt;Para conectar na base basta usar o comando &lt;code&gt;mongo&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;mongo&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;MongoDB shell version: 1.2.2&lt;/em&gt;&lt;br /&gt;&lt;em&gt;url: test&lt;/em&gt;&lt;br /&gt;&lt;em&gt;connecting to: test&lt;/em&gt;&lt;br /&gt;&lt;em&gt;type "help" for help&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Caso você tenha configurado uma porta alternativa em &lt;code&gt;/srv/mongodb/etc/mongodb.conf&lt;/code&gt;, você pode especificar isso na linha de comando do cliente:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;mongo --port 27018&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Você também pode se conectar a um servidor remoto, caso ele esteja habilitado para conexão externa, usando a &lt;em&gt;flag&lt;/em&gt; &lt;code&gt;--host&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Para escolher qual base de dados usar, o comando é &lt;code&gt;use&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;code&gt;use mydb&lt;/code&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Autorização&lt;/h3&gt;&lt;br /&gt;Você pode se autorizar na linha de comando com as opções &lt;code&gt;-u&lt;/code&gt; (usuário) e &lt;code&gt;-p&lt;/code&gt; (senha), ou já do &lt;em&gt;prompt&lt;/em&gt; do interpretador:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;use admin&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.auth('admin', 'ra35EG/dz');&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Comandos básicos&lt;/h3&gt;&lt;br /&gt;A linguagem de interação com MongoDB é &lt;a href="http://pt.wikipedia.org/wiki/JavaScript"&gt;Javascript&lt;/a&gt;, mas há alguns comandos úteis no interpretador.&lt;br /&gt;&lt;br /&gt;Para listar comandos úteis:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;help&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Listar recursos uteis da base atual:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.help();&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Listar recursos uteis de uma coleção (levemente equivalente a tabela de um banco relacional), no exemplo &lt;code&gt;foo&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.help();&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para listar as bases instaladas:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;show dbs&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para listar as coleções da base atual:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;show collections&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Listar usuários da base atual:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;show users&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Criar usuário na base atual:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.addUser('admin', 'ra35EG/dz');&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Autenticar-se:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.auth('admin', 'ra35EG/dz');&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Listar o conteúdo de uma coleção:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.find();&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Apagar uma coleção:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.drop();&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Apagar a base de dados atual:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.dropDatabase();&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Armazenamento de dados&lt;/h3&gt;&lt;br /&gt;Repare que o MongoDB é &lt;strong&gt;livre de esquema&lt;/strong&gt;, portanto uma coleção pode conter estruturas de dados radicalmente diferentes, sempre no formato &lt;a href="http://json.org/"&gt;JSON&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Por exemplo, vamos inserir dois dados distintos na coleção &lt;code&gt;foo&lt;/code&gt; da base &lt;code&gt;mydb&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;use mydb&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;var j = { name: 'mongo' };&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;var t = { x: 3 };&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.save(j);&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.save(t);&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.find();&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b8949d9cd50237b8573833b"), "name" : "mongo" }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b8949dbcd50237b8573833c"), "x" : 3 }&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Você não precisa predefinir a coleção, que é criada automaticamente no salvamento da primeira estrutura. O campo &lt;code&gt;_id&lt;/code&gt; é criado automaticamente e é a &lt;strong&gt;chave primária&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Para apagar o objeto &lt;code&gt;j&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;j = db.foo.findOne({ name: 'mongo' });&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.remove(j);&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para apagar todos os objetos basta remover a coleção:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.drop();&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Vamos usar um pouco mais de lógica:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;for (var i=0; i&amp;lt;100; ++i) db.foo.save({ x: i, y: i*i });&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Esse &lt;em&gt;loop&lt;/em&gt; cria cem registros, com &lt;code&gt;x&lt;/code&gt; variando de zero a noventa e nove e &lt;code&gt;y&lt;/code&gt; igual a seu quadrado:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.find();&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573833e"), "x" : 0, "y" : 0 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573833f"), "x" : 1, "y" : 1 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738340"), "x" : 2, "y" : 4 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738341"), "x" : 3, "y" : 9 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738342"), "x" : 4, "y" : 16 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738343"), "x" : 5, "y" : 25 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738344"), "x" : 6, "y" : 36 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738345"), "x" : 7, "y" : 49 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738346"), "x" : 8, "y" : 64 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738347"), "x" : 9, "y" : 81 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738348"), "x" : 10, "y" : 100 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738349"), "x" : 11, "y" : 121 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573834a"), "x" : 12, "y" : 144 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573834b"), "x" : 13, "y" : 169 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573834c"), "x" : 14, "y" : 196 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573834d"), "x" : 15, "y" : 225 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573834e"), "x" : 16, "y" : 256 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573834f"), "x" : 17, "y" : 289 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738350"), "x" : 18, "y" : 324 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738351"), "x" : 19, "y" : 361 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;has more&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Consultas (&lt;em&gt;queries&lt;/em&gt;)&lt;/h3&gt;&lt;br /&gt;É possível fazer consultas simples ou bem complexas assim como em modelos relacionais usando MongoDB.&lt;br /&gt;&lt;br /&gt;Vamos obter uma contagem de objetos:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.find().count();&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;100&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Só os cinco primeiros objetos:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.find().limit(5);&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573833e"), "x" : 0, "y" : 0 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573833f"), "x" : 1, "y" : 1 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738340"), "x" : 2, "y" : 4 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738341"), "x" : 3, "y" : 9 }&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora os cinco seguintes:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.find().skip(5).limit(5);&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738343"), "x" : 5, "y" : 25 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738344"), "x" : 6, "y" : 36 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738345"), "x" : 7, "y" : 49 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738346"), "x" : 8, "y" : 64 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738347"), "x" : 9, "y" : 81 }&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para obter o elemento com valor de &lt;code&gt;x&lt;/code&gt; vinte e quatro:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;var e = db.foo.findOne({ x: 24 });&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;print(e.y);&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;576&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;print(tojson(e));&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738356"), "x" : 24, "y" : 576 }&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Consultas avançadas&lt;/h3&gt;&lt;br /&gt;Vamos complicar um pouco…&lt;br /&gt;&lt;br /&gt;Para obter todos os registros com &lt;code&gt;x&lt;/code&gt; maior que cinquenta:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.find('this.x &gt; 50');&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738371"), "x" : 51, "y" : 2601 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738372"), "x" : 52, "y" : 2704 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738373"), "x" : 53, "y" : 2809 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738374"), "x" : 54, "y" : 2916 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738375"), "x" : 55, "y" : 3025 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738376"), "x" : 56, "y" : 3136 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738377"), "x" : 57, "y" : 3249 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738378"), "x" : 58, "y" : 3364 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738379"), "x" : 59, "y" : 3481 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573837a"), "x" : 60, "y" : 3600 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573837b"), "x" : 61, "y" : 3721 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573837c"), "x" : 62, "y" : 3844 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573837d"), "x" : 63, "y" : 3969 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573837e"), "x" : 64, "y" : 4096 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b8573837f"), "x" : 65, "y" : 4225 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738380"), "x" : 66, "y" : 4356 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738381"), "x" : 67, "y" : 4489 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738382"), "x" : 68, "y" : 4624 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738383"), "x" : 69, "y" : 4761 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;{ "_id" : ObjectId("4b894c05cd50237b85738384"), "x" : 70, "y" : 4900 }&lt;/em&gt;&lt;br /&gt;&lt;em&gt;has more&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Outra opção é usar o &lt;a href="http://www.mongodb.org/display/DOCS/Advanced+Queries"&gt;operador condicional&lt;/a&gt; &lt;code&gt;$gt&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.find({ x: { $gt: 50 } });&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Da mesma forma outros operadores. Por exemplo, todos os elementos com &lt;code&gt;x&lt;/code&gt; entre vinte e três e vinte e seis, inclusive:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.find('23 &amp;lt;= this.x &amp;&amp; this.x &amp;lt;= 26');&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ou:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.find({ x: { $gte: 23, $lte: 26 } });&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Os principais operadores são:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;$lt&lt;/code&gt; – menor que&lt;/li&gt; &lt;li&gt;&lt;code&gt;$gt&lt;/code&gt; – maior que&lt;/li&gt; &lt;li&gt;&lt;code&gt;$lte&lt;/code&gt; – menor ou igual a&lt;/li&gt; &lt;li&gt;&lt;code&gt;$gte&lt;/code&gt; – maior ou igual a&lt;/li&gt; &lt;li&gt;&lt;code&gt;$ne&lt;/code&gt; – diferente de&lt;/li&gt; &lt;li&gt;&lt;code&gt;$in&lt;/code&gt; – está em (recebe uma lista)&lt;/li&gt; &lt;li&gt;&lt;code&gt;$nin&lt;/code&gt; – não está em&lt;/li&gt; &lt;li&gt;&lt;code&gt;$mod&lt;/code&gt; – resto igual a (recebe uma lista onde o primeiro valor é o divisor e o segundo o resto)&lt;/li&gt; &lt;li&gt;&lt;code&gt;$exists&lt;/code&gt; – contém ou não o atributo&lt;/li&gt; &lt;li&gt;&lt;code&gt;$not&lt;/code&gt; – negação de uma condição&lt;/li&gt;&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Ordenação&lt;/h3&gt;&lt;br /&gt;A ordenação é feita usando o método &lt;code&gt;sort&lt;/code&gt;. Por exemplo, para ordenar de modo descrescente pelo atributo &lt;code&gt;y&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.find().sort({ y: -1 });&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Expressões regulares&lt;/h3&gt;Quando há campos com valor &lt;em&gt;string&lt;/em&gt;, é possível usar expressões regulares:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.find({ name: /^mon.o$/i });&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Índices&lt;/h3&gt;Quando você faz muitas consultas baseadas em um determinado atributo, é interessante criar um índice para ele. Por exemplo, se quisermos criar um índice para nosso atributo &lt;code&gt;x&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;db.foo.ensureIndex({ x: 1 });&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Obs.¹: o atributo &lt;code&gt;_id&lt;/code&gt; possui índice por padrão.&lt;br /&gt;&lt;br /&gt;Obs.²: é possível criar índices compostos.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Agregação&lt;/h3&gt;&lt;br /&gt;Não vou entrar nesse mérito, mas é possível criar agregações, como &lt;code&gt;GROUP_BY&lt;/code&gt; de SQL. Para tanto veja a &lt;a href="http://www.mongodb.org/display/DOCS/Aggregation"&gt;documentação oficial&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Módulos de conexão com linguagens de programação&lt;/h3&gt;&lt;br /&gt;Há módulos para várias linguagens, que podem ser encontrados na &lt;a href="http://api.mongodb.org/"&gt;lista de APIs&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;O módulo que pude e me fascinou foi para &lt;a href="http://api.mongodb.org/python"&gt;Python&lt;/a&gt;. Sua instalação usando &lt;a href="http://peak.telecommunity.com/dist/ez_setup.py"&gt;&lt;code&gt;easy_install&lt;/code&gt;&lt;/a&gt; foi muito simples:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;sudo easy_install -U pymongo&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E seu uso extremamente fácil devido à similiaridade entre &lt;a href="http://diveintopython.org/getting_to_know_python/dictionaries.html"&gt;dicionários de Python&lt;/a&gt; e JSON. A única reclamação que faço é o fato do método &lt;code&gt;db.auth()&lt;/code&gt; do MongoDB ter sido traduzido como &lt;code&gt;db.authenticate()&lt;/code&gt; em Python, o que me fez perder alguns segundos tentando entender por que não funcionava.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;**&lt;/h3&gt;&lt;br /&gt;Espero que este artigo seja mais do que útil e incite o uso dessa intrigante ferramenta.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-8349320847110518626?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/8349320847110518626/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=8349320847110518626' title='7 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8349320847110518626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8349320847110518626'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/02/mongodb.html' title='MongoDB'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_rGfO7DAuOSE/S4lVpD9rPyI/AAAAAAAAAUw/jCU1Qk1BbCU/s72-c/mongodb.jpg' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-8948507057408789978</id><published>2010-02-25T14:38:00.002-03:00</published><updated>2010-02-25T14:39:54.240-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><title type='text'>Kodumaro no Twitter</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 100px; height: 100px; border: none;" src="http://3.bp.blogspot.com/_rGfO7DAuOSE/S4a0tjBLPbI/AAAAAAAAAUs/NqzC5P5s5c8/s200/kodumaro.jpg" alt="Twitter" /&gt; &lt;a href="http://kodumaro.blogspot.com/"&gt;Kodumaro&lt;/a&gt; agora no &lt;a href="http://twitter.com/"&gt;Twitter&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;a href="http://twitter.com/kodumaro"&gt;@kodumaro&lt;/a&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;A conta será usada para divulgar novos artigos e para troca de ideias com os leitores.&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-8948507057408789978?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/8948507057408789978/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=8948507057408789978' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8948507057408789978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8948507057408789978'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/02/kodumaro-agora-no-twitter-kodumaro.html' title='Kodumaro no Twitter'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_rGfO7DAuOSE/S4a0tjBLPbI/AAAAAAAAAUs/NqzC5P5s5c8/s72-c/kodumaro.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-6779938689445226658</id><published>2010-01-14T21:13:00.007-03:00</published><updated>2010-09-30T14:07:45.630-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='Funcional'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>FizzBuzz (No Stairway to Heaven)</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 55px; height: 55px; border: none;" src="http://2.bp.blogspot.com/_rGfO7DAuOSE/SwSZGIY_eXI/AAAAAAAAATA/Gh-qDqdTMX0/s200/glider.png" alt="Glider" /&gt; Hoje um &lt;a href="http://twitter.com/flavioamieiro"&gt;amigo meu&lt;/a&gt; veio falar comigo de uma brincadeira velha – e que eu não conhecia – chamada &lt;a href="http://stackoverflow.com/questions/437/what-is-your-solution-to-the-fizzbuzz-problem"&gt;FizzBuzz&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;[update 2010-01-15]&lt;/tt&gt;&lt;br /&gt;Sugestão de apontador do &lt;a href="http://twitter.com/identica_cesarb"&gt;Cesar Barros&lt;/a&gt;: &lt;a href="http://wolfbyte-net.blogspot.com/2007/09/if-something-is-worth-doing.html"&gt;If something is worth doing…&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;A propósito, atualizei o código Lisp.&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;A brincadeira consiste em imprimir uma sequência de números, tradicionalmente de 1 a 100. Porém os números múltiplos de 3 devem ser substituídos por &lt;em&gt;fizz&lt;/em&gt; e os números múltiplos de 5 por &lt;em&gt;buzz&lt;/em&gt;. Os números que são divisíveis por 3 e por 5 devem ser substituídos por &lt;em&gt;fizzbuzz&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;No Stackoverflow você pode encontrar as versões mais loucas, como &lt;a href="http://stackoverflow.com/questions/437/what-is-your-solution-to-the-fizzbuzz-problem/21328#21328"&gt;LOLCODE&lt;/a&gt;, &lt;a href="http://stackoverflow.com/questions/437/what-is-your-solution-to-the-fizzbuzz-problem/4295#4295"&gt;Brainf*ck&lt;/a&gt;, &lt;a href="http://stackoverflow.com/questions/437/what-is-your-solution-to-the-fizzbuzz-problem/10452#10452"&gt;Ook&lt;/a&gt;, &lt;em&gt;assembly&lt;/em&gt; de &lt;a href="http://stackoverflow.com/questions/437/what-is-your-solution-to-the-fizzbuzz-problem/10421#10421"&gt;8051&lt;/a&gt;, &lt;a href="http://stackoverflow.com/questions/437/what-is-your-solution-to-the-fizzbuzz-problem/66914#66914"&gt;6502&lt;/a&gt; e &lt;a href="http://stackoverflow.com/questions/437/what-is-your-solution-to-the-fizzbuzz-problem/37420#37420"&gt;Linux IA-32&lt;/a&gt;, &lt;a href="http://stackoverflow.com/questions/437/what-is-your-solution-to-the-fizzbuzz-problem/48722#48722"&gt;Hebreu Estruturado&lt;/a&gt;, &lt;a href="http://stackoverflow.com/questions/437/what-is-your-solution-to-the-fizzbuzz-problem/35629#35629"&gt;Cobol&lt;/a&gt; e &lt;a href="http://stackoverflow.com/questions/437/what-is-your-solution-to-the-fizzbuzz-problem/124485#124485"&gt;Forth&lt;/a&gt;, como destaque para o poético código em &lt;a href="http://stackoverflow.com/questions/437/what-is-your-solution-to-the-fizzbuzz-problem/91068#91068"&gt;Perl&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Aqui quero postar algumas soluções que achei interessantes.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Em &lt;a href="http://haskell.org/"&gt;Haskell&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;putStr (concat [if (mod x 15)==0 then "fizzbuzz\n" else if (mod x 3)==0 then "fizz\n" else if (mod x 5)==0 then "buzz\n" else (show x) ++ "\n" | x &amp;lt;- [1..100]])&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em &lt;a href="http://python.org/"&gt;Python&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;print "\n".join('fizzbuzz' if x%15==0 else 'fizz' if x%3==0 else 'buzz' if x%5==0 else str(x) for x in xrange(1, 101))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em &lt;a href="http://www.perl.org/"&gt;Perl&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;print +(fizz)[$_%3] . (buzz)[$_%5] || $_, $/ for 1..100;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em &lt;a href="http://clisp.cons.org/"&gt;Common Lisp&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint lang-cl"&gt;(format t "~{~A~%~}" (loop for x from 1 to 100 collect (if (zerop (mod x 15)) "fizzbuzz" (if (zerop (mod x 3)) "fizz" (if (zerop (mod x 5)) "buzz" x)))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-6779938689445226658?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/6779938689445226658/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=6779938689445226658' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/6779938689445226658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/6779938689445226658'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/01/fizzbuzz.html' title='FizzBuzz (&lt;em&gt;No Stairway to Heaven&lt;/em&gt;)'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_rGfO7DAuOSE/SwSZGIY_eXI/AAAAAAAAATA/Gh-qDqdTMX0/s72-c/glider.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-6576141260006879094</id><published>2010-01-08T23:07:00.003-03:00</published><updated>2010-01-08T23:22:49.095-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Evento'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Ajude a mostrar a PythonBrasil na PyCon 2010</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://photos1.blogger.com/blogger/6505/3295/200/python.png" alt="" /&gt; Meu amigo &lt;a href="http://henriquebastos.net/"&gt;Henrique Bastos&lt;/a&gt; publicou hoje um artigo entitulado &lt;a href="http://henriquebastos.net/2010/01/08/ajude-a-mostrar-a-pythonbrasil-na-pycon-2010/"&gt;Ajude a mostrar a PythonBrasil na PyCon 2010&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;A proposta é muito legal e já preenchi o &lt;a href="http://henriquebastos.wufoo.com/forms/vamos-divulgar-nossa-comunidade-python-na-pycon/"&gt;formulário&lt;/a&gt; para reunir informações sobre a Comunidade Python no Brasil.&lt;br /&gt;&lt;br /&gt;Segue uma reprodução do artigo:&lt;br /&gt;&lt;blockquote&gt;Salve Pythonistas!&lt;br /&gt;&lt;br /&gt;De 19 a 21 de fevereiro será realizada a &lt;a title="Site do evento." href="http://us.pycon.com"&gt;PyCon&lt;/a&gt;, &lt;a title="Veja onde será realizada a conferência." href="http://maps.google.com.br/maps/place?cid=16656910773578529375&amp;amp;q=hyatt+atlanta&amp;amp;hl=pt-BR&amp;amp;cd=1&amp;amp;cad=src:pplink&amp;amp;ei=TL1HS9TrJp_EyQTwxqTmBw&amp;amp;sig2=FbA0IOSLu6RvNabKmyeADg"&gt;em Atlanta nos Estados Unidos&lt;/a&gt;. Como alguns de vocês já sabem, participarei do evento apresentando a &lt;a title="Veja o resumo na página das palestras." href="http://us.pycon.org/2010/conference/talks"&gt;palestra #78 entitulada «Small acts make great revolutions»&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Esta apresentação será uma evolução da palestra relâmpago que fiz na &lt;a title="Site do evento." href="http://www.pythonbrasil.org.br/2009"&gt;PythonBrasil[5] em Caxias do Sul&lt;/a&gt;, onde tento difundir os conceitos por trás das iniciativas que vêm movimentando a comunidade no Rio de Janeiro.&lt;br /&gt;&lt;br /&gt;No entanto, falar só do que acontece no Rio me parece muito pouco para uma oportunidade dessas. Quero muito aproveitar a &lt;a title="Site do evento." href="http://us.pycon.com"&gt;PyCon&lt;/a&gt; para mostrar o grande desenvolvimento da &lt;a href="http://www.python.org.br/wiki"&gt;Comunidade Python no Brasil&lt;/a&gt;. Pessoasfantásticas estão fazendo as coisas acontecerem em Terras Brasilis. E a &lt;a title="Video da 1a palestra relâmpago sobre &amp;quot;Small Acts&amp;quot; " href="http://www.vcasmo.com/video/pythonrio/5494"&gt;exemplo do que fiz no FISL 10&lt;/a&gt;, pretendo continuar na linha de tentar evidenciar que na nossa comunidade, o todo é muito maior do que a soma das partes. Mas para isto, eu preciso da ajuda de vocês.&lt;br /&gt;&lt;br /&gt;Para poder falar com propriedade sobre a &lt;a href="http://www.python.org.br/wiki"&gt;Comunidade Python no Brasil&lt;/a&gt;, precisamos traçar o perfil do nosso grupo. Por isso, preparei um rápido questionário &lt;em&gt;online&lt;/em&gt; que ajudará a levantar informações sobre nossa comunidade. Ele está disponível em: &lt;a title="Não deixe de responder à pesquisa!" href="http://henriquebastos.wufoo.com/forms/vamos-divulgar-nossa-comunidade-python-na-pycon/"&gt;http://henriquebastos.wufoo.com/forms/vamos-divulgar-nossa-comunidade-python-na-pycon/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;É muito importante que o maior número de &lt;em&gt;pythonistas&lt;/em&gt; respondam à pesquisa. Isso vai ajudar muito! Portanto, &lt;strong&gt;não economizem nos &lt;em&gt;retweets&lt;/em&gt; e espalhem o &lt;em&gt;link&lt;/em&gt; da pesquisa por todas as listas de email&lt;/strong&gt; no Brasil,  relacionadas com &lt;a title="Site da linguagem" href="http://python.org"&gt;Python&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Além disso, também estou buscando &lt;em&gt;links&lt;/em&gt; para boas fotos em alta resolução, como as tiradas na escadaria da PUC-RS durante o FISL 10 e as fotos «aéreas» da &lt;a href="http://www.pythonbrasil.org.br/2008"&gt;PythonBrasil[4] na UVA&lt;/a&gt; etc. Basta publicarem os &lt;em&gt;links&lt;/em&gt; para as fotos nos comentários deste &lt;em&gt;post&lt;/em&gt; ou me enviar por &lt;em&gt;email&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Obrigado à todos, e &lt;em&gt;vamo que vamo&lt;/em&gt;!&lt;br /&gt;&lt;br /&gt;[]’s!&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Já andei &lt;a href="http://twitter.com/batalema/status/7541409617"&gt;tuitando&lt;/a&gt; e divulguei nas &lt;a href="http://montegasppa.blogspot.com/2010/01/ajude-mostrar-pythonbrasil-na-pycon.html"&gt;Reflexões de Monte Gasppa e Giulia C.&lt;/a&gt; também. Convido todos então a &lt;a href="http://henriquebastos.net/2010/01/08/ajude-a-mostrar-a-pythonbrasil-na-pycon-2010/"&gt;ler o artigo&lt;/a&gt; e &lt;a href="http://henriquebastos.wufoo.com/forms/vamos-divulgar-nossa-comunidade-python-na-pycon/"&gt;preencher o formulário&lt;/a&gt;, ajudando assim o Henrique a revelar e expor a Comunidade Python no Brasil ao Mundo!&lt;br /&gt;&lt;br /&gt;[]’s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-6576141260006879094?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/6576141260006879094/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=6576141260006879094' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/6576141260006879094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/6576141260006879094'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2010/01/ajude-mostrar-pythonbrasil-na-pycon.html' title='Ajude a mostrar a PythonBrasil na PyCon 2010'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-7740215310213452111</id><published>2009-12-22T19:28:00.006-03:00</published><updated>2010-02-26T11:58:24.679-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Seaside</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://3.bp.blogspot.com/_rGfO7DAuOSE/SByvpfxLTOI/AAAAAAAAAFQ/nea8UWGDh5A/s200/squeak.jpg" alt="Squeak" /&gt; &lt;a href="http://seaside.st/"&gt;Seaside&lt;/a&gt; é um arcabouço (&lt;em&gt;framework&lt;/em&gt;) para desenvolvimento de aplicações &lt;em&gt;web&lt;/em&gt; para &lt;a href="http://smalltalk.org"&gt;Smalltalk&lt;/a&gt;. É descrito pelo próprio autor como um arcabouço &lt;strong&gt;herético&lt;/strong&gt;, por quebrar todas as regras dos guru&lt;del&gt;don&lt;/del&gt;s atuais.&lt;br /&gt;&lt;br /&gt;Pessoalmente gosto muito de coisas heréticas ou &lt;strong&gt;subversivas&lt;/strong&gt;. Sou um apaixonado por subversão. =D&lt;br /&gt;&lt;br /&gt;Olhando a &lt;a href="http://book.seaside.st/book"&gt;documentação&lt;/a&gt;, podemos ver que Seaside é suportado pelas máquinas virtuais &lt;a href="http://smalltalk.cincom.com/"&gt;Cincom VisualWorks&lt;/a&gt;, &lt;a href="http://smalltalk.gnu.org/"&gt;GNU Smalltalk&lt;/a&gt;, &lt;a href="http://www.instantiations.com/VAST/prod/vast.html"&gt;VA Smalltalk&lt;/a&gt;, &lt;a href="http://squeak.org/"&gt;Squeak&lt;/a&gt; e seus derivados &lt;a href="http://pharo-project.org/"&gt;Pharo&lt;/a&gt; e &lt;a href="http://seaside.gemstone.com/"&gt;GLASS&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;GNU Smalltalk&lt;/h3&gt;&lt;br /&gt;A máquina virtual recomentada é Squeak, da qual gosto muito e que é ótima para aplicações &lt;em&gt;desktop&lt;/em&gt;, no entanto Squeak é uma plataforma muito pesada, consome muitos recursos da máquina, por isso, para Seaside, optei por uma plataforma mais leve: GNU Smalltalk.&lt;br /&gt;&lt;br /&gt;GNU Smalltalk sofre porém de um mal extremamente irritante: a sintaxe da linguagem é muito irregular – para ser eufémico.&lt;br /&gt;&lt;br /&gt;Teoricamente GNU Smalltalk suportaria a sintaxe correta de &lt;a href="http://pt.wikipedia.org/wiki/Smalltalk#Sintaxe"&gt;Smalltalk-80&lt;/a&gt;, mas não funciona bem assim… ele é muito chato e levanta erros de sintaxe para códigos perfeitamente corretos, mas que diferem do que o GNU Smalltalk espera de Smalltalk-80. Então é preciso experimentar algumas formas diferentes – mas regulares – de fazer as coisas antes de encontrar uma que funcione (às vezes ele implica até com nomes de argumentos).&lt;br /&gt;&lt;br /&gt;Vou usar aqui a sintaxe Smalltalk-80 precisa – e que funciona no GNU Smalltalk –, mas colocarei o mesmo código na sintaxe peculiar do GNU Smalltalk ao final deste artigo apenas por curiosidade.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Preparação da imagem&lt;/h3&gt;&lt;br /&gt;Para criar a imagem para nosso exemplo usei o comando:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; gst-load -iI seaside.im Seaside Seaside-Development Seaside-Examples&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Isso cria uma imagem &lt;code&gt;seaside.im&lt;/code&gt; com os pacotes &lt;code&gt;Seaside&lt;/code&gt; (Seaside em si), &lt;code&gt;Seaside-Development&lt;/code&gt; (ferramentas de desenvolvimento) e &lt;code&gt;Seaside-Examples&lt;/code&gt; (exemplos).&lt;br /&gt;&lt;br /&gt;Usei então o &lt;a href="http://book.seaside.st/book/getting-started/gst/first-component"&gt;exemplo&lt;/a&gt; de componente da própria documentação: &lt;code&gt;MyCounter.st&lt;/code&gt;.&lt;br /&gt;&lt;ul&gt; &lt;li&gt;O método de classe &lt;code&gt;#canBeRoot&lt;/code&gt; diz se o componente pode ser registrado como uma aplicação autónoma ou não.&lt;/li&gt; &lt;li&gt;Na inicialização (&lt;code&gt;#initialize&lt;/code&gt;) o atributo &lt;code&gt;count&lt;/code&gt; é zerado.&lt;/li&gt; &lt;li&gt;O método &lt;code&gt;#states&lt;/code&gt; retorna uma coleção de estados que podem ser retrilhados (&lt;em&gt;backtracked&lt;/em&gt;).&lt;/li&gt; &lt;li&gt;O método &lt;code&gt;#renderContentOn:&lt;/code&gt; é usado para renderizar a página.&lt;/li&gt; &lt;li&gt;Ao final a mensagem &lt;code&gt;#registerAsApplication:&lt;/code&gt; registra o componente como aplicação.&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;O código fica então (se copiar e colar, substituia &lt;code&gt;↑&lt;/code&gt; por &lt;code&gt;^&lt;/code&gt;):&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;" See: http://www.gnu.org/software/smalltalk/manual/html_node/Seaside.html "&lt;br /&gt;&lt;br /&gt;Seaside.WAComponent subclass: #MyCounter&lt;br /&gt;    instanceVariableNames: 'count'&lt;br /&gt;    classVariableNames: ''&lt;br /&gt;    poolDictionaries: ''&lt;br /&gt;    category: 'Seaside Examples'&lt;br /&gt;!&lt;br /&gt;&lt;br /&gt;!MyCounter class methodsFor: 'testing'!&lt;br /&gt;&lt;br /&gt;    canBeRoot&lt;br /&gt;        ↑true&lt;br /&gt;    !&lt;br /&gt;&lt;br /&gt;!&lt;br /&gt;&lt;br /&gt;!MyCounter methodsFor: 'initializing'!&lt;br /&gt;&lt;br /&gt;    initialize&lt;br /&gt;        super initialize.&lt;br /&gt;        count := 0.&lt;br /&gt;    !&lt;br /&gt;&lt;br /&gt;!&lt;br /&gt;&lt;br /&gt;!MyCounter methodsFor: 'accessing'!&lt;br /&gt;&lt;br /&gt;    states&lt;br /&gt;        ↑{ self }&lt;br /&gt;    !&lt;br /&gt;&lt;br /&gt;!&lt;br /&gt;&lt;br /&gt;!MyCounter methodsFor: 'rendering'!&lt;br /&gt;&lt;br /&gt;    renderContentOn: html&lt;br /&gt;        html heading: count.&lt;br /&gt;        html anchor&lt;br /&gt;            callback: [ count := count + 1 ];&lt;br /&gt;            with: '++'.&lt;br /&gt;        html space.&lt;br /&gt;        html anchor&lt;br /&gt;            callback: [ count := count - 1 ];&lt;br /&gt;            with: '--'.&lt;br /&gt;    !&lt;br /&gt;&lt;br /&gt;!&lt;br /&gt;&lt;br /&gt;MyCounter registerAsApplication: 'mycounter'.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para carregar o componente na imagem usei o comando:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; gst -I seaside.im -S MyCounter.st&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Rodar a aplicação&lt;/h3&gt;&lt;br /&gt;O seguinte comando levanta a máquina virtual no modo servidor:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; gst-remote -I seaside.im --daemon&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Depois disso você poderá ver a máquina virtual ouvindo na porta 12345/TCP:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; netstat -ln4 | grep 12345&lt;br /&gt;&lt;em&gt;tcp        0      0 0.0.0.0:12345           0.0.0.0:*               LISTEN&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;É possível obter o PID do processo da máquina virtual com seguinte comando:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; gst-remote --pid&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Porém o Seaside não está rodando. Para rodar o serviço &lt;em&gt;web&lt;/em&gt; use o comando:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; gst-remote --start=Seaside&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;É possível também iniciar a máquina virtual &lt;strong&gt;já rodando o Seaside&lt;/strong&gt; com o seguinte comando:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; gst-remote -I seaside.im --daemon --start=Seaside&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Por padrão o serviço &lt;em&gt;web&lt;/em&gt; Seaside estará escutando na porta 8080/TCP.&lt;br /&gt;&lt;br /&gt;Para acessar a aplicação que acabamos de criar use o endereço &lt;a href="http://localhost:8080/seaside/mycounter"&gt;http://localhost:8080/seaside/mycounter&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Parar a aplicação&lt;/h3&gt;&lt;br /&gt;Para parar a aplicação use o comando:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; gst-remote --stop=Seaside&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Repare que, apesar do serviço &lt;em&gt;web&lt;/em&gt; ter parado, a máquina virtual continua rodando. Para pará-la:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; gst-remote --kill&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Para comparação&lt;/h3&gt;&lt;br /&gt;A título de comparação, segue o código usando a sintaxe &lt;del&gt;bizarra e esdrúxula&lt;/del&gt; peculiar do GNU Smalltalk:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;Seaside.WAComponent subclass: MyCounter [&lt;br /&gt;    | count |&lt;br /&gt;    &lt;br /&gt;    &amp;lt;category: 'Seaside Examples'&amp;gt;&lt;br /&gt;    &amp;lt;comment: nil&amp;gt;&lt;br /&gt;&lt;br /&gt;    MyCounter class &amp;gt;&amp;gt; canBeRoot [&lt;br /&gt;        &amp;lt;category: 'testing'&amp;gt;&lt;br /&gt;        ^true&lt;br /&gt;    ]&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    initialize [&lt;br /&gt;        &amp;lt;category: 'initializing'&amp;gt;&lt;br /&gt;        super initialize.&lt;br /&gt;        count := 0&lt;br /&gt;    ]&lt;br /&gt;&lt;br /&gt;    states [&lt;br /&gt;        &amp;lt;category: 'accessing'&amp;gt;&lt;br /&gt;        ^{ self }&lt;br /&gt;    ]&lt;br /&gt;&lt;br /&gt;    renderContentOn: html [&lt;br /&gt;        &amp;lt;category: 'rendering'&amp;gt;&lt;br /&gt;        html heading: count.&lt;br /&gt;        (html anchor)&lt;br /&gt;            callback: [count := count + 1];&lt;br /&gt;            with: '++'.&lt;br /&gt;        html space.&lt;br /&gt;        (html anchor)&lt;br /&gt;            callback: [count := count - 1];&lt;br /&gt;            with: '--'&lt;br /&gt;    ]&lt;br /&gt;].&lt;br /&gt;&lt;br /&gt;MyCounter registerAsApplication: 'mycounter'.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-7740215310213452111?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/7740215310213452111/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=7740215310213452111' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/7740215310213452111'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/7740215310213452111'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/12/seaside.html' title='Seaside'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_rGfO7DAuOSE/SByvpfxLTOI/AAAAAAAAAFQ/nea8UWGDh5A/s72-c/squeak.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-1284665232521181172</id><published>2009-12-06T12:42:00.013-03:00</published><updated>2010-04-14T21:10:13.293-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='Funcional'/><title type='text'>Mais sobre reiteração</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 55px; height: 55px; border: none;" src="http://2.bp.blogspot.com/_rGfO7DAuOSE/SwSZGIY_eXI/AAAAAAAAATA/Gh-qDqdTMX0/s200/glider.png" alt="Glider" /&gt; A reiteração ou iteração é um dos mais efetivos algoritmos para para processamento de sequências, mas sua eficiência não se limita a processamento de conjuntos prontos, essa técnica de algoritmo também pode ser usada para processamento de amostragens em plena coleta.&lt;br /&gt;&lt;br /&gt;Vamos a um algoritmo bem simples, a média aritmética:&lt;br /&gt;&lt;center&gt;&lt;img src="http://cacilhas.info/bin/mimetex.cgi?\bar{x}=\frac{\sum_{i=1}^nx_i}{n}" alt="mean_x=sum_x/n" /&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;O algoritmo reiterativo pode ser expresso da seguinte forma:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(defun mean ((a-list list))&lt;br /&gt;  (/&lt;br /&gt;    (apply #'+ a-list)&lt;br /&gt;    (length a-list)))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora imagine que você tem o registro contínuo do comportamento de um dado específico ao longo do tempo e gostaria de manter sua média sem preocupação como os valores em si (acho um caso pouco provável, mas…).&lt;br /&gt;&lt;br /&gt;Se reparando bem, há dois dados importantes para o cálculo da média aritmética: a própria média e a quantidade de elementos. Basta que a função receba esses valores além dos novos valores que serão usados para atualizar a média anterior.&lt;br /&gt;&lt;br /&gt;Assim é possível armazenar apenas a média atual e a quantidade de elementos avaliados:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(defun update-mean ((the-mean hash-table) (a-list list))&lt;br /&gt;  (let ((*count* (+ (gethash 'count the-mean) (length a-list))))&lt;br /&gt;    (setf (gethash 'mean the-mean)&lt;br /&gt;      (/&lt;br /&gt;        (+&lt;br /&gt;          (apply #'+ a-list)&lt;br /&gt;          (* (gethash 'mean the-mean) (gethash 'count the-mean)))&lt;br /&gt;        *count*))&lt;br /&gt;    (setf (gethash 'count the-mean) *count*)&lt;br /&gt;    the-mean))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Então, além de receber a lista com os dados mais recentes (segundo parâmetro), a função recebe como primeiro parâmetro um &lt;em&gt;hash&lt;/em&gt; com os dados de média anteriores.&lt;br /&gt;&lt;br /&gt;O formato inicial do &lt;em&gt;hash&lt;/em&gt; deve ser:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;#s(hash-table :test fasthash-eql (count . 0) (mean . 0))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ou seja, &lt;code&gt;'mean&lt;/code&gt; zero (0) e &lt;code&gt;'count&lt;/code&gt; zero (0). O &lt;em&gt;hash&lt;/em&gt; será atualizado e retornado:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint lang-lisp"&gt;(setq *mean*&lt;br /&gt;  (make-hash-table&lt;br /&gt;    :initial-contents (list&lt;br /&gt;      (cons 'count 0)&lt;br /&gt;      (cons 'mean 0))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Na próxima falarei em &lt;a href="http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#On-line_algorithm"&gt;variância &lt;em&gt;on-line&lt;/em&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-1284665232521181172?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/1284665232521181172/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=1284665232521181172' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/1284665232521181172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/1284665232521181172'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/12/mais-sobre-reiteracao.html' title='Mais sobre reiteração'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_rGfO7DAuOSE/SwSZGIY_eXI/AAAAAAAAATA/Gh-qDqdTMX0/s72-c/glider.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-285191462001059816</id><published>2009-11-04T19:41:00.006-03:00</published><updated>2010-11-01T17:03:13.296-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><title type='text'>Ideias poderosas por trás de uma piada</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://photos1.blogger.com/blogger/6505/3295/200/baal.png" alt="Baal" /&gt; &lt;a href="http://www.dieblinkenlights.com/"&gt;Ricardo Bánffy&lt;/a&gt; fez uma &lt;strong&gt;piada de 1º de abril&lt;/strong&gt; no ano passado lançando um suposto &lt;em&gt;framework&lt;/em&gt; em &lt;a href="http://www.lisp.org/"&gt;Lisp&lt;/a&gt; chamado &lt;a href="http://www.dieblinkenlights.com/artigos_pt/o-kanamit-web-framework"&gt;Kanamit&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;No entanto a parte da piada é somente o terceiro tópico do texto e o Bánffy aproveitou o ar de piada para rasgar o verbo e dizer umas verdades sem medo.&lt;br /&gt;&lt;br /&gt;Como &lt;strong&gt;concordo quase 100% com o texto&lt;/strong&gt;, decidi reproduzi-lo aqui de forma séria:&lt;br /&gt;&lt;blockquote&gt;&lt;em&gt;Eu sempre gostei de escrever aqui sobre linguagens «exóticas». Já houve um tempo em que &lt;a href="http://python.org/"&gt;Python&lt;/a&gt; era exótico. Hoje Python é &lt;/em&gt;mainstream&lt;em&gt;. &lt;a href="http://www.ruby-lang.org/"&gt;Ruby&lt;/a&gt;, idem. Há até suporte a &lt;a href="http://www.rubyonrails.pro.br/"&gt;Rails&lt;/a&gt; no NetBeans 6 e para Python no Visual Studio. Não dá pra ser muito mais &lt;/em&gt;mainstream&lt;em&gt; do que isso.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Nem todas as linguagens exóticas que eu conheci deram certo. &lt;a href="http://smalltalk.org/"&gt;Smalltalk&lt;/a&gt;, por exemplo, continua sendo aquela linguagem muito sofisticada, &lt;strong&gt;anos-luz à frente&lt;/strong&gt; do Java, mas que quase ninguém usa. Smalltalk tem &lt;strong&gt;ideias poderosas&lt;/strong&gt; demais. A ideia de rodar dentro de uma máquina virtual, de todo o código poder ser examinado e modificado «ao vivo», do compilador incremental, do &lt;/em&gt;class browser&lt;em&gt;, do &lt;/em&gt;late-binding&lt;em&gt;, das mensagens... Tudo isso era demais pras cabecinhas da maioria dos programadores que só conseguem entender Visual Basic ou PHP e olha lá.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Mas «Visual Basic e PHP resolvem todos os meus problemas», dizem eles. Claro. Se tudo o que eles conhecem se resume a isso, eles não imaginam sequer que existam outros tipos de problema. É uma limitação de capacidade expressiva: eles não têm as ferramentas intelectuais necessárias para expressar as &lt;strong&gt;classes de problemas que outras ferramentas expressam&lt;/strong&gt; e resolvem.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;Não se pode pensar em uma lâmpada fluorescente se tudo o que você conhece são pedras lascadas e peles de urso.&lt;/strong&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Uma outra linguagem muito além do seu tempo é o Lisp. Além do seu tempo porque, se ela é uma coisa poderosa hoje comparada ao que temos hoje, imaginem em 1960 quando ela foi inventada…&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Por muito tempo, havia implementações de Lisp para computadores &lt;/em&gt;desktop&lt;em&gt;, mas, com processadores de 16 bits e menos de um &lt;/em&gt;megabyte&lt;em&gt; de RAM, essas máquinas serviam apenas como brinquedos. Você podia fazer um &lt;/em&gt;loop&lt;em&gt; e imprimir 10 vezes «fulano é bobo», mas não muito mais do que isso.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Naquele tempo, para se rodar programas em Lisp, você precisaria de uma Lisp &lt;/em&gt;machine&lt;em&gt;, um computador dedicado, com um processador único capaz de coisas que nenhum outro processador da época – ou de hoje – era capaz de fazer. Eram incrivelmente caras.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Mas as implementações de brinquedo eram o bastante para abrir as cabeças dos jovens computólogos (antes deles se chamarem assim). Lisp e &lt;a href="http://schemers.org/"&gt;Scheme&lt;/a&gt; (um dialeto de Lisp) são usados como ferramenta didática em todos os bons cursos de ciência da computação. Se no seu curso não tem, pare de perder tempo e peça seu dinheiro de volta. Não sei quanto é a mensalidade, mas é certo que o curso vale menos.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;E, claro, hoje em dia, temos computadores amplamente capazes de rodar boas implementações de Lisp. Meu &lt;/em&gt;notebook&lt;em&gt; consegue emular uma Lisp &lt;/em&gt;machine&lt;em&gt; da Texas Instruments (uma Micro-Explorer) mais depressa do que ela era originalmente.&lt;/em&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Artigo original: &lt;a href="http://www.dieblinkenlights.com/artigos_pt/o-kanamit-web-framework"&gt;O Kanamit Web Framework&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-285191462001059816?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/285191462001059816/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=285191462001059816' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/285191462001059816'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/285191462001059816'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/11/ideias-poderosas-por-tras-de-uma-piada.html' title='Ideias poderosas por trás de uma piada'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-716295691748370467</id><published>2009-10-21T22:01:00.008-03:00</published><updated>2010-11-01T16:59:13.674-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='Funcional'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Mais sobre programação funcional</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://4.bp.blogspot.com/_rGfO7DAuOSE/Rgv00nwEXZI/AAAAAAAAAB8/r59qEVD0qOE/s200/haskell.jpg" alt="Paradigma funcional" /&gt;&lt;br /&gt;&lt;br /&gt;Aproveitando o ensejo do &lt;a href="http://kodumaro.blogspot.com/2009/10/oddwording-2.html"&gt;artigo anterior&lt;/a&gt; sobre programação funcional, gostaria de puxar mais este artigo sobre três algoritmos tradicionais: sequência de Fibonacci, fatorial e &lt;em&gt;quick sort&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Fatorial&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://pt.wikipedia.org/wiki/Fatorial"&gt;Fatorial&lt;/a&gt; é um dos algoritmos recursivos mais tradicionais da Matemática. É também um dos algoritmos mais simples:&lt;br /&gt;&lt;center&gt;&lt;img src="http://cacilhas.info/bin/mimetex.cgi?%5Cleft{0!=1%5C%5Cn!=n%5Ccdot(n-1)!" alt="0!=1 n!=n*(n-1)!" /&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;Sua implementação tanto em &lt;a href="http://www.haskell.org/"&gt;Haskell&lt;/a&gt; quanto em &lt;a href="http://clisp.cons.org/"&gt;Common Lisp&lt;/a&gt; descreve exatamente esse algoritmo.&lt;br /&gt;&lt;br /&gt;Em Haskell:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;factorial :: Integer -&amp;gt; Integer&lt;br /&gt;factorial 0 = 1&lt;br /&gt;factorial n = n * (factorial (n - 1))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em Common Lisp:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(defun factorial ((n integer))&lt;br /&gt;  (if (zerop n)&lt;br /&gt;    n&lt;br /&gt;    (* n (factorial (- n 1)))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Já em &lt;a href="http://schemers.org/"&gt;Scheme&lt;/a&gt; a coisa pode complicar… se o interpretador (uso &lt;a href="http://www.gnu.org/software/guile/guile.html"&gt;&lt;code&gt;guile&lt;/code&gt;&lt;/a&gt;) tiver sido compilado com suporte a &lt;a href="http://gmplib.org/"&gt;&lt;em&gt;bignum&lt;/em&gt;&lt;/a&gt;, tudo bem, se não, é preciso fazer uma pequena mágica, multiplicando os resultados do maior para o menor:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(define (factorial n)&lt;br /&gt;  (define (loop k l)&lt;br /&gt;    (if (zero? k)&lt;br /&gt;      l&lt;br /&gt;      (loop (- k 1) (* k l))))&lt;br /&gt;  (loop n 1))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Sequência de Fibonacci&lt;/h3&gt;&lt;br /&gt;A &lt;a href="http://pt.wikipedia.org/wiki/Sequência_de_Fibonacci"&gt;Sequência de Fibonacci&lt;/a&gt; é uma progressão natural iniciando por 1, 1 e progredindo ao passo de que cada elemento é a soma dos dois anteriores:&lt;br /&gt;&lt;center&gt;&lt;img src="http://cacilhas.info/bin/mimetex.cgi?%5Cleft{a_0=1%5C%5Ca_1=1%5C%5Ca_n=a_{n-2}+a_{n-1}" alt="a0=1 a1=1 an=a(n-2)+a(n-1)" /&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;É uma sequência recursiva em árvore binária, o pesadelo dos programadores. =D&lt;br /&gt;&lt;br /&gt;Mas como já foi muito estudada, há diversas formas de implementá-la sem usar código recursivo, como &lt;a href="http://pt.wikipedia.org/wiki/Iteração"&gt;algoritmo reiterativo&lt;/a&gt;, &lt;a href="http://pt.wikipedia.org/wiki/Matriz_(matemática)#Operações_envolvendo_matrizes"&gt;potência de matrizes&lt;/a&gt; e &lt;a href="http://montegasppa.blogspot.com/2006/07/desempenho-de-algoritmos.html"&gt;função fechada&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;A seguinte implementação em Haskell utiliza recursão e lista infinita:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;fib :: [Integer]&lt;br /&gt;fib = 1 : 1 : zipWith (+) fib (tail fib)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Já em Common Lisp foi uma boa ideia usar reiteração, muito mais elegante do que seria possível em qualquer linguagem imperativa:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(defun fib (index)&lt;br /&gt;  (check-type index (integer 0 *))&lt;br /&gt;  (loop&lt;br /&gt;    for a = 1 then b&lt;br /&gt;    and b = 1 then (+ a b)&lt;br /&gt;    repeat index&lt;br /&gt;    finally (return a)))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;em&gt;Quick sort&lt;/em&gt;&lt;/h3&gt;&lt;br /&gt;O &lt;a href="http://pt.wikipedia.org/wiki/Quicksort"&gt;algoritmo de ordenação &lt;em&gt;quick sort&lt;/em&gt;&lt;/a&gt; é a exceção das exceções: um algoritmo de ordenação recursivo em árvore binária, o que deveria ser o pior dos casos, no entanto é um dos métodos de ordenação mais rápidos e eficientes que conhecemos.&lt;br /&gt;&lt;br /&gt;O princípio é o seguinte: toma-se um elemento qualquer da lista, tradicionalmente o primeiro, então separa-se a lista em duas, uma de elementos menores que o tomado e outra de elementos maiores. Aplica-se a mesma ordenação &lt;em&gt;quick sort&lt;/em&gt; a cada uma das novas listas e concatena-as com o elemento tomado no meio.&lt;br /&gt;&lt;br /&gt;Em Haskell isso pode ser descrito assim:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;qsort :: Ord a =&amp;gt; [a] -&amp;gt; [a]&lt;br /&gt;qsort [] = []&lt;br /&gt;qsort (x:xs) = qsort lesser ++ [x] ++ qsort greater&lt;br /&gt;    where&lt;br /&gt;        lesser =  [e | e &amp;lt;- xs, e &amp;lt; x]&lt;br /&gt;        greater = [e | e &amp;lt;- xs, e &amp;gt;= x]&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em Common Lisp o princípio é o mesmo, mas com aquele monte de parêntesis característicos de Lisp:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(defun qsort ((a-list list))&lt;br /&gt;  (if (&amp;lt; (length a-list) 2)&lt;br /&gt;    a-list&lt;br /&gt;    (let ((x (pop a-list)))&lt;br /&gt;      (concatenate 'list&lt;br /&gt;        (qsort&lt;br /&gt;          (loop for e in a-list&lt;br /&gt;            if (&amp;lt; e x)&lt;br /&gt;              collect e))&lt;br /&gt;        (list x)&lt;br /&gt;        (qsort&lt;br /&gt;          (loop for e in a-list&lt;br /&gt;            if (&amp;gt;= e x)&lt;br /&gt;              collect e))))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Espero que este artigo tenha sido interessante e cause curiosidade aos leitores sobre programação funcional.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-716295691748370467?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/716295691748370467/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=716295691748370467' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/716295691748370467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/716295691748370467'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/10/mais-sobre-programacao-funcional.html' title='Mais sobre programação funcional'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_rGfO7DAuOSE/Rgv00nwEXZI/AAAAAAAAAB8/r59qEVD0qOE/s72-c/haskell.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-7637611925033835765</id><published>2009-10-16T21:46:00.012-03:00</published><updated>2009-10-20T20:42:42.320-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lisp'/><category scheme='http://www.blogger.com/atom/ns#' term='Funcional'/><category scheme='http://www.blogger.com/atom/ns#' term='Haskell'/><title type='text'>Oddwording de novo</title><content type='html'>&lt;img style="border: medium none ; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://photos1.blogger.com/blogger/6505/3295/200/prog.png" alt="Poliedro" /&gt; Em maio de 2007 publiquei um &lt;a href="http://kodumaro.blogspot.com/2007/05/oddwording.html"&gt;artigo&lt;/a&gt; sobre a implementação do algoritmo &lt;em&gt;oddwording&lt;/em&gt; em diversas linguagens de programação.&lt;br /&gt;&lt;br /&gt;Para relembrar, segue o código em &lt;a href="http://www.haskell.org/"&gt;Haskell&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;module Main where&lt;br /&gt;&lt;br /&gt;import IO&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;main = mainloop&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;mainloop :: IO ()&lt;br /&gt;mainloop = do&lt;br /&gt;    ph &amp;lt;- readString&lt;br /&gt;    if ph == ""&lt;br /&gt;        then&lt;br /&gt;            return ()&lt;br /&gt;        else do&lt;br /&gt;            let nph = oddword ph&lt;br /&gt;            putStrLn nph&lt;br /&gt;            mainloop&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;readString :: IO String&lt;br /&gt;readString = do&lt;br /&gt;    putStrLn "Digite uma frase: "&lt;br /&gt;    putStr "&amp;gt; "&lt;br /&gt;    hFlush stdout&lt;br /&gt;    s &amp;lt;- getLine&lt;br /&gt;    return s&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;oddword :: String -&amp;gt; String&lt;br /&gt;oddword s = listToStr $ invodd $ strToList s&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;strToList :: String -&amp;gt; [String]&lt;br /&gt;strToList "" = []&lt;br /&gt;strToList s = (take spi s) : (strToList (drop (incr spi) s))&lt;br /&gt;    where spi = nextspace s&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;incr :: Int -&amp;gt; Int&lt;br /&gt;incr = (+ 1)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;nextspace :: String -&amp;gt; Int&lt;br /&gt;nextspace "" = 0&lt;br /&gt;nextspace (x:xs) =&lt;br /&gt;    if x == ' '&lt;br /&gt;        then&lt;br /&gt;            0&lt;br /&gt;        else&lt;br /&gt;            1 + (nextspace xs)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;listToStr :: [String] -&amp;gt; String&lt;br /&gt;listToStr [] = ""&lt;br /&gt;listToStr (x:xs) = x ++ " " ++ (listToStr xs)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;invodd :: Ord a =&amp;gt; [[a]] -&amp;gt; [[a]]&lt;br /&gt;invodd [] = []&lt;br /&gt;invodd (x:xs) = x : (inveven xs)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;inveven :: Ord a =&amp;gt; [[a]] -&amp;gt; [[a]]&lt;br /&gt;inveven [] = []&lt;br /&gt;inveven (x:xs) = (inv x) : (invodd xs)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;inv :: Ord a =&amp;gt; [a] -&amp;gt; [a]&lt;br /&gt;inv [] = []&lt;br /&gt;inv (x:xs) = (inv xs) ++ [x]&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;&amp;lt;update ressaca&amp;gt;&lt;/tt&gt;&lt;br /&gt;Havia esquecido de forçar o &lt;em&gt;flush&lt;/em&gt; de STOUT na função &lt;code&gt;readString&lt;/code&gt;. Corrigido!&lt;br /&gt;&lt;tt&gt;&amp;lt;/update&amp;gt;&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;No entanto ficou faltando uma linguagem excepcionalmente importante, &lt;a href="http://www.lisp.org/"&gt;Lisp&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Lisp (LISt Processing) é uma família de linguagens funcionais concebida por John McCarthy em 1958, baseada no &lt;a href="http://pt.wikipedia.org/wiki/Cálculo_lambda"&gt;cálculo lambda&lt;/a&gt;. As principais linguagens da família Lisp são &lt;a href="http://clisp.cons.org/"&gt;Common Lisp&lt;/a&gt;, &lt;a href="http://schemers.org/"&gt;Scheme&lt;/a&gt; e &lt;a href="http://www.gnu.org/software/emacs/manual/html_mono/elisp.html"&gt;Emacs Lisp&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;O código acima será reimplementado abaixo em Common Lisp.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Observação:&lt;/strong&gt; os blocos de código deverão ser escritos em arquivo na ordem &lt;strong&gt;inversa&lt;/strong&gt; em que aparecem aqui, ou seja, digite cada bloco no arquivo em linhas acima do bloco digitado anteriormente.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Ciclo principal&lt;/h3&gt;&lt;br /&gt;O ciclo principal será a função &lt;code&gt;mainloop&lt;/code&gt;. Sua lógica de funcionamento é a seguinte:&lt;br /&gt;&lt;ol&gt; &lt;li&gt;Pegar uma &lt;em&gt;string&lt;/em&gt; digitada na entrada padrão;&lt;/li&gt; &lt;li&gt;Se a &lt;em&gt;string&lt;/em&gt; for vazia, sair do programa;&lt;/li&gt; &lt;li&gt;Aplicar o algoritmo &lt;em&gt;oddwording&lt;/em&gt;;&lt;/li&gt; &lt;li&gt;Exibir na tela o resultado;&lt;/li&gt; &lt;li&gt;Recomeçar o ciclo.&lt;/li&gt; &lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;A função fica assim:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(defun mainloop ()&lt;br /&gt;  (loop do&lt;br /&gt;    (format t "~&amp;amp;~a~%"&lt;br /&gt;      (oddword (*exit-if-empty* (*read-string*))))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Lendo uma linha da entrada padrão&lt;/h3&gt;&lt;br /&gt;Para ler uma linha da entrada padrão, devemos exibir um &lt;em&gt;prompt&lt;/em&gt;, ler a entrada digitada pelo usuário e remover os espaços em branco do começo e do fim:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(defun *read-string* ()&lt;br /&gt;  (format t "~&amp;amp;Digite uma frase:~%&amp;gt; ")&lt;br /&gt;  (string-trim " " (read-line)))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Saindo caso a &lt;em&gt;string&lt;/em&gt; esteja vazia&lt;/h3&gt;&lt;br /&gt;Caso nada tenha sido digitado, o programa encerra. Para isso é preciso avaliar a &lt;em&gt;string&lt;/em&gt;, encerrando o processo se apropriado, caso contrário retornar a &lt;em&gt;string&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(defun *exit-if-empty* ((a-string string))&lt;br /&gt;  (if (string= a-string "")&lt;br /&gt;    (exit)&lt;br /&gt;    a-string))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Descrição do algoritmo em alto nível&lt;/h3&gt;&lt;br /&gt;Podemos agora definir em alto nível o algoritmo &lt;em&gt;oddwording&lt;/em&gt;:&lt;br /&gt;&lt;ol&gt; &lt;li&gt;Transformar a &lt;em&gt;string&lt;/em&gt; em uma lista de palavras;&lt;/li&gt; &lt;li&gt;Inverter somente o conteúdo dos elementos de índice ímpar da lista;&lt;/li&gt; &lt;li&gt;Transformar novamente a lista de palavras em uma &lt;em&gt;string&lt;/em&gt;.&lt;/li&gt; &lt;/ol&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(defun oddword ((a-string string))&lt;br /&gt;  (list-to-str (invodd (str-to-list a-string))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;em&gt;String&lt;/em&gt; para lista&lt;/h3&gt;&lt;br /&gt;Para transformar uma &lt;em&gt;string&lt;/em&gt; em uma lista, basta quebrada em cada ocorrência de espaço (&lt;code&gt;#&amp;#92;Space&lt;/code&gt;):&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(defun str-to-list ((a-string string))&lt;br /&gt;  (loop&lt;br /&gt;    for i = 0 then (1+ j)&lt;br /&gt;    as j = (position #&amp;#92;Space a-string :start i)&lt;br /&gt;    collect (subseq a-string i j)&lt;br /&gt;    while j))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Lista para &lt;em&gt;string&lt;/em&gt;&lt;/h3&gt;&lt;br /&gt;Para transformar uma lista de palavras em uma &lt;em&gt;string&lt;/em&gt; única, é preciso concatenar todos os elementos da lista, sem esquecer de acrescentar espaços entre eles:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(defun list-to-str ((a-list list))&lt;br /&gt;  (string-trim " "&lt;br /&gt;    (apply #'concatenate 'string&lt;br /&gt;      (loop for e in a-list&lt;br /&gt;        collect (concatenate 'string e " ")))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Inversão dos elementos ímpares&lt;/h3&gt;&lt;br /&gt;Só faltou inverter os elementos de índice ímpar da lista. Nada mais simples: pegar cada elemento, se o índice for ímpar, inverter:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(defun invodd ((a-list list))&lt;br /&gt;  (loop&lt;br /&gt;    for x in a-list&lt;br /&gt;    and i from 0&lt;br /&gt;    collect (if (oddp i)&lt;br /&gt;      (reverse x)&lt;br /&gt;      x)))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Fazendo funcionar&lt;/h3&gt;&lt;br /&gt;Para que tudo aconteça, no &lt;strong&gt;final&lt;/strong&gt; do arquivo acrescente uma chamada à função principal:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;(mainloop)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E execute o arquivo com o comando &lt;code&gt;clisp&lt;/code&gt; (aconselho o uso dos parâmetros &lt;code&gt;-K&amp;nbsp;full&lt;/code&gt; e &lt;code&gt;-q&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Lisp tem uma abordagem extremamente elegante e clara, aproveita o paradigma funcional perfeitamente e seus programas podem ser retroalimentados recursivamente para obter-se um comportamento de aprendizado, apreciado no desenvolvimento de &lt;a href="http://pt.wikipedia.org/wiki/Inteligência_artificial"&gt;IA&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;&amp;lt;update 2009-10-20&amp;gt;&lt;/tt&gt;&lt;br /&gt;Adicionada tipagem aos argumentos das funções e removido código redundante.&lt;br /&gt;&lt;tt&gt;&amp;lt;/update&amp;gt;&lt;/tt&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-7637611925033835765?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/7637611925033835765/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=7637611925033835765' title='3 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/7637611925033835765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/7637611925033835765'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/10/oddwording-2.html' title='O&lt;em&gt;ddwording&lt;/em&gt; de novo'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-4978013544784863230</id><published>2009-10-06T21:20:00.005-03:00</published><updated>2009-10-06T21:31:37.620-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><category scheme='http://www.blogger.com/atom/ns#' term='Smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='Tcl'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Basic'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>IDEs em ambiente GNU/Linux</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://photos1.blogger.com/blogger/6505/3295/200/prog.png" alt="Poliedro" /&gt; Semana passada escrevi um artigo sobre alguns &lt;a href="http://pt.wikipedia.org/wiki/Ambiente_de_desenvolvimento_integrado"&gt;ambientes de desenvolvimento integrado&lt;/a&gt; e editores de texto, alguns deles &lt;a href="http://pt.wikipedia.org/wiki/Rapid_Application_Development"&gt;RAD&lt;/a&gt;. No entanto o artigo ficou muito longo, daí tive a ideia de quebrá-lo em três partes.&lt;br /&gt;&lt;br /&gt;Publiquei em meu &lt;em&gt;blog&lt;/em&gt; &lt;a href="http://montegasppa.blogspot.com/"&gt;Reflexões de Monte Gasppa e Giulia C.&lt;/a&gt;, mas agora, pensando bem, acho que cabe pelo menos uma referência aqui no &lt;a href="http://kodumaro.blogspot.com/"&gt;Kodumaro&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;As três partes do artigo são:&lt;br /&gt;&lt;ol&gt; &lt;li&gt;&lt;a href="http://montegasppa.blogspot.com/2009/10/ide-1.html"&gt;Editores de texto&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://montegasppa.blogspot.com/2009/10/ide-2.html"&gt;IDEs focadas em projeto&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://montegasppa.blogspot.com/2009/10/ide-3.html"&gt;RAD&lt;/a&gt;&lt;/li&gt; &lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;A quem se interessar, boa leitura!&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-4978013544784863230?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/4978013544784863230/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=4978013544784863230' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/4978013544784863230'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/4978013544784863230'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/10/ides-em-ambiente-gnu-linux.html' title='IDEs em ambiente GNU/Linux'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-2511996179269125893</id><published>2009-08-21T11:00:00.001-03:00</published><updated>2009-08-21T11:02:19.360-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Evento'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Dev in Rio 2009</title><content type='html'>Gente,&lt;br /&gt;&lt;br /&gt;Notícia fresquinha no &lt;a href="http://henriquebastos.net/2009/08/21/dev-in-rio-2009-eu-vou/"&gt;&lt;em&gt;blog&lt;/em&gt; do Henrique Bastos&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;h2&gt;Dev in Rio 2009: EU VOU!&lt;/h2&gt;&lt;br /&gt;Finalmente o Rio de Janeiro ganhou um grande evento de tecnologia focado no que é mais importante: &lt;strong&gt;Pessoas&lt;/strong&gt;!&lt;br /&gt;&lt;br /&gt;É com muito orgulho que apresentamos o &lt;a href="http://devinrio.com.br"&gt;&lt;strong&gt;&lt;em&gt;Dev in Rio 2009&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;, uma conferência bombástica sobre desenvolvimento de software que acontecerá no próximo dia &lt;strong&gt;14 de setembro&lt;/strong&gt; no &lt;a href="http://www.ccsulamerica.com.br/PgLocalizacao.php"&gt;Centro de Convenções SulAmérica&lt;/a&gt;, no Rio de Janeiro!&lt;br /&gt;&lt;br /&gt;O &lt;a href="http://devinrio.com.br"&gt;&lt;strong&gt;&lt;em&gt;Dev in Rio 2009&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;, contará com palestrantes nacionais e internacionais que falarão sobre &lt;a href="http://java.sun.com/"&gt;Java&lt;/a&gt;, &lt;a href="http://www.ruby-lang.org/"&gt;Ruby&lt;/a&gt; e &lt;a href="http://rubyonrails.org/"&gt;Ruby on Rails&lt;/a&gt;, &lt;a href="http://python.org"&gt;Python&lt;/a&gt;, &lt;a href="http://djangoproject.com"&gt;Django&lt;/a&gt;, &lt;a href="http://www.opensource.org/"&gt;Open Source&lt;/a&gt;, &lt;a href="http://www.joomla.org/"&gt;Joomla!&lt;/a&gt;, &lt;a href="http://improveit.com.br/xp/manifesto_agil"&gt;Métodos Ágeis&lt;/a&gt;, e muito mais. Nomes como &lt;a title="Akita é a referência de Rails no Brasil." href="http://akitaonrails.com/"&gt;Fábio Akita&lt;/a&gt;, &lt;a title="Vinícius é especialista em Extreme Programming e produtos Web." href="http://improveit.com.br/"&gt;Vinícius Manhães Teles&lt;/a&gt;, &lt;a title="Jacob é co-criador do Django" href="http://jacobian.org"&gt;Jacob Kaplan-Moss&lt;/a&gt;, &lt;a title="Conheça mais sobre o Guilherme e sua particpação na Comunidade Java." href="http://guilhermesilveira.wordpress.com/"&gt;Guilherme Silveira&lt;/a&gt;, &lt;a title="Conheça mais sobre o Nico e seu trabalho na Caelum." href="http://blog.caelum.com.br/"&gt;Nico Steppat&lt;/a&gt;, &lt;a title="Conheça o Ryan e seu trabalho com Open Source e Joomla!" href="http://www.picnet.net/blog/author/cozimek/"&gt;Ryan Ozimek&lt;/a&gt; e &lt;a title="Jeff é consultor especializado em métodos ágeis." href="http://www.agileproductdesign.com/"&gt;Jeff Patton&lt;/a&gt; agitarão um dia inteiro de muita tecnologia e diversão. Veja a &lt;a href="http://devinrio.com.br"&gt;programação detalhada&lt;/a&gt; no site da &lt;a href="http://devinrio.com.br/"&gt;&lt;strong&gt;&lt;em&gt;Dev in Rio 2009&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Mas não é só isso. Como eu disse no início, este é um evento focado em &lt;strong&gt;pessoas&lt;/strong&gt;. Toda a organização do evento está voltada para promover ao máximo a interação e integração entre os presentes.&lt;br /&gt;&lt;br /&gt;Por isso, o &lt;a href="http://devinrio.com.br/"&gt;&lt;strong&gt;&lt;em&gt;Dev in Rio 2009&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; contará com uma &lt;a href="http://dojorio.org"&gt;Arena DojoRio&lt;/a&gt; onde participantes e palestrantes poderão programar lado à lado, experimentando diversas linguagens e técnicas, buscando juntos as melhores formas de desenvolver software.&lt;br /&gt;&lt;br /&gt;O evento está sendo organizado por &lt;a href="http://henriquebastos.net"&gt;mim (Henrique Bastos)&lt;/a&gt; em parceria com o meu amigo &lt;a href="http://gc.blog.br/2009/08/20/dev-in-rio-2009-eu-vou/"&gt;Guilherme Chapiewski&lt;/a&gt;, contando com todo o apoio dos membros da  &lt;a href="http://pythonrio.org"&gt;PythOnRio&lt;/a&gt;, &lt;a href="http://dojorio.org"&gt;DojoRio&lt;/a&gt; e &lt;a href="http://horaextra.org"&gt;#Horaextra&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;A realização está sendo coordenada pelas nossas experientes amigas da  &lt;a href="http://www.arteccom.com.br"&gt;Arteccom&lt;/a&gt;. E tê-las ao nosso lado já garante que este será um evento para marcar o circuito carioca.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Você&lt;/strong&gt; não pode perder esta incrível oportunidade de participar desse mega evento, interagir com grandes nomes do cenário mundial de tecnologia, conhecer pessoas interessantes que compartilham a paixão pelo desenvolvimento de software, e ainda por cima começar sua semana só na terça-feira. &lt;a href="http://devinrio.com.br"&gt;Inscreva-se já!&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;Nos vemos por lá!&lt;/strong&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;[]’s!&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-2511996179269125893?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/2511996179269125893/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=2511996179269125893' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/2511996179269125893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/2511996179269125893'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/08/dev-in-rio-2009.html' title='Dev in Rio 2009'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-3640145799036930672</id><published>2009-07-01T19:01:00.004-03:00</published><updated>2009-08-01T11:45:11.752-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><title type='text'>Ponteiro opaco</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 100px; height: 119px; border: none;" src="http://4.bp.blogspot.com/_rGfO7DAuOSE/Skfqi_b3SZI/AAAAAAAAAPw/LGCcKqN8ONI/s200/gcc.jpg" alt="GCC" id="BLOGGER_PHOTO_ID_5352504569017878930" /&gt; Muitas vezes programadores de &lt;a href="http://www.cplusplus.com/"&gt;C++&lt;/a&gt; e &lt;a href="http://java.sun.com"&gt;Java&lt;/a&gt; confundem &lt;a href="http://pt.wikipedia.org/wiki/Encapsulamento"&gt;encapsulamento&lt;/a&gt; com &lt;strong&gt;ocultação&lt;/strong&gt;, o que não é a intenção da &lt;a href="http://pt.wikipedia.org/wiki/Orientação_a_objetos"&gt;orientação a objetos&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;No entanto, o contrário da ocultação, a &lt;strong&gt;exposição&lt;/strong&gt;, também não é desejável para o encapsulamento, pois causa uma confusão entre &lt;a href="http://en.wikipedia.org/wiki/Interface_(computer_science)"&gt;interface&lt;/a&gt; e &lt;a href="http://en.wikipedia.org/wiki/Implementation"&gt;implementação&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Em C++, a declaração de uma classe força a exposição de sua estrutura privada. Um exemplo bem simples:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class X {&lt;br /&gt;    public:&lt;br /&gt;        X(int);&lt;br /&gt;        ~X();&lt;br /&gt;&lt;br /&gt;        int get(void) const;&lt;br /&gt;&lt;br /&gt;    private:&lt;br /&gt;        int value;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Neste exemplo insanamente simples, é possível ver a estrutura privada da classe &lt;code&gt;X&lt;/code&gt;, o que no caso não é um problema muito sério, mas em casos ligeiramente mais complexos, é possível &lt;a href="http://kodumaro.blogspot.com/2009/01/atributos-privados-onde.html"&gt;corromper o encapsulamento&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Uma forma de resolver o problema é usando um &lt;a href="http://en.wikipedia.org/wiki/Design_pattern"&gt;&lt;em&gt;design pattern&lt;/em&gt;&lt;/a&gt;&amp;sup1; chamado &lt;a href="http://en.wikipedia.org/wiki/Opaque_pointer"&gt;ponteiro opaco&lt;/a&gt; ou &lt;em&gt;Pimpl&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;A ideia é que a classe de interface seja apenas uma moldura (&lt;em&gt;wrapper&lt;/em&gt;) para a classe de implementação. A classe de implementação é declarada no corpo da classe de interface, mas nada é exposto ali.&lt;br /&gt;&lt;br /&gt;A classe de implementação vai ser finalmente implementada no arquivo onde os métodos da classe de interface são implementados. Os métodos da classe de interface então simplemente chamam os métodos da classe de implementação.&lt;br /&gt;&lt;br /&gt;Voltemos ao exemplo&amp;hellip; o arquivo de cabeçalho de nossa classe (&lt;code&gt;x.h&lt;/code&gt; por exemplo) passa a ser:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class X {&lt;br /&gt;    class Ximpl;&lt;br /&gt;&lt;br /&gt;    public:&lt;br /&gt;        X(int);&lt;br /&gt;        ~X();&lt;br /&gt;&lt;br /&gt;        int get(void) const;&lt;br /&gt;&lt;br /&gt;    private:&lt;br /&gt;        Ximpl *pimpl;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Como é possível ver, nada da implementação está exposto.&lt;br /&gt;&lt;br /&gt;Então a classe de implementação é finalmente definida no arquivo de implementação (&lt;code&gt;x.cc&lt;/code&gt;):&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class X::Ximpl {&lt;br /&gt;    public:&lt;br /&gt;        Ximpl(int);&lt;br /&gt;        ~Ximpl();&lt;br /&gt;&lt;br /&gt;        int get(void) const;&lt;br /&gt;&lt;br /&gt;    private:&lt;br /&gt;        int value;&lt;br /&gt;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O resto do código fica:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;X::X(int value): pimpl(new X::Ximpl(value)) {&lt;br /&gt;    // Nada mais a fazer&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;X::Ximpl::Ximpl(int value): value(value) {&lt;br /&gt;    // Nada mais a fazer&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;X::~X() {&lt;br /&gt;    delete this-&amp;gt;pimpl;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;X::Ximpl::~Ximpl() {&lt;br /&gt;    // Nada mais a fazer&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;X::get(void) const {&lt;br /&gt;    return this-&amp;gt;pimpl-&amp;gt;get();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;X::Ximpl::get(void) const {&lt;br /&gt;    return this-&amp;gt;value;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;É claro que é um &lt;em&gt;pattern&lt;/em&gt; extremamente &lt;strong&gt;desconfortável&lt;/strong&gt;, pois é preciso implementar cada método duas vezes, uma para a classe de interface, outra para a classe de implementação&amp;hellip; e há sim formas melhores de fazer isso.&lt;br /&gt;&lt;br /&gt;Mas &lt;em&gt;Pimpl&lt;/em&gt; funciona, é uma saída viável e pode salvar sua vida. =D&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&lt;tt&gt;[update 2009-08-01]&lt;/tt&gt;Sugestão de leitura de &lt;a href="http://0xc0de.wordpress.com/"&gt;0xc0de&lt;/a&gt;: &lt;a href="http://www.gotw.ca/gotw/024.htm"&gt;Compilation Firewalls&lt;/a&gt;.&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&amp;sup1; &lt;em&gt;Design patterns&lt;/em&gt;: antes que me crucifiquem por usar esta expressão fora do mundinho pequeno de Java, a definição de &lt;em&gt;design pattern&lt;/em&gt; é «um jeito formal de documentar a solução para um problema de desenvolvimento», o que define corretamente ponteiro opaco.&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-3640145799036930672?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/3640145799036930672/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=3640145799036930672' title='4 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/3640145799036930672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/3640145799036930672'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/07/pimpl.html' title='Ponteiro opaco'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_rGfO7DAuOSE/Skfqi_b3SZI/AAAAAAAAAPw/LGCcKqN8ONI/s72-c/gcc.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-8181852037886965787</id><published>2009-06-28T19:10:00.010-03:00</published><updated>2009-06-29T21:22:28.812-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><title type='text'>Variaridade</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 100px; height: 119px; border: none;" src="http://4.bp.blogspot.com/_rGfO7DAuOSE/Skfqi_b3SZI/AAAAAAAAAPw/LGCcKqN8ONI/s200/gcc.jpg" alt="GCC" id="BLOGGER_PHOTO_ID_5352504569017878930" /&gt; Uma &lt;a href="http://en.wikipedia.org/wiki/Variadic_function"&gt;função &lt;del&gt;&lt;em&gt;variádica&lt;/em&gt;&lt;/del&gt; variária&lt;/a&gt; &amp;ndash; em inglês &lt;strong&gt;&lt;em&gt;variadic&lt;/em&gt;&lt;/strong&gt;, &lt;em&gt;variable arity&lt;/em&gt;, aridade&amp;sup1; variável &amp;ndash; é aquela que suporta uma quantidade variável de parâmetros.&lt;br /&gt;&lt;br /&gt;Muitas linguagens suportam funções variárias, aliás de forma bem simples. &lt;a href="http://python.org/"&gt;Python&lt;/a&gt; usa o operador &lt;code&gt;*&lt;/code&gt; para indicar quantidade variável de parâmetros, &lt;a href="http://www.lua.org/"&gt;Lua&lt;/a&gt; usa o operador &lt;code&gt;...&lt;/code&gt; e &lt;a href="http://clisp.cons.org/"&gt;Common Lisp&lt;/a&gt; o operador &lt;code&gt;&amp;amp;rest&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Outras linguagens podem ser ainda mais simples, como por exemplo &lt;a href="http://www.perl.org/"&gt;Perl&lt;/a&gt;, onde toda função é variária e os parâmetros são recebidos na lista &lt;code&gt;@_&lt;/code&gt;, tradicionalmente capturados por &lt;code&gt;shift&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Já &lt;a href="http://java.sun.com/"&gt;Java&lt;/a&gt; não suporta funções verdadeiramente variárias devido a sua limitação forçada de tipagem, no entanto é possível simular com o uso de &lt;code&gt;Object&lt;/code&gt; e &lt;em&gt;casting&lt;/em&gt; («vazamento» na falta de uma tradução melhor):&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;void myFunction(Object... args) {&lt;br /&gt;    // Código do método&lt;br /&gt;    …&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Funções variárias em C/C++&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://pt.wikipedia.org/wiki/C_(linguagem_de_programação)"&gt;C&lt;/a&gt;/&lt;a href="http://www.cplusplus.com/"&gt;C++&lt;/a&gt; usa o cabeçalho &lt;a href="http://en.wikipedia.org/wiki/Stdarg.h"&gt;&lt;code&gt;stdarg.h&lt;/code&gt;&lt;/a&gt; para suporte a funções variárias.&lt;br /&gt;&lt;br /&gt;O exemplo apresentado na &lt;a href="http://en.wikipedia.org/wiki/Stdarg.h"&gt;Wikipédia&lt;/a&gt; é bastante simples: uma função &lt;code&gt;printargs&lt;/code&gt; que recebe uma quantidade arbitrária de números inteiros, encerrando com -1 (ou qualquer número negativo em nosso exemplo), e os exibe na saída padrão.&lt;br /&gt;&lt;br /&gt;Precisamos incluir dois cabeçalhos em C++, &lt;code&gt;cstdarg&lt;/code&gt; para suporte a funções variária e &lt;code&gt;cstdio&lt;/code&gt; para exibir o resultado:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#include &amp;lt;cstdio&amp;gt;&lt;br /&gt;#include &amp;lt;cstdarg&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ou, em C:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdarg.h&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A assinatura da função fica assim:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;void printargs(int arg1, ...) {&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para acesso aos parâmetros múltiplos é usado um objeto &lt;code&gt;va_list&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    va_list args;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A função &lt;code&gt;va_start()&lt;/code&gt; inicializa o objeto. Ela recebe dois parâmetros: o objeto &lt;code&gt;va_list&lt;/code&gt; e o nome do último argumento antes da lista:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    va_start(args, arg1);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Portanto é preciso haver pelo menos um argumento antes da lista variável. Podemos então exibir o primeiro parâmetro, recebido no argumento &lt;code&gt;arg1&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    printf("%d", arg1);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A função &lt;code&gt;va_arg()&lt;/code&gt; retorna o argumento seguinte. Ela recebe como parâmetros o objeto &lt;code&gt;va_list&lt;/code&gt; e o tipo do parâmetro da lista a ser recuperado.&lt;br /&gt;&lt;br /&gt;O tipo precisar ser plenamente promovido, ou seja, ponteiro, inteiro, ponto flutuante ou precisão dupla. Outros tipos, como &lt;code&gt;char&lt;/code&gt; precisam sofrer &lt;em&gt;casting&lt;/em&gt;, como por exemplo (&lt;strong&gt;não faz parte do código de &lt;code&gt;printargs&lt;/code&gt;&lt;/strong&gt;):&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;char c = static_cast&amp;lt;char&amp;gt;(va_arg(va, int));&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Continuando o código, podemos agora reiterar sobre os resultados de &lt;code&gt;va_arg()&lt;/code&gt; até encontrarmos o valor de parada negativo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    int arg;&lt;br /&gt;    while((arg = va_arg(args, int)) &gt;= 0)&lt;br /&gt;        printf(" %d", arg);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Após o fim da reiteração dos parâmetros obtidos do objeto &lt;code&gt;va_list&lt;/code&gt; através de &lt;code&gt;va_arg()&lt;/code&gt;, é preciso encerrar o objeto:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    va_end(arg);&lt;br /&gt;    printf("\n");&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Caso você queira restringir o formato de entrada da função, isso é possível usando &lt;code&gt;__attribute__&lt;/code&gt; em sua declaração. Por exemplo, se a função &lt;code&gt;log()&lt;/code&gt; recebe o nível de &lt;em&gt;log&lt;/em&gt; como primeiro parâmetro, uma &lt;em&gt;string&lt;/em&gt; de formatação como segundo parâmetro (&lt;code&gt;2&lt;/code&gt;) e os parâmetros variáveis a partir do terceiro (&lt;code&gt;3&lt;/code&gt;), com formato similar ao da função &lt;code&gt;printf()&lt;/code&gt;, isso é feito com a seguinte assinatura:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;extern void&lt;br /&gt;log(int level, cons char *fmt, ...)&lt;br /&gt;__attribute__((format(printf, 2, 3)));&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As opções para &lt;code&gt;format()&lt;/code&gt; são &lt;code&gt;printf&lt;/code&gt;, &lt;code&gt;scanf&lt;/code&gt;, &lt;code&gt;strftime&lt;/code&gt; e &lt;code&gt;strfmon&lt;/code&gt;. Veja &lt;a href="http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Function-Attributes.html"&gt;Declaring Attributes of Functions&lt;/a&gt; da documentação do &lt;a href="http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/"&gt;GCC&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;small&gt;&amp;sup1;Aridade: em Matemática é o número de operandos de uma função.&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-8181852037886965787?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/8181852037886965787/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=8181852037886965787' title='3 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8181852037886965787'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8181852037886965787'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/06/variadic.html' title='Variaridade'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_rGfO7DAuOSE/Skfqi_b3SZI/AAAAAAAAAPw/LGCcKqN8ONI/s72-c/gcc.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-1057086620735538448</id><published>2009-05-14T19:03:00.001-03:00</published><updated>2009-05-14T19:04:34.699-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tcl'/><title type='text'>Um «Olá Mundo!» pequenininho</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left;" src="http://photos1.blogger.com/blogger/6505/3295/200/tcl.jpg" alt="tcl.jpg" /&gt; Como este &lt;em&gt;blog&lt;/em&gt; estava muito parado, resolvi postar um «Olá Mundo!» com janela de duas linhas em &lt;a href="http://wiki.tcl.tk/"&gt;Tcl/Tk&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;wm title . Hello&lt;br /&gt;grid [ button .bt -text { Olá Mundo! } -command exit ]&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Se preferir, pode ser criado um &lt;em&gt;script&lt;/em&gt; autoexecutável acrescentando o &lt;em&gt;hash-bang&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#!/bin/sh&lt;br /&gt;#&amp;#92;&lt;br /&gt;exec wish "$0" "$@"&lt;br /&gt;&lt;br /&gt;wm title . Hello&lt;br /&gt;grid [ button .bt -text { Olá Mundo! } -command exit ]&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-1057086620735538448?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/1057086620735538448/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=1057086620735538448' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/1057086620735538448'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/1057086620735538448'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/05/um-ola-mundo-pequenininho.html' title='Um «Olá Mundo!» pequenininho'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-4749053583994587531</id><published>2009-03-19T00:01:00.012-03:00</published><updated>2009-03-19T11:57:22.376-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Sobre APIs</title><content type='html'>Umas das coisas mais importantes em programação, sem a qual ninguém consegue desevolver, é &lt;a href="http://pt.wikipedia.org/wiki/API"&gt;API&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;API &amp;ndash; Interface de Programação de Aplicativos &amp;ndash; é o conjunto de recursos de que o programador dispõe para desenvolver suas aplicações.&lt;br /&gt;&lt;br /&gt;Este artigo faz uma comparação &amp;ndash; na verdade, mais uma demonstração &amp;ndash; de cinco APIs muito usadas: &lt;a href="http://ieeexplore.ieee.org/xpl/freeabs_all.jsp?tp=&amp;isnumber=4694975&amp;arnumber=4694976&amp;punumber=4694974"&gt;IEEE 1003&lt;/a&gt;, &lt;a href="http://www.cplusplus.com/reference/"&gt;STL&lt;/a&gt;, &lt;a href="http://www.gnustep.org/resources/OpenStepSpec/OpenStepSpec.html"&gt;OpenStep&lt;/a&gt;, &lt;a href="http://library.gnome.org/devel/glib/stable/"&gt;GLib&lt;/a&gt; e &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/"&gt;Java&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Para a demonstração será usado um trecho de código para ler a primeira linha de um arquivo.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Por que não a API do Windows?&lt;/h3&gt;&lt;br /&gt;Antes de começar, é preciso esclarecer por que não a &lt;a href="http://msdn.microsoft.com/pt-br/default.aspx"&gt;API do Windows&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;O objetivo de uma API é oferecer um ambiente homogêneo de programação, para que o programador não seja obrigado a reaprender a mesma coisa diversas vezes. Para facilitar isso, muitas APIs ainda podem ser usadas em diversas linguagens diferentes, outras em apenas uma.&lt;br /&gt;&lt;br /&gt;No entanto uma API que funciona apenas em um único sistema operacional &amp;ndash; ou ainda no grupo de sistemas operacionais de uma única empresa &amp;ndash; não está fazendo seu trabalho, por mais usado que esse(s) sistema(s) possa ser.&lt;br /&gt;&lt;br /&gt;Assim a API do Windows não faz mais do que se espera da interface de um sistema operacional.&lt;br /&gt;&lt;br /&gt;É claro que é necessário que o Windows possua uma API, mesmo que seja exclusivamente para conexão de outras APIs mais universais.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;IEEE 1003 (POSIX)&lt;/h3&gt;&lt;br /&gt;O padrão POSIX, definido pela &lt;a href="http://www.ieee.org/"&gt;IEEE&lt;/a&gt;, oferece uma interface completa para sistemas compatíveis com &lt;a href="http://www.unix.org/"&gt;UNIX&lt;/a&gt;. Alguns exemplos são &lt;a href="http://www.ibm.com/servers/aix"&gt;IBM AIX&lt;/a&gt;, &lt;a href="http://br.sun.com/practice/software/solaris/"&gt;Solaris&lt;/a&gt;, &lt;a href="http://www.gnu.org/"&gt;GNU&lt;/a&gt; (e daí também Linux), &lt;a href="http://www.bsd.org/"&gt;BSD&lt;/a&gt;, &lt;a href="http://www.apple.com/br/macosx/"&gt;Mac OS&amp;nbsp;X&lt;/a&gt;, &lt;a href="http://pt.wikipedia.org/wiki/Xenix"&gt;MS Xenix&lt;/a&gt; e muitos outros.&lt;br /&gt;&lt;br /&gt;O trecho de código em &lt;a href="http://pt.wikipedia.org/wiki/C_(linguagem_de_programação)"&gt;C&lt;/a&gt; para ler a primeira linha de um arquivo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;FILE *fd = fopen(filename, "r");&lt;br /&gt;&lt;br /&gt;if (fd) {&lt;br /&gt;    while (!eof(fd)) {&lt;br /&gt;        char buf;&lt;br /&gt;        fread(&amp;amp;buf, sizeof(char), 1, fd);&lt;br /&gt;        printf("%c", buf);&lt;br /&gt;        if (buf == '&amp;#92;n')&lt;br /&gt;            break;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    fclose(fd);&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Observação&lt;sup&gt;1&lt;/sup&gt;: é preciso incluir o cabeçalho &lt;code&gt;stdio.h&lt;/code&gt; ou, em C++, &lt;code&gt;cstdio&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Observação&lt;sup&gt;2&lt;/sup&gt;: a variável &lt;code&gt;filename&lt;/code&gt; é do tipo &lt;code&gt;const&amp;nbsp;char&amp;nbsp;*&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Observação&lt;sup&gt;3&lt;/sup&gt;: foi preciso procurar ocorrência do carácter &lt;code&gt;&amp;#92;n&lt;/code&gt; pois POSIX não ofereça uma função de alto nível para ler uma linha.&lt;br /&gt;&lt;br /&gt;Observação&lt;sup&gt;4&lt;/sup&gt;: o padrão POSIX é completamente procedimental &amp;ndash; as demais APIs citadas aqui são orientadas a objetos &amp;ndash;, sendo um pouco desajeitado para algumas operações.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;STL&lt;/h3&gt;&lt;br /&gt;A linguagem de programação &lt;a href="http://www.cplusplus.com/"&gt;C++&lt;/a&gt; possui uma biblioteca padrão própria bastante completa chamada STL &amp;ndash; Standard Library.&lt;br /&gt;&lt;br /&gt;Para o exemplo, é preciso incluir o cabeçalho &lt;code&gt;fstream&lt;/code&gt; para a manipulação de arquivo e o cabeçalho &lt;code&gt;iostream&lt;/code&gt; para a exibição dos dados na tela:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;std::ifstream fd(filename);&lt;br /&gt;&lt;br /&gt;if (fd.is_open()) {&lt;br /&gt;    char buf[1024];&lt;br /&gt;    fd.getline(buf, 1023);&lt;br /&gt;&lt;br /&gt;    std::cout &amp;lt;&amp;lt; buf &amp;lt;&amp;lt; std::endl;&lt;br /&gt;    fd.close();&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Observação&lt;sup&gt;1&lt;/sup&gt;: como citado acima, é preciso incluir pelo menos o cabeçalho &lt;code&gt;fstream&lt;/code&gt; ao manipular arquivos:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#include &amp;lt;fstream&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Observação&lt;sup&gt;2&lt;/sup&gt;: a variável &lt;code&gt;filename&lt;/code&gt; precisa ser do tipo &lt;code&gt;const&amp;nbsp;char&amp;nbsp;*&lt;/code&gt; &amp;ndash; &lt;code&gt;std::ifstream&lt;/code&gt; não suporta &lt;code&gt;std::string&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;OpenStep&lt;/h3&gt;&lt;br /&gt;A empresa &lt;a href="http://www.dmoz.org/Computers/Software/Operating_Systems/Microkernel/Mach/NeXT/"&gt;NeXT&lt;/a&gt; de Steve Jobs, ora adquirida pela &lt;a href="http://www.apple.com/"&gt;Apple&lt;/a&gt;, abriu a API de seu sistema operacional em 1992 num acordo com a &lt;a href="http://www.sun.com/"&gt;SUN Microsystems&lt;/a&gt;, sob o nome de OpenStep, o que permitiu, além da criação de aplicações de terceiros para NeXTSTEP, também o desenvolvimento de outros sistemas operacionais compatíveis com sua API e APIs de programação para sistemas já existentes, tornando-os compatíveis com OpenStep.&lt;br /&gt;&lt;br /&gt;Exemplos de sistemas compatíveis com essa API são &lt;a href="http://www.apple.com/br/macosx/"&gt;Mac OS&amp;nbsp;X&lt;/a&gt; e &lt;a href="http://gnustep.org/"&gt;GNUstep&lt;/a&gt; (portável para Windows e qualquer plataforma compatível com POSIX).&lt;br /&gt;&lt;br /&gt;A API OpenStep funciona exclusivamente em &lt;a href="http://pt.wikipedia.org/wiki/Objective-C"&gt;Objective-C&lt;/a&gt;, apesar de haver alguns portes para outras linguagens, como C++, &lt;a href="http://smalltalk.org/"&gt;Smalltalk&lt;/a&gt; e &lt;a href="http://www.gnu.org/software/guile/guile.html"&gt;Guile Scheme&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Vamos ao exemplo em Objective-C:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;id fd = [NSFileHandle fileHandleForReadingAtPath: filename];&lt;br /&gt;&lt;br /&gt;if (fd != nil) {&lt;br /&gt;    char buf = 0;&lt;br /&gt;    [fd seekToEndOfFile];&lt;br /&gt;    unsigned long long eof = [fd offsetFile];&lt;br /&gt;    [fd seekToFileOffset: 0];&lt;br /&gt;&lt;br /&gt;    while (([fd offsetInFile] &amp;lt; eof) &amp;amp;&amp;amp; (buf != '&amp;#92;n')) {&lt;br /&gt;        [[fd readDataOfLength: 1] getBytes: &amp;amp;buf length: 1];&lt;br /&gt;        printf("%c", buf);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    [fd closeFile];&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Observação&lt;sup&gt;1&lt;/sup&gt;: é preciso importar o cabeçalho &lt;code&gt;Foundation.h&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Observação&lt;sup&gt;2&lt;/sup&gt;: a variável &lt;code&gt;filename&lt;/code&gt; precisa ser do tipo &lt;code&gt;NSString&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Observação&lt;sup&gt;3&lt;/sup&gt;: &lt;strong&gt;eu&lt;/strong&gt; não conheço um método para ler uma linha de um arquivo em OpenStep, portanto usei um esquema similar ao usado acima em POSIX.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;GLib&lt;/h3&gt;&lt;br /&gt;A GLib começou como parte do &lt;em&gt;toolkit&lt;/em&gt; gráfico &lt;a href="http://www.gtk.org/"&gt;Gtk+&lt;/a&gt; na versão 2.0, tendo evoluído para se tornar uma API multiplataforma orientada a objetos completa e independente da interface gráfica.&lt;br /&gt;&lt;br /&gt;Você pode usar GLib em qualquer sistema POSIX e em Windows.&lt;br /&gt;&lt;br /&gt;A maior curiosidade da GLib é que ela deixa explícita o equívoco &amp;ndash; ou a falácia &amp;ndash; de quem crê que não seja possível programar orientado a objetos em uma linguagem não orientada a objetos: é escrita em C e completamente orientada a objetos.&lt;br /&gt;&lt;br /&gt;Aliás a base da GLib é o &lt;a href="http://library.gnome.org/devel/gobject/stable/"&gt;GObject&lt;/a&gt; que, curiosamente, não é compatível com a estrutura de orientação a objetos de C++ e outras linguagens clássicas, apesar de haver portes para C++ e outras.&lt;br /&gt;&lt;br /&gt;O exemplo a seguir é um trecho de código em &lt;a href="http://live.gnome.org/Vala"&gt;Vala&lt;/a&gt;, linguagem criada expecificamente para a GLib:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;var file = File.new_for_path(filename);&lt;br /&gt;&lt;br /&gt;if (file.query_exists(null)) {&lt;br /&gt;    try {&lt;br /&gt;        var fd = new DataInputStream(file.read(null));&lt;br /&gt;        stdout.printf("%s&amp;#92;n", fd.read_line(null, null));&lt;br /&gt;        fd.close(null);&lt;br /&gt;    } catch (Error e) {&lt;br /&gt;        // Ignora exceções&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;[update 2009-03-19]&lt;/tt&gt;Faltou o &lt;code&gt;close&lt;/code&gt;.&lt;tt&gt;[/update]&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;Observação&lt;sup&gt;1&lt;/sup&gt;: é preciso «usar» &lt;code&gt;GLib&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;using GLib;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Observação&lt;sup&gt;2&lt;/sup&gt;: a variável &lt;code&gt;filename&lt;/code&gt; é do tipo &lt;code&gt;string&lt;/code&gt; &amp;ndash; equivalente em C a &lt;code&gt;GString&lt;/code&gt; e &lt;code&gt;gchar&amp;nbsp;*&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Observação&lt;sup&gt;3&lt;/sup&gt;: é preciso usar o pacote (&lt;code&gt;--pkg&lt;/code&gt;) &lt;code&gt;gio-2.0&lt;/code&gt;, que importa GIO, recursos de I/O da GLib.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Java&lt;/h3&gt;&lt;br /&gt;Em sua linguagem de programação, a SUN Microsystems optou por criar uma API própria (bem complicada e verborrágica em relação às demais, diga-se).&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;BufferedReader fd = null;&lt;br /&gt;try {&lt;br /&gt;    fd = new BufferedReader(new FileReader(filename));&lt;br /&gt;    System.out.println(fd.readLine());&lt;br /&gt;&lt;br /&gt;} catch (Exception e) {&lt;br /&gt;    // Ignora exceções&lt;br /&gt;&lt;br /&gt;} finally {&lt;br /&gt;    try {&lt;br /&gt;        if (fd != null)&lt;br /&gt;            fd.close();&lt;br /&gt;    } catch (IOException e) {&lt;br /&gt;        // Ignora exceções&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Observação&lt;sup&gt;1&lt;/sup&gt;: as classes usadas estão no pacote &lt;code&gt;java.io&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;import java.io.BufferedReader;&lt;br /&gt;import java.io.FileReader;&lt;br /&gt;import java.io.IOException;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Observação&lt;sup&gt;2&lt;/sup&gt;: a variável &lt;code&gt;filename&lt;/code&gt; é do tipo &lt;code&gt;String&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Fica aqui a dica de três APIs interessantes.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-4749053583994587531?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/4749053583994587531/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=4749053583994587531' title='9 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/4749053583994587531'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/4749053583994587531'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/03/api.html' title='Sobre APIs'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-5790388600982301128</id><published>2009-03-11T22:05:00.013-03:00</published><updated>2009-04-01T23:13:55.745-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Quem vai pra Vala?</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 100px; height: 100px; border: none;" src="http://1.bp.blogspot.com/_rGfO7DAuOSE/SbhgHqf0qYI/AAAAAAAAAOI/2b3cylnjqy4/s200/live-gnome.jpg" alt="live.gnome.org" id="BLOGGER_PHOTO_ID_5312101445266614658" /&gt; Dessa vez o pessoal do &lt;a href="http://live.gnome.org/"&gt;Gnome&lt;/a&gt; acertou a mão. Estou falando da &lt;a href="http://live.gnome.org/Vala"&gt;linguagem de programação Vala&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Até hoje, quem queria programar em &lt;a href="http://pt.wikipedia.org/wiki/C_Sharp"&gt;C#&lt;/a&gt; era obrigado a usar ou um &lt;a href="http://www.microsoft.com/windows/"&gt;sistema operacional problemático&lt;/a&gt;, ou uma &lt;a href="http://www.mono-project.com/"&gt;ferramenta monstruosamente pesada e ineficiente&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Não mais.&lt;br /&gt;&lt;br /&gt;O projeto Gnome lançou há algum tempo a linguagem Vala, fortemente baseada na sintaxe do C#, mas voltada para aplicações Gnome. Quem manja de C# ou maja de &lt;a href="http://java.sun.com/"&gt;Java&lt;/a&gt; e já viu C# não terá dificuldade em lidar com Vala.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Instalação&lt;/h3&gt;&lt;br /&gt;Segundo a &lt;a href="http://live.gnome.org/Vala"&gt;página do projeto&lt;/a&gt;, Vala foi feito para plataforma Gnome. Surgiu aí meu primeiro problema: uso &lt;a href="http://www.slackware.org/"&gt;Slackware&lt;/a&gt; e o &lt;a href="http://pt.wikipedia.org/wiki/Patrick_Volkerding"&gt;Volkerding&lt;/a&gt; decidiu que Slackware não terá mais suporte a Gnome! Em sua total substituição, há o &lt;a href="http://www.xfce.org/"&gt;Xfce&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Simplesmente não há um pacote oficial de Gnome para Slackware &amp;ndash; e os não-oficiais que já experimentei simplesmente detonaram o sistema todo.&lt;br /&gt;&lt;br /&gt;Ainda mais: e quem usa outros SOs? Se não tiver Gnome já era?&lt;br /&gt;&lt;br /&gt;Qual não foi minha agradável surpresa quando descobri que &lt;strong&gt;Vala compilou e instalou sem problemas no Slackware 12.2&lt;/strong&gt;?! Sua dependência verdadeira é GTK+ 2.x, que você encontra em praticamente qualquer distribuição GNU/Linux ou &lt;a href="http://www.bsd.org/"&gt;BSD&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;E Windows? &lt;a href="http://live.gnome.org/Vala/ValaOnWindows"&gt;Também tem!&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Usando&lt;/h3&gt;&lt;br /&gt;Um «Olá Mundo» em Vala é bastante simples (tanto quanto Java, pelo menos):&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;using GLib;&lt;br /&gt;&lt;br /&gt;public class HelloWorld : Object {&lt;br /&gt;    public static int main(string[] args) {&lt;br /&gt;        stdout.printf("Olá Mundo!\n");&lt;br /&gt;        return 0;&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ao contrário do &lt;a href="http://msdn.microsoft.com/netframework/"&gt;.NET&lt;/a&gt;, não há código escondido do programador. Por exemplo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;using GLib;&lt;br /&gt;&lt;br /&gt;public class HelloWorld : Object {&lt;br /&gt;&lt;br /&gt;    private Gtk.Window window;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public HelloWorld() {&lt;br /&gt;        window = new Gtk.Window(Gtk.WindowType.TOPLEVEL);&lt;br /&gt;        window.set_default_size(300, 200);&lt;br /&gt;        window.destroy += Gtk.main_quit;&lt;br /&gt;        window.add(new Gtk.Label("Olá Mundo!"));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public void show() {&lt;br /&gt;        window.show_all();&lt;br /&gt;        Gtk.main();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public static int main (string[] args) {&lt;br /&gt;        Gtk.init(ref args);&lt;br /&gt;        var sample = new HelloWorld();&lt;br /&gt;        sample.show();&lt;br /&gt;&lt;br /&gt;        return 0;&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;del&gt;Antes que alguém reclame, peço desculpas pelos códigos mal orientados a objetos, mas não quis ter muito o que explicar.&lt;/del&gt;&lt;br /&gt;&lt;tt&gt;[update]&lt;/tt&gt;Ajeitei pra ninguém ficar me chateando.&lt;tt&gt;[/update]&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Maturidade&lt;/h3&gt;&lt;br /&gt;Estranhamente a linguagem já está bastante madura na &lt;a href="http://live.gnome.org/Vala/Release"&gt;0.5.7&lt;/a&gt;. Não encontrei quebras inusitadas nem erros bizarros.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update 2009-04-01]&lt;/tt&gt;&lt;br /&gt;Encontrei uma quebra inusitada: Vala não lida bem com &lt;a href="http://pt.wikipedia.org/wiki/Closure"&gt;&lt;em&gt;closures&lt;/em&gt;&lt;/a&gt; e escopo dinâmico. Ela se perde um pouco gerando alguns erros inesperados.&lt;br /&gt;&lt;br /&gt;Outro erro inconveniente está na API com C: o &lt;em&gt;bind&lt;/em&gt; de método destruidor não suporta parâmetros, o que pode ocorrer em alguns casos da GLib &amp;ndash; lembre-se do que não há métodos destruidores reais em C, mas sim funções de desalocação.&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;A única coisa que tenho a reclamar &lt;strong&gt;muito&lt;/strong&gt; é a documentação precária, bem longe das documentações de API bem organizadas da &lt;a href="http://java.sun.com/j2se/1.4.2/docs/api/"&gt;SUN Microsystems&lt;/a&gt; e da &lt;a href="http://msdn.microsoft.com/"&gt;Microsoft&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;IDE&lt;/h3&gt;&lt;br /&gt;Por enquanto há uma IDE chamada &lt;a href="http://www.valaide.org/"&gt;Val(a)IDE&lt;/a&gt; &amp;ndash; só que essa já desarmou na minha cara algumas vezes &amp;ndash; e a promessa de uma &lt;a href="https://launchpad.net/valable"&gt;extensão&lt;/a&gt; para o &lt;a href="http://www.eclipse.org/"&gt;Eclipse&lt;/a&gt; &amp;ndash; que ainda não apareceu na página da própria extensão.&lt;br /&gt;&lt;br /&gt;Segundo a &lt;a href="http://live.gnome.org/Vala"&gt;página official&lt;/a&gt;, há também extensões para &lt;a href="http://anonsvn.mono-project.com/source/trunk/monodevelop/extras/ValaBinding/"&gt;MonoDevelop&lt;/a&gt; (Deus me livre!) e para &lt;a href="http://vtg.googlecode.com/"&gt;GEdit&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;**&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;É isso aí! Quando eu ganhar um pouco mais de intimidade com a linguagem, escrevo mais alguma coisa. Por enquanto foi só divulgação. Um tutorial meia-boca pode ser encontrado &lt;a href="http://live.gnome.org/Vala/Tutorial"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-5790388600982301128?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/5790388600982301128/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=5790388600982301128' title='9 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5790388600982301128'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5790388600982301128'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/03/vala.html' title='Quem vai pra Vala?'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_rGfO7DAuOSE/SbhgHqf0qYI/AAAAAAAAAOI/2b3cylnjqy4/s72-c/live-gnome.jpg' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-3333194749440288105</id><published>2009-03-04T12:25:00.002-03:00</published><updated>2009-03-04T12:27:12.761-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Calculadora científica com o Vim</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://photos1.blogger.com/blogger/6505/3295/200/python.png" alt="" /&gt; Desta vez vou &lt;em&gt;reblogar&lt;/em&gt;&amp;hellip;&lt;br /&gt;&lt;br /&gt;O &lt;a href="http://www.blogger.com/profile/11511626443237920795"&gt;voyeg3r&lt;/a&gt; publicou um artigo curtinho e muito legal sobre como criar uma calculadora científica no &lt;a href="http://www.vim.org/"&gt;Vim&lt;/a&gt; usando &lt;a href="http://python.org/"&gt;Python&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;O artigo pode ser encontrado no &lt;a href="http://vivaotux.blogspot.com/2009/03/calculadora-cientifica-com-o-vim.html"&gt;vivaotux&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Boa leitura!&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-3333194749440288105?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/3333194749440288105/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=3333194749440288105' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/3333194749440288105'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/3333194749440288105'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/03/calculadora-cientifica-com-o-vim.html' title='Calculadora científica com o Vim'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-6235602295320517129</id><published>2009-01-29T23:30:00.008-03:00</published><updated>2009-08-26T22:06:08.116-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Propriedades e acessores</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://photos1.blogger.com/blogger/6505/3295/200/python.png" alt="" /&gt; Em &lt;a href="http://java.sun.com"&gt;Java&lt;/a&gt; e em &lt;a href="http://http://www.cplusplus.com/"&gt;C++&lt;/a&gt; há um bom motivo para que os atributos sejam sempre privados: preservar a interface das classes.&lt;br /&gt;&lt;br /&gt;Por exemplo, imagine que temos uma classe que representa o registro de uma pessoa. Nela temos a idade. Sendo um número inteiro, poderia ser um atributo público:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;Person person;&lt;br /&gt;person.age = 23;&lt;br /&gt;std::cout &amp;lt;&amp;lt; person.age &amp;lt;&amp;lt; std::endl;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Faz sentido. Agora imagine que mais tarde descobrimos que é preciso fazer um tratamento do valor recebido &amp;ndash; para estar numa faixa aceitável, por exemplo&amp;hellip;&lt;br /&gt;&lt;br /&gt;Sem alterar a interface &amp;ndash; e efetuar uma refatoração total de todo código onde ocorre instância &amp;ndash; é impossível.&lt;br /&gt;&lt;br /&gt;Então, em Java e C++ é &lt;strong&gt;importante&lt;/strong&gt; usar métodos acessores e manter os atributos privados. Dessa forma qualquer alteração futura pode ser feita na classe sem alterar o restante do código:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;Person person;&lt;br /&gt;person.setAge(23);&lt;br /&gt;std::cout &amp;lt;&amp;lt; person.getAge() &amp;lt;&amp;lt; std::endl;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Propriedades&lt;/h3&gt;&lt;br /&gt;Já em &lt;a href="http://python.org/"&gt;Python&lt;/a&gt; isso não faz sentido!&lt;br /&gt;&lt;br /&gt;Em Python, além de atributos e métodos, há as propriedades. Então atributos podem ser públicos e, caso seja necessário adicionar alguma lógica na leitura ou gravação do atributo, basta substituí-lo por uma propriedade, sem prejudicar a interface.&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class Person:&lt;br /&gt;&lt;br /&gt;    def __init__(self):&lt;br /&gt;        self.name = ""&lt;br /&gt;        self.age = 0&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Substituindo por propriedades:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class Person:&lt;br /&gt;&lt;br /&gt;    def __init__(self):&lt;br /&gt;        self.name = ""&lt;br /&gt;        self.__age = 0&lt;br /&gt;&lt;br /&gt;    def _get_age(self):&lt;br /&gt;        return self.__age&lt;br /&gt;&lt;br /&gt;    def _set_age(self, age):&lt;br /&gt;        if 0 &amp;lt;= age &amp;lt; 150:&lt;br /&gt;            self.__age = age&lt;br /&gt;&lt;br /&gt;    age = property(_get_age, _set_age)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E a interface permanece imutável!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Aviso:&lt;/strong&gt; não use propriedade quando não for necessário! Use atributo público. Um pouco de desempenho não faz mal a ninguém, mesmo em &lt;em&gt;scripts&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Aviso&amp;sup2;: testei esse código no &lt;em&gt;prompt&lt;/em&gt; e não funciona, mas funciona em &lt;em&gt;script&lt;/em&gt;. Se alguém puder descobrir o que está acontecendo, agradeço.&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;[update 2009-08-26]&lt;/tt&gt;Usando &lt;a href="http://ipython.scipy.org/moin/"&gt;IPython&lt;/a&gt; funcionou corretamente, portanto não sei o que causou o erro. =P&lt;br /&gt;&lt;br /&gt;Assim assim, valeu &lt;a href="http://thiagoc.net/"&gt;Thiago Coutinho&lt;/a&gt; por tê-lo identificado (acho que ainda ocorre durante a interpretação em linha do CPython tradicional).&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Usando metaclasse&lt;/h3&gt;&lt;br /&gt;Uma forma de implementar automaticamente autopropriedades foi sugerida por Guido van Rossum em &lt;a href="http://www.pythonbrasil.com.br/moin.cgi/UnificandoTiposClasses"&gt;Unificando Tipos e Classes&lt;/a&gt; (&lt;a href="http://python.org/download/releases/2.2.3/descrintro/"&gt;original&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Usaremos uma metaclasse:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class autoprop(type):&lt;br /&gt;&lt;br /&gt;    def __init__(cls, name, base, dict):&lt;br /&gt;        super(autoprop, cls).__init__(name, base, dict)&lt;br /&gt;        props = {}&lt;br /&gt;        for method in dict:&lt;br /&gt;            if method.startswith("_get_") \&lt;br /&gt;                or method.startswith("_set_") \&lt;br /&gt;                or method.startswith("_del_"):&lt;br /&gt;                props[method[5:]] = True&lt;br /&gt;        for prop in props:&lt;br /&gt;            fget = getattr(cls, "_get_" + prop, None)&lt;br /&gt;            fset = getattr(cls, "_set_" + prop, None)&lt;br /&gt;            fdel = getattr(cls, "_del_" + prop, None)&lt;br /&gt;            setattr(cls, prop, property(fget, fset, fdel))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A ideia por trás dessa metaclasse é identificar métodos iniciados por &lt;code&gt;_get_&lt;/code&gt;, &lt;code&gt;_set_&lt;/code&gt; ou &lt;code&gt;_del_&lt;/code&gt; e criar propriedades a partir daí. O método iniciado por &lt;code&gt;_get_&lt;/code&gt; representa a leitura, &lt;code&gt;_set_&lt;/code&gt; representa a escrita e &lt;code&gt;_del_&lt;/code&gt; representa a remoção.&lt;br /&gt;&lt;br /&gt;Nossa classe então ficaria assim:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class Person:&lt;br /&gt;    __metaclass__ = autoprop&lt;br /&gt;&lt;br /&gt;    def __init__(self):&lt;br /&gt;        self.name = ""&lt;br /&gt;        self.__age = 0&lt;br /&gt;&lt;br /&gt;    def _get_age(self):&lt;br /&gt;        return self.__age&lt;br /&gt;&lt;br /&gt;    def _set_age(self, age):&lt;br /&gt;        if 0 &amp;lt;= age &amp;lt; 150:&lt;br /&gt;            self.__age = age&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Usando decoradores&lt;/h3&gt;&lt;br /&gt;Mas realmente, ao contrário da metaclasse para &lt;a href="http://kodumaro.blogspot.com/2009/01/s-ingleton.html"&gt;&lt;em&gt;singleton&lt;/em&gt;&lt;/a&gt;, usar metaclasse para autopropriedade é como usar uma escopeta para espantar uma mosca.&lt;br /&gt;&lt;br /&gt;Vamos usar decoradores!&lt;br /&gt;&lt;br /&gt;O decorador &lt;code&gt;@property&lt;/code&gt; pode ser usado para criar propriedades para apenas leitura. Como precisamos de leitura e gravação, podemos usar &lt;code&gt;@apply&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;É um pouco &lt;em&gt;gambiarrático&lt;/em&gt;, mas funciona muito bem e deixa o código relativamente limpo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class Person:&lt;br /&gt;&lt;br /&gt;    def __init__(self):&lt;br /&gt;        self.name = ""&lt;br /&gt;        self.__age = 0&lt;br /&gt;&lt;br /&gt;    @apply&lt;br /&gt;    def age():&lt;br /&gt;        def fget(self):&lt;br /&gt;            return self.__age&lt;br /&gt;&lt;br /&gt;        def fset(self, age):&lt;br /&gt;            if 0 &amp;lt;= age &amp;lt; 150:&lt;br /&gt;                self.__age = age&lt;br /&gt;&lt;br /&gt;        return property(**locals())&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A função deve ter o nome da propriedade. O método de escrita deve chamar-se &lt;code&gt;fset&lt;/code&gt;, o de leitura &lt;code&gt;fget&lt;/code&gt; e o de remoção &lt;code&gt;fdel&lt;/code&gt;. A parte mais feia desse código é o retorno. =)&lt;br /&gt;&lt;br /&gt;**&lt;br /&gt;&lt;br /&gt;Fica aqui a dica!&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-6235602295320517129?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/6235602295320517129/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=6235602295320517129' title='16 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/6235602295320517129'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/6235602295320517129'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/01/propriedades.html' title='Propriedades e acessores'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-329129268178961671</id><published>2009-01-28T20:53:00.008-03:00</published><updated>2009-01-29T08:42:04.557-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Interface fluente</title><content type='html'>Outro &lt;a href="http://en.wikipedia.org/wiki/Design_pattern"&gt;&lt;em&gt;pattern&lt;/em&gt;&lt;/a&gt; interessante é conhecido como &lt;a href="http://en.wikipedia.org/wiki/Fluent_interface"&gt;&lt;em&gt;carrying return&lt;/em&gt;&lt;/a&gt; (não confundir com &lt;em&gt;carriage return&lt;/em&gt;, carácter com código ASCII 13).&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update 2009-01-29]&lt;/tt&gt;Esse era o nome dado há uns anos atrás, quando conheci esse &lt;em&gt;pattern&lt;/em&gt;. Porém ele não ganhou espaço entre os programadores na época e poucos continuaram usando (como eu). =P&lt;br /&gt;&lt;br /&gt;Hoje em dia ele voltou com o nome &lt;em&gt;Fluent Interface&lt;/em&gt;, Interface Fluente.&lt;br /&gt;&lt;br /&gt;A propósito, troquei o título deste artigo para usar uma linguagem mais nova e mais fácil de ser reconhecida.&lt;br /&gt;&lt;br /&gt;Valeu &lt;a href="http://devlog.waltercruz.com/"&gt;Walter&lt;/a&gt; e &lt;a href="http://www.blogger.com/profile/06234409817785100127"&gt;Lucas&lt;/a&gt;!&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;del&gt;Há outros nomes, mas não consigo encontrar no &lt;a href="http://www.google.com/search?q=fluent+interface"&gt;São Google&lt;/a&gt;, pois não é um &lt;em&gt;pattern&lt;/em&gt; muito usado.&lt;/del&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Parecido com Smalltalk&lt;/h3&gt;&lt;br /&gt;Imagine que você tem uma classe &lt;a href="http://java.sun.com/"&gt;Java&lt;/a&gt; que recebe muitos parâmetros na instanciação:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;Person person = new Person(&lt;br /&gt;    aString, aDate, anotherString, aLoad, aPerson, anotherPerson&lt;br /&gt;);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A quantidade de argumentos pode explodir ao extremo. &lt;a href="http://python.org/"&gt;Python&lt;/a&gt; pode apresentar maior visibilidade quanto ao significado dos parâmetros:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;person = Person(&lt;br /&gt;    name=aString,&lt;br /&gt;    birthdate=aDate,&lt;br /&gt;    id=anotherString,&lt;br /&gt;    load=aLoad,&lt;br /&gt;    father=aPerson,&lt;br /&gt;    mother=anotherPerson&lt;br /&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://smalltalk.org/"&gt;Smalltalk&lt;/a&gt;, uma linguagem bem mais antiga do que Python ou Java, já tinha uma abordagem bem mais elegante:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;person := Person new.&lt;br /&gt;person&lt;br /&gt;    setName:      aString;&lt;br /&gt;    setBirthdate: aDate;&lt;br /&gt;    setId:        anotherString;&lt;br /&gt;    setLoad:      aLoad;&lt;br /&gt;    setFather:    aPerson;&lt;br /&gt;    setMother:    anotherPerson.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;É possível conseguir um código similar em Java usando acessores tipo &lt;em&gt;setter&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;Person person = new Person();&lt;br /&gt;person.setName(aString);&lt;br /&gt;person.setBirthdate(aDate);&lt;br /&gt;person.setId(anotherString);&lt;br /&gt;person.setLoad(aLoad);&lt;br /&gt;person.setFather(aPerson);&lt;br /&gt;person.setMother(anotherPerson);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Finalmente&lt;/h3&gt;&lt;br /&gt;Mas é possível obter um código ainda mais elegante usando o &lt;em&gt;pattern&lt;/em&gt; em questão.&lt;br /&gt;&lt;br /&gt;A ideia é simples: em vez dos acessores &lt;em&gt;setter&lt;/em&gt; não terem retorno (&lt;code&gt;void&lt;/code&gt;), basta eles retornarem &lt;code&gt;this&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class Person {&lt;br /&gt;    private String name;&lt;br /&gt;    private Date birthdate;&lt;br /&gt;    private String id;&lt;br /&gt;    private Load load;&lt;br /&gt;    private Person father;&lt;br /&gt;    private Person mother;&lt;br /&gt;&lt;br /&gt;    public Person() {&lt;br /&gt;        name = null;&lt;br /&gt;        birthdate = null;&lt;br /&gt;        id = null;&lt;br /&gt;        load = null;&lt;br /&gt;        father = null;&lt;br /&gt;        mother = null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String getName() {&lt;br /&gt;        return name;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Person setName(String name) {&lt;br /&gt;        this.name = name;&lt;br /&gt;        return this;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Date getBirthdate() {&lt;br /&gt;        return birthdate;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Person setBirthdate(Date birthdate) {&lt;br /&gt;        this.birthdate = birthdate;&lt;br /&gt;        return this;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Load getLoad() {&lt;br /&gt;        return load;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Person setLoad(Load load) {&lt;br /&gt;        this.load = load;&lt;br /&gt;        return this;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Person getFather() {&lt;br /&gt;        return father;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Person setFather(Person father) {&lt;br /&gt;        this.father = father;&lt;br /&gt;        return this;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Person getMother() {&lt;br /&gt;        return mother;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Person setMother(Person mother) {&lt;br /&gt;        this.mother = mother;&lt;br /&gt;        return this;&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora podemos usar uma estrutura de código similar à de Smalltalk:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;Person person = new Person()&lt;br /&gt;    .setName(aString)&lt;br /&gt;    .setBirthdate(aDate)&lt;br /&gt;    .setId(anotherString)&lt;br /&gt;    .setLoad(aLoad)&lt;br /&gt;    .setFather(aPerson)&lt;br /&gt;    .setMother(anotherPerson);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-329129268178961671?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/329129268178961671/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=329129268178961671' title='9 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/329129268178961671'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/329129268178961671'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/01/return-this.html' title='Interface fluente'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-4157282883139547208</id><published>2009-01-27T21:39:00.006-03:00</published><updated>2009-01-28T20:52:18.942-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Singleton</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://photos1.blogger.com/blogger/6505/3295/200/python.png" alt="" /&gt; Um &lt;a href="http://en.wikipedia.org/wiki/Design_pattern"&gt;&lt;em&gt;design pattern&lt;/em&gt;&lt;/a&gt; bastante conhecido na engenharia de &lt;em&gt;software&lt;/em&gt; é &lt;a href="http://pt.wikipedia.org/wiki/Singleton"&gt;&lt;em&gt;singleton&lt;/em&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Singleton&lt;/em&gt; é quando uma classe possui apenas uma instância e não se deseja que em uma mesma aplicação haja mais de uma.&lt;br /&gt;&lt;br /&gt;Exemplos de classes desejadamente &lt;em&gt;singleton&lt;/em&gt; são &lt;em&gt;pools&lt;/em&gt; e carregadores.&lt;br /&gt;&lt;br /&gt;Em &lt;a href="http://www.cplusplus.com/"&gt;C++&lt;/a&gt; a saída para criar uma classe &lt;em&gt;singleton&lt;/em&gt; é tornar protegido seu método construtor e criar um método &lt;code&gt;getInstance&lt;/code&gt; para retornar a instância única:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class Loader {&lt;br /&gt;    protected:&lt;br /&gt;        Loader();&lt;br /&gt;&lt;br /&gt;    public:&lt;br /&gt;        ~Loader();&lt;br /&gt;&lt;br /&gt;        static Loader&amp;amp; getInstance();&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O método &lt;code&gt;getInstance&lt;/code&gt; deve guardar uma referência estática para a instância:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;static Loader&amp;amp; Loader::getInstance() {&lt;br /&gt;    static Loader *instance = 0;&lt;br /&gt;    if (!instance)&lt;br /&gt;        instance = new Loader();&lt;br /&gt;    return *instance;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://java.sun.com/"&gt;Java&lt;/a&gt; utiliza a mesma abordagem, já outras linguagens, como &lt;a href="http://www.perl.org/"&gt;Perl&lt;/a&gt;, &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt; e &lt;a href="http://www.ruby-lang.org/en/"&gt;Ruby&lt;/a&gt; têm uma abordagem bem mais elegante.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;&lt;em&gt;Singleton&lt;/em&gt; em Python&lt;/h3&gt;&lt;br /&gt;A ideia de &lt;em&gt;singleton&lt;/em&gt; em Python &amp;ndash; Perl e Ruby &amp;ndash; é usar o próprio construtor da classe para obter a instância.&lt;br /&gt;&lt;br /&gt;Por exemplo, em vez de (Java):&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;Image character = Loader.getInstance().getImage("char.png");&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Teremos (Python):&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;character = Loader().getImage("char.png")&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Há três formas de implementar &lt;em&gt;singleton&lt;/em&gt; em Python: &lt;sup&gt;1&lt;/sup&gt;implementando diretamente na classe, &lt;sup&gt;2&lt;/sup&gt;herdando um classe pai ou &lt;sup&gt;3&lt;/sup&gt;usando metaclasse (o mais divertido!).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Implementação direta na classe&lt;/h3&gt;&lt;br /&gt;Você pode implementar uma classe &lt;em&gt;singleton&lt;/em&gt; diretamente, usando os metamétodos &lt;code&gt;__new__&lt;/code&gt; (construtor real) e &lt;code&gt;__init__&lt;/code&gt; (construtor de inicialização).&lt;br /&gt;&lt;br /&gt;A classe ainda precisa ter um atributo de classe para armazenar a instância.&lt;br /&gt;&lt;br /&gt;A ideia mais simples é implementar &lt;code&gt;__new__&lt;/code&gt; para devolver a instância em vez de uma nova a cada vez:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class Loader:&lt;br /&gt;&lt;br /&gt;    __instance = None&lt;br /&gt;    __initialized = False&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    def __new__(cls, *args, **keyw):&lt;br /&gt;        if cls.__instance is None:&lt;br /&gt;            cls.__instance = object.__new__(cls)&lt;br /&gt;        return cls.__instance&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Repare no atributo &lt;code&gt;__initialized&lt;/code&gt;&amp;hellip; isso é porque ainda temos um problema: o construtor de inicialização (&lt;code&gt;__init__&lt;/code&gt;) será chamado novamente a cada tentativa de obter a instância.&lt;br /&gt;&lt;br /&gt;Então precisamos verificar se a inicialização já foi executada:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    def __init__(self, *args, **keyw):&lt;br /&gt;        if not self.__initialized:&lt;br /&gt;            self.__initialized = True&lt;br /&gt;            # Restante do método...&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Pronto! Nossa classe já é &lt;em&gt;singleton&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Herança&lt;/h3&gt;&lt;br /&gt;Podemos usar uma classe pai que implemente unicidade e estendê-la:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class Singleton:&lt;br /&gt;&lt;br /&gt;    __instance = None&lt;br /&gt;    __initialized = False&lt;br /&gt;&lt;br /&gt;    def __new__(cls, *args, **keyw):&lt;br /&gt;        if cls.__instance is None:&lt;br /&gt;            cls.__instance = object.__new__(cls)&lt;br /&gt;        return cls.__instance&lt;br /&gt;&lt;br /&gt;    def __init__(self, *args, **keyw):&lt;br /&gt;        if not self.__initialized:&lt;br /&gt;            self.__initialized = True&lt;br /&gt;            self._init(*args, **keyw)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Assim, para implementar uma classe &lt;em&gt;singleton&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class Loader(Singleton):&lt;br /&gt;&lt;br /&gt;    def _init(self, *args, **keyw):&lt;br /&gt;        # Este será o construtor...&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A vantagem desta abordagem é sua capacidade de reaproveitamento: é possível reutilizar a classe &lt;code&gt;Singleton&lt;/code&gt; como classe pai de cada nova classe &lt;em&gt;singleton&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;No entanto traz dois inconvenientes: primeiro os métodos podem conflitar com métodos de outras classes pai em herança múltipla; segundo é preciso prestar atenção à implementação estranha (uso de &lt;code&gt;_init&lt;/code&gt; em vez de &lt;code&gt;__init__&lt;/code&gt;) e ter cuidado com a sobrescrita de métodos.&lt;br /&gt;&lt;br /&gt;A solução para tornar isso mais transparente é usar uma metaclasse.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Metaclasse&lt;/h3&gt;&lt;br /&gt;Metaclasse é um classe cujas instâncias são classes. Vamos criar uma metaclasse cujas classes sejam &lt;em&gt;singleton&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class singleton(type):&lt;br /&gt;&lt;br /&gt;    def __init__(cls, name, base, dict):&lt;br /&gt;        super(singleton, cls).__init__(name, base, dict)&lt;br /&gt;        cls.__instance = None&lt;br /&gt;        cls.__copy__ = lambda self: self&lt;br /&gt;        cls.__deepcopy__ = lambda self, memo=None: self&lt;br /&gt;&lt;br /&gt;    def __call__(cls, *args, **keyw):&lt;br /&gt;        if cls.__instance is None:&lt;br /&gt;            cls.__instance = \&lt;br /&gt;                super(singleton, cls).__call__(*args, **keyw)&lt;br /&gt;        return cls.__instance&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora vem a beleza da metaclasse: para criar uma classe &lt;em&gt;singleton&lt;/em&gt; basta fazer:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class Loader:&lt;br /&gt;    __metaclass__ = singleton&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Nada mais! Todo o resto da classe pode ser implementado sem preocupações.&lt;br /&gt;&lt;br /&gt;A única dúvida que pode ocorrer é: e se a classe tiver outra metaclasse?&lt;br /&gt;&lt;br /&gt;É fácil resolver! Por exemplo: imagine uma classe &lt;em&gt;singleton&lt;/em&gt; que implemente autopropriedades:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class Loader:&lt;br /&gt;&lt;br /&gt;    class __metaclass__(autoprop, singleton):&lt;br /&gt;        pass&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;**&lt;br /&gt;&lt;br /&gt;Está aqui outra dica! Mais sobre &lt;em&gt;singleton&lt;/em&gt; pode ser encontrado nas &lt;a href="http://montegasppa.blogspot.com/2006/09/metaclasses-singleton.html"&gt;Reflexões de Monte Gasppa e Giulia C.&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-4157282883139547208?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/4157282883139547208/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=4157282883139547208' title='6 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/4157282883139547208'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/4157282883139547208'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/01/s-ingleton.html' title='S&lt;em&gt;ingleton&lt;/em&gt;'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-7744110868985511599</id><published>2009-01-27T11:06:00.017-03:00</published><updated>2009-01-28T09:08:08.678-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='Shell'/><title type='text'>Mostrando o status e o branch de repositórios git no console</title><content type='html'>Com uma função de &lt;em&gt;shell script&lt;/em&gt; e a ajuda da variável &lt;code&gt;PS1&lt;/code&gt; podemos fazer uma configuração bem interessante: exibir no próprio console em qual &lt;em&gt;branch&lt;/em&gt; estamos e qual o estado dele.&lt;br /&gt;&lt;br /&gt;Um exemplo de como fica:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm4.static.flickr.com/3107/3231618838_62e0b90b3b_o.png"&gt;&lt;img style="display: block; margin: 0pt 10px 10px 0pt; text-align: center; cursor: hand; width: 500px; height: 200px;" src="http://farm4.static.flickr.com/3107/3231618838_ce16c91c0a.jpg" alt="Git no terminal" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Esse é um &lt;em&gt;screenshot&lt;/em&gt; do meu &lt;em&gt;desktop&lt;/em&gt;, mostrando o repositório do &lt;a href="http://getontracks.org/"&gt;tracks&lt;/a&gt; (um aplicativo interessante para quem pretende usar a metodologia GTD). Em amarelo, o caminho do repositório. Entre os colchetes, o &lt;em&gt;branch&lt;/em&gt; no qual estamos, e finalmente, um &lt;code&gt;*&lt;/code&gt; indicando se o repositório contém modificações ainda não confirmadas no repositório.&lt;br /&gt;&lt;br /&gt;Para configurar, basta adicionar ao seu &lt;code&gt;.bashrc&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;function parse_git_dirty {&lt;br /&gt;    [[ $(git status 2&gt; /dev/null | tail -n1) \&lt;br /&gt;        != "nothing to commit (working directory clean)" \&lt;br /&gt;    ]] &amp;amp;&amp;amp; echo "*"&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function parse_git_branch {&lt;br /&gt;    git branch --no-color 2&gt; /dev/null | \&lt;br /&gt;    sed -e '/^[^*]/d' \&lt;br /&gt;        -e "s/* \(.*\)/[\1$(parse_git_dirty)]/"&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;export PS1='\u@\h \[\033[1;33m\]\w\[\033[0m\]$(parse_git_branch)$'&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Visto originalmente &lt;a href="http://henrik.nyh.se/2008/12/git-dirty-prompt"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;- Walter Cruz&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-7744110868985511599?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/7744110868985511599/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=7744110868985511599' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/7744110868985511599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/7744110868985511599'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/01/mostrando-o-status-e-o-branch-de.html' title='Mostrando o status e o branch de repositórios git no console'/><author><name>Walter Cruz</name><uri>http://www.blogger.com/profile/10836863572075307104</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_QrHWeNioH_k/R49C4RsNH6I/AAAAAAAAACc/iaDJgilsVjk/S220/Bodao.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm4.static.flickr.com/3107/3231618838_ce16c91c0a_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-97797765010199340</id><published>2009-01-24T13:11:00.007-03:00</published><updated>2009-01-27T12:46:30.962-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Pyglet</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://photos1.blogger.com/blogger/6505/3295/200/python.png" alt="" /&gt; Há alguns módulos em &lt;a href="http://python.org/"&gt;Python&lt;/a&gt; de interface com a biblioteca de mídia &lt;a href="http://www.libsdl.org/"&gt;SDL&lt;/a&gt;, sendo o mais conhecido &lt;a href="http://pygame.org/"&gt;PyGame&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;PyGame é legal, lembra a mim a antiga API gráfica do Colour BASIC do &lt;a href="http://pt.wikipedia.org/wiki/MSX"&gt;MSX&lt;/a&gt; (eita saudosismo!).&lt;br /&gt;&lt;br /&gt;No entanto o &lt;a href="http://fazerjogos.org/"&gt;Kao Félix&lt;/a&gt; apresentou recentemente um outro módulo menos conhecido, chamado &lt;a href="http://www.pyglet.org/"&gt;Pyglet&lt;/a&gt;, que, a primeira vista, achei mais &lt;em&gt;pythónica&lt;/em&gt;. =D&lt;br /&gt;&lt;br /&gt;Gostaria então de sugirir dois tutoriais do Kao Félix:&lt;br /&gt;&lt;ul&gt; &lt;li&gt;&lt;a href="http://fazerjogos.org/?p=107"&gt;Introdução à pyglet&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://fazerjogos.org/?p=117"&gt;Movimentação Suave e NPC’s na Pyglet&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Instalando Pyglet&lt;/h3&gt;&lt;br /&gt;Se você possui o &lt;a href="http://peak.telecommunity.com/DevCenter/EasyInstall"&gt;EasyInstall&lt;/a&gt;, basta executar:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;sudo easy_install -U pyglet&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Primeira aplicação&lt;/h3&gt;&lt;br /&gt;Resolvi fazer minha primeira aplicação segundo as dicas do Kao Félix, mas adaptando a meu jeito próprio de programar.&lt;br /&gt;&lt;br /&gt;Iniciaremos com o &lt;em&gt;hash-bang&lt;/em&gt;, as peculiaridades de Python e os &lt;code&gt;import&lt;/code&gt;s dos submódulos de Pyglet que vamos precisar:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#!/usr/bin/env python&lt;br /&gt;# coding: UTF-8&lt;br /&gt;&lt;br /&gt;from __future__ import division&lt;br /&gt;__metaclass__ = type&lt;br /&gt;&lt;br /&gt;from pyglet import app, clock, resource, sprite&lt;br /&gt;from pyglet.window import key, Window&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Carregando os recursos iniciais&lt;/h3&gt;&lt;br /&gt;Esta é classe &lt;a href="http://montegasppa.blogspot.com/2006/09/metaclasses-singleton.html"&gt;&lt;em&gt;singleton&lt;/em&gt;&lt;/a&gt; para carregar os recursos de mídia que precisaremos.&lt;br /&gt;&lt;br /&gt;Fiz o seguinte: baixei a &lt;a href="http://fazerjogos.org/wp-content/uploads/2008/11/char.png"&gt;bola&lt;/a&gt; do Kao, mas pode também baixar &lt;a href="http://cacilhas.info/imagens/char.png"&gt;daqui mesmo&lt;/a&gt; &amp;ndash; preferível, para não sobrecarregar o &lt;em&gt;link&lt;/em&gt; dele.&lt;br /&gt;&lt;br /&gt;O arquivo de som está no pacote do KDE, mas você pode baixar &lt;a href="http://cacilhas.info/imagens/pop.wav"&gt;daqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Nessa classe &lt;em&gt;singleton&lt;/em&gt;, implementaremos o método &lt;code&gt;__new__&lt;/code&gt; (apenas para &lt;em&gt;singleton&lt;/em&gt;) e &lt;code&gt;__init__&lt;/code&gt; para carregar as mídias.&lt;br /&gt;&lt;br /&gt;Para carregar uma imagem usamos &lt;code&gt;resource.image()&lt;/code&gt;. Para áudio, &lt;code&gt;resource.media()&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class Loader:&lt;br /&gt;    """Singleton class for loading resources"""&lt;br /&gt;&lt;br /&gt;    __inst = None&lt;br /&gt;    __initialized = False&lt;br /&gt;&lt;br /&gt;    def __new__(cls, *args, **keyw):&lt;br /&gt;        if not cls.__inst:&lt;br /&gt;            cls.__inst = object.__new__(cls)&lt;br /&gt;        return cls.__inst&lt;br /&gt;&lt;br /&gt;    def __init__(self):&lt;br /&gt;        if not self.__initialized:&lt;br /&gt;            self.__initialzed = True&lt;br /&gt;&lt;br /&gt;            self.images = {}&lt;br /&gt;            self.sounds = {}&lt;br /&gt;&lt;br /&gt;            image = resource.image("char.png")&lt;br /&gt;            image.anchor_x = image.width // 2&lt;br /&gt;            image.anchor_y = image.height // 2&lt;br /&gt;            self.images["ball"] = image&lt;br /&gt;&lt;br /&gt;            self.sounds["pop"] = resource.media(&lt;br /&gt;                "pop.wav",&lt;br /&gt;                streaming=False&lt;br /&gt;            )&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O parâmetro &lt;code&gt;streaming=False&lt;/code&gt; indica que o arquivo de áudio deve ser completamente carregado para a memória &amp;ndash; e não tratado como um fluxo (&lt;em&gt;stream&lt;/em&gt;).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Gerenciando o teclado&lt;/h3&gt;&lt;br /&gt;Uma nova classe será usada para gerenciar o teclado. O construtor armazenará uma referência para a janela principal e o método &lt;code&gt;handle_input()&lt;/code&gt; gerenciará as teclas:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class KeyHandler(key.KeyStateHandler):&lt;br /&gt;    """Class for handling key events"""&lt;br /&gt;&lt;br /&gt;    def __init__(self, window):&lt;br /&gt;        super(KeyHandler, self).__init__()&lt;br /&gt;        self.window = window&lt;br /&gt;&lt;br /&gt;    def handle_input(self, dt):&lt;br /&gt;        speed = 320 * dt&lt;br /&gt;        dx, dy = 0, 0&lt;br /&gt;&lt;br /&gt;        if self[key.RIGHT]:&lt;br /&gt;            dx = 1&lt;br /&gt;        elif self[key.LEFT]:&lt;br /&gt;            dx = -1&lt;br /&gt;&lt;br /&gt;        if self[key.UP]:&lt;br /&gt;            dy = 1&lt;br /&gt;        elif self[key.DOWN]:&lt;br /&gt;            dy = -1&lt;br /&gt;&lt;br /&gt;        self.window.ball.x += dx * speed&lt;br /&gt;        self.window.ball.y += dy * speed&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Repare que nosso objeto &lt;code&gt;window&lt;/code&gt; terá um atributo &lt;code&gt;ball&lt;/code&gt;, que é um &lt;a href="http://www.pyglet.org/doc/programming_guide/displaying_images.html#sprites"&gt;&lt;em&gt;sprite&lt;/em&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Agora nosso &lt;em&gt;sprite&lt;/em&gt;&lt;/h3&gt;&lt;br /&gt;Vamos criar agora uma classe que estende &lt;code&gt;sprite.Sprite&lt;/code&gt;, a classe de &lt;em&gt;sprite&lt;/em&gt; de Pyglet.&lt;br /&gt;&lt;br /&gt;O único método que implementaremos será o construtor, que buscará em &lt;code&gt;Loader&lt;/code&gt; a imagem que desejamos:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class Ball(sprite.Sprite):&lt;br /&gt;    """Sprite that's a ball"""&lt;br /&gt;&lt;br /&gt;    def __init__(self, *args, **keyw):&lt;br /&gt;        super(Ball, self).__init__(&lt;br /&gt;            Loader().images["ball"],&lt;br /&gt;            *args, **keyw&lt;br /&gt;        )&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Janela principal&lt;/h3&gt;&lt;br /&gt;Finalmente a aplicação!&lt;br /&gt;&lt;br /&gt;Por um mal hábito adquirido programando &lt;a href="http://docs.python.org/library/tkinter.html"&gt;Tkinter&lt;/a&gt;, tenho o hábito de usar a mesma classe para aplicação e janela principal, porém você não precisa fazer &lt;del&gt;esse bacalhau&lt;/del&gt; isso!&lt;br /&gt;&lt;br /&gt;No entanto vou mostrar aqui da forma como estou habituado.&lt;br /&gt;&lt;br /&gt;O construtor:&lt;br /&gt;&lt;ul&gt; &lt;li&gt;ajustará o título da janela (&lt;code&gt;set_caption()&lt;/code&gt;);&lt;/li&gt; &lt;li&gt;criará uma nova bola (classe &lt;code&gt;Ball&lt;/code&gt;);&lt;/li&gt; &lt;li&gt;registrará o manipulador de eventos de teclas (&lt;code&gt;push_handlers()&lt;/code&gt;);&lt;/li&gt; &lt;li&gt;e registrará o método &lt;code&gt;handle_input()&lt;/code&gt; do manipulador de eventos de teclas para execução periódica (&lt;code&gt;clock.schedule_interval()&lt;/code&gt;).&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class MainApplication(Window):&lt;br /&gt;    """Main window and application"""&lt;br /&gt;&lt;br /&gt;    def __init__(self):&lt;br /&gt;        super(MainApplication, self).__init__()&lt;br /&gt;        self.set_caption("Teste de movimento")&lt;br /&gt;&lt;br /&gt;        self.ball = Ball(x=300, y=240)&lt;br /&gt;&lt;br /&gt;        handler = KeyHandler(self)&lt;br /&gt;        self.push_handlers(handler)&lt;br /&gt;        clock.schedule_interval(handler.handle_input, 1/60)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Manipulando outros eventos&lt;/h3&gt;&lt;br /&gt;Os métodos de &lt;code&gt;Window&lt;/code&gt; que manipulam eventos têm nome iniciado por &lt;code&gt;on_&lt;/code&gt;, seguido pelo nome do evento. Por exemplo: &lt;code&gt;on_close&lt;/code&gt;, &lt;code&gt;on_draw&lt;/code&gt;, &lt;code&gt;on_key_press&lt;/code&gt;, &lt;code&gt;on_key_release&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Vamos implementar &lt;code&gt;on_close()&lt;/code&gt; para tocar o som ao sair e &lt;code&gt;on_draw()&lt;/code&gt; para exibir o &lt;em&gt;sprite&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    def on_close(self):&lt;br /&gt;        Loader().sounds["pop"].play()&lt;br /&gt;        super(MainApplication, self).on_close()&lt;br /&gt;&lt;br /&gt;    def on_draw(self):&lt;br /&gt;        self.clear()&lt;br /&gt;        self.ball.draw()&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Fazendo funcionar&lt;/h3&gt;&lt;br /&gt;Para terminar, precisamos instanciar a aplicação e chamar o ciclo principal de Pyglet.&lt;br /&gt;&lt;br /&gt;&lt;small&gt;Veja que esse tipo de programação onde um módulo toma o controle e programamos os métodos que atenderão eventos caracteriza um &lt;em&gt;framework&lt;/em&gt;.&lt;/small&gt;&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;if __name__ == "__main__":&lt;br /&gt;    window = MainApplication()&lt;br /&gt;    app.run()&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conclusão&lt;/h3&gt;&lt;br /&gt;Vemos aqui um ótimo módulo &amp;ndash; ou melhor, &lt;em&gt;framework&lt;/em&gt; &amp;ndash; para criação de aplicações gráficas usando as bibliotecas SDL e &lt;a href="http://opengl.org/"&gt;OpenGL&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-97797765010199340?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/97797765010199340/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=97797765010199340' title='4 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/97797765010199340'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/97797765010199340'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/01/pyglet.html' title='Pyglet'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-7843244449481146369</id><published>2009-01-10T07:43:00.003-03:00</published><updated>2009-01-10T10:09:22.493-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><title type='text'>Atributos privados onde?</title><content type='html'>Os programadores de &lt;a href="http://java.sun.com/"&gt;Java&lt;/a&gt; e &lt;a href="http://www.cplusplus.com/"&gt;C++&lt;/a&gt; pregam vigorosamente a favor de métodos e atributos privados, como se isso fosse uma grandíssima vantagem.&lt;br /&gt;&lt;br /&gt;É um recurso&amp;hellip; faz sentido em seu contexto, mas não traz vantagem alguma por si só &amp;ndash; ao contrário da evangelização dos fanáticos.&lt;br /&gt;&lt;br /&gt;De qualquer forma, o C++ não bloqueia tanto o acesso do programador quanto é pregado.&lt;br /&gt;&lt;br /&gt;Por exemplo, voltemos lá atrás no artigo &lt;a href="http://kodumaro.blogspot.com/2008/10/portando-gdbm-para-lua.html"&gt;Portanto GDBM para Lua&lt;/a&gt;: havia uma classe &lt;code&gt;GdbmObject&lt;/code&gt; com um descritor de arquivo de banco de dados privado.&lt;br /&gt;&lt;br /&gt;Digamos que, por alguma razão bizarra, queiramos ter acesso direto ao descritor.&lt;br /&gt;&lt;br /&gt;Mas o atributo é privado!&lt;br /&gt;&lt;br /&gt;Vamos ao &lt;strong&gt;bacalhau&lt;/strong&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class GdbmObjectCorrupting {&lt;br /&gt;    public:&lt;br /&gt;        bool closed;&lt;br /&gt;        GDBM_FILE fd;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Repare que os atributos públicos aqui têm o mesmo tipo e o mesmo nome dos atributos privados da classe original. Isso garantirá que os símbolos gerados sejam idênticos &amp;ndash; e este é o truque.&lt;br /&gt;&lt;br /&gt;Agora imagine que temos a instância &lt;code&gt;obj&lt;/code&gt; de &lt;code&gt;GdbmObject&lt;/code&gt;, da qual queremos acessar os atributos privados. A mágica é:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;GdbmObjectCorrupting *aux =&lt;br /&gt;    reinterpret_cast&amp;lt;GdbmObjectCorrupting *&amp;gt;(obj);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Pronto! Já está feit&lt;del&gt;o o bacalhau&lt;/del&gt;a a mágica!&lt;br /&gt;&lt;br /&gt;No escopo de &lt;code&gt;aux&lt;/code&gt;, &lt;code&gt;aux-&amp;gt;fd&lt;/code&gt; dá acesso direto ao descritor de &lt;code&gt;obj&lt;/code&gt;, assim como &lt;code&gt;aux-&amp;gt;closed&lt;/code&gt; dá acesso ao booleano &lt;code&gt;closed&lt;/code&gt; de &lt;code&gt;obj&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Agora, este artigo é uma &lt;strong&gt;prova de conceito&lt;/strong&gt;! Não aconselho ninguém a fazer isso. Aliás &lt;u&gt;o &lt;a href="http://kodumaro.blogspot.com/"&gt;Kodumaro&lt;/a&gt; desaprova fortemente tal prática&lt;/u&gt;: reitero, é apenas uma prova de conceito.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-7843244449481146369?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/7843244449481146369/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=7843244449481146369' title='11 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/7843244449481146369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/7843244449481146369'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2009/01/atributos-privados-onde.html' title='Atributos privados onde?'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-8120201546523373317</id><published>2008-12-10T22:27:00.006-03:00</published><updated>2008-12-11T13:59:52.560-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Perl'/><title type='text'>Perl6</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; border: none;" src="http://photos1.blogger.com/blogger/6505/3295/200/camel.png" alt="Perl" /&gt; &lt;a href="http://www.wall.org/~larry/"&gt;Larry Wall&lt;/a&gt;, criador do &lt;a href="http://www.perl.org/"&gt;Perl&lt;/a&gt; e cocriador do &lt;a href="http://www.parrot.org/"&gt;Parrot&lt;/a&gt;, declarou que &lt;a href="http://www.computerworld.com.au/article/269758/perl_6_break_compatibility_support_other_interpreters?eid=-6787"&gt;a versão 6 de Perl não será compatível com as versões anteriores&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Realmente dei uma olhada no &lt;a href="http://dev.perl.org/perl6/"&gt;Perl6&lt;/a&gt; e está muito diferente&amp;hellip; só que para melhor. =)&lt;br /&gt;&lt;br /&gt;A única coisa de que não gostei foram das mudanças em &lt;a href="http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html"&gt;expressões regulares&lt;/a&gt;, no mais as mudanças só acrescentam.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Tipagem&lt;/h3&gt;&lt;br /&gt;Uma das maiores reclamações que os programadores fazem de Perl é sua tipagem &lt;em&gt;insanamente&lt;/em&gt; fraca, apenas três tipos: escalar (&lt;code&gt;$&lt;/code&gt;&lt;em&gt;scalar&lt;/em&gt;), vetor (&lt;code&gt;@&lt;/code&gt;&lt;em&gt;array&lt;/em&gt;) e vetor associativo (&lt;code&gt;%&lt;/code&gt;&lt;em&gt;hash&lt;/em&gt;).&lt;br /&gt;&lt;br /&gt;Perl6 traz o suporte a tipos! Pelo que vi na documentação, há seis tipos novos: inteiro (&lt;code&gt;int&lt;/code&gt;), ponto flutuante (&lt;code&gt;num&lt;/code&gt;), &lt;em&gt;string&lt;/em&gt; (&lt;code&gt;str&lt;/code&gt;), booleano (&lt;code&gt;bool&lt;/code&gt;), &lt;em&gt;bit&lt;/em&gt; (&lt;code&gt;bit&lt;/code&gt;) e referência (&lt;code&gt;ref&lt;/code&gt;), de forma estática:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;my int $foo = 5;&lt;br /&gt;my str $bar = "foo";&lt;br /&gt;my num $baz = 5.3;&lt;br /&gt;my bool $foobar = 1;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Conversão:&lt;pre&gt;&lt;code class="prettyprint"&gt;print str 5;&lt;br /&gt;print scalar @list;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Passagem de parâmetros&lt;/h3&gt;&lt;br /&gt;Em Perl a passagem de parâmetros sempre foi por cópia, agora passa a ser por referência, exceto para tipos primitivos.&lt;br /&gt;&lt;br /&gt;No caso de atribuição de referência de tipos primitivos, em vez do tradicional:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt; my $b = &amp;#92;$a;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Passa a ser:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt; my $b := $a;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Mudanças em vetores&lt;/h3&gt;&lt;br /&gt;A criação de vetor passa a suportar um formato mais simples.&lt;br /&gt;&lt;br /&gt;Temos o tradicional:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;my @fruits = ("apple", "pear", "banana");&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Que passa a ser:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;my @fruits = "apple", "pear", "banana";&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E a lista:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;my @fruits = qw/apple pear banana/;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Passa a ser:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;my @fruits = &amp;lt;apple pear banana&amp;gt;;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em Perl5, para se obter um item de um vetor, o primeiro carácter mudava de &lt;code&gt;@&lt;/code&gt; para &lt;code&gt;$&lt;/code&gt;: &lt;code&gt;$fruits[0]&lt;/code&gt;. Agora, em Perl6, não há mais alteração: &lt;code&gt;@fruits[0]&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;A quantidade de elementos de um vetor era dada por:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;my $count = $#fruits + 1;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora, em Perl6 passa a ser:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;my int $count = @fruits.elems;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Repara que o famigerado &lt;code&gt;-&amp;gt;&lt;/code&gt; virou um simples ponto!&lt;br /&gt;&lt;br /&gt;Também para obter o último elemento do vetor, que era:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;my $last = $fruit[$#fruit];&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Passa a ser:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;my $last = @fruit[@fruit.end];&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ou ainda:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;my $last = @fruit[*-1];&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para se obter um vetor em um contexto &lt;em&gt;string&lt;/em&gt;, Perl6 oferece o atalho &lt;code&gt;~&lt;/code&gt;. Para numérico &lt;code&gt;+&lt;/code&gt; e para booleano &lt;code&gt;?&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;my str $str_fruits = ~@fruits;&lt;br /&gt;my num $num_fruits = +@fruits;&lt;br /&gt;my bool $bool_fruits = ?@fruits;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Tratamento de exceções&lt;/h3&gt;&lt;br /&gt;Em Perl5 era usado &lt;code&gt;eval&lt;/code&gt; para avaliar um bloco com possível exceção e &lt;code&gt;$@&lt;/code&gt; recebia os dados de exceção:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;eval {&lt;br /&gt;    &amp;hellip;&lt;br /&gt;};&lt;br /&gt;if ($@) {&lt;br /&gt;    warn "exception: $@";&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Perl6 passa a usar &lt;code&gt;try&lt;/code&gt;-&lt;code&gt;CATCH&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;try {&lt;br /&gt;    &amp;hellip;&lt;br /&gt;    CATCH {&lt;br /&gt;        warn "exception: $!";&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Repare que a mensagem de exceção passa a ser capturada em &lt;code&gt;$!&lt;/code&gt; e o bloco &lt;code&gt;CATCH&lt;/code&gt; fica dentro do bloco &lt;code&gt;try&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Repetições&lt;/h3&gt;&lt;br /&gt;Não há uma forma menos dolorosa de dizer isso: &lt;code&gt;foreach&lt;/code&gt; vira &lt;code&gt;for&lt;/code&gt;, que também passa a suportar algumas construções de &lt;code&gt;while&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt; vira &lt;code&gt;loop&lt;/code&gt;, que também passa a suportar algumas construções de &lt;code&gt;while&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Então:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;foreach (@fruits) {&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Vira:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;for @fruits {&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;foreach my $fruit (@fruits) {&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Vira:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;for @fruits -&amp;gt; $fruit {&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora, olha o &lt;code&gt;while&lt;/code&gt; aí:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;while (my($age, $sex, $location) = splice @whatever, 0, 3) {&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Vira:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;for @whatever -&amp;gt; $age, $sex, $location {&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Contando até dez em Perl5:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;for (my $i = 1; $i &amp;lt;=10; $i++) {&lt;br /&gt;    print "$i\n";&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Contando até dez em Perl6:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;loop (my $i = 1; $i &amp;lt;=10; $i++) {&lt;br /&gt;    say $i;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E &lt;code&gt;loop { &amp;hellip; }&lt;/code&gt; funciona como &lt;code&gt;while (1) { &amp;hellip; }&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Vetor associativo&lt;/h3&gt;&lt;br /&gt;Sofre alterações parecidas com as de vetor.&lt;br /&gt;&lt;br /&gt;Por exemplo, em Perl5:&lt;br /&gt;&lt;pre&gt;&lt;code="prettyprint"&gt;my $c = $days{February};&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em Perl6 vira:&lt;br /&gt;&lt;pre&gt;&lt;code="prettyprint"&gt;my int $c = %days{'February'};&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ou ainda:&lt;br /&gt;&lt;pre&gt;&lt;code="prettyprint"&gt;my int $c = %days&amp;lt;February&amp;gt;;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Alguns métodos&lt;/h3&gt;&lt;br /&gt;Para se obter o tamanho de uma &lt;em&gt;string&lt;/em&gt; em Perl5:&lt;br /&gt;&lt;pre&gt;&lt;code="prettyprint"&gt;my $len = length $string;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em Perl6 fica:&lt;br /&gt;&lt;pre&gt;&lt;code="prettyprint"&gt;my int $len = $string.chars;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para exibir um vetor de modo ordenado em Perl5:&lt;br /&gt;&lt;pre&gt;&lt;code="prettyprint"&gt;print sort(@fruits);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em Perl6:&lt;br /&gt;&lt;pre&gt;&lt;code="prettyprint"&gt;say @array.sort;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ou ainda:&lt;br /&gt;&lt;pre&gt;&lt;code="prettyprint"&gt;@array.sort.print;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Variáveis de sistema&lt;/h3&gt;&lt;br /&gt;Para se obter o valor da variável &lt;code&gt;HOME&lt;/code&gt; em Perl5:&lt;br /&gt;&lt;pre&gt;&lt;code="prettyprint"&gt;print $ENV{HOME};&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Em Perl6 passa a ser:&lt;br /&gt;&lt;pre&gt;&lt;code="prettyprint"&gt;print %*ENV&amp;lt;HOME&amp;gt;;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ou ainda:&lt;br /&gt;&lt;pre&gt;&lt;code="prettyprint"&gt;print $+HOME;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Orientação a objetos&lt;/h3&gt;&lt;br /&gt;Criar uma classe em Perl5 era uma &lt;a href="http://montegasppa.blogspot.com/2006/09/orientao-objetos-em-perl.html"&gt;aventura&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;Você criava um pacote (&lt;code&gt;package&lt;/code&gt;) e «abençoava» um escalar com o pacote&amp;hellip; pronto: aí tinha uma instância cuja classe era o pacote.&lt;br /&gt;&lt;br /&gt;Um tremendo &lt;strong&gt;bacalhau&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Em Perl6 temos as palavras reservadas &lt;code&gt;class&lt;/code&gt;, &lt;code&gt;has&lt;/code&gt; (para atributos) e &lt;code&gt;method&lt;/code&gt; (para métodos), para criar classes reais.&lt;br /&gt;&lt;br /&gt;Métodos privados precisam começar com &lt;code&gt;!&lt;/code&gt;, por exemplo, &lt;code&gt;$!age&lt;/code&gt;, e métodos públicos precisam começar com &lt;code&gt;.&lt;/code&gt;, como por exemplo &lt;code&gt;$.name&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;A passagem de parâmetros também mudou. Além de ser por referência, como citado, passa a suportar parâmetros nominais e parâmetros excedentes &amp;ndash; como &lt;code&gt;*args&lt;/code&gt; de &lt;a href="http://python.org/"&gt;Python&lt;/a&gt;, mas com a sintaxe &lt;code&gt;*@args&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Se o argumento for mutável precisa ser seguido de &lt;code&gt;is&amp;nbsp;rw&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;O que era:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;package Square;&lt;br /&gt;@ISA = qw/ Rectangle /;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Passa a ser:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class Square is Rectangle {&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E o que era:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;my $rect = new Rectangle(4, 5);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Passa a ser:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;my Rectangle $rect .= new(4, 5);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conclusão&lt;/h3&gt;&lt;br /&gt;Há muito mais! Consulte a página &lt;a href="http://feather.perl6.nl/syn/Differences.html"&gt;Perl6::Perl5::Differences&lt;/a&gt;, mas o que já sabemos é: quem trabalha com Perl &lt;strong&gt;vai precisar aprender de novo&lt;/strong&gt;!&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-8120201546523373317?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/8120201546523373317/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=8120201546523373317' title='11 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8120201546523373317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/8120201546523373317'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2008/12/perl6.html' title='Perl6'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-5444979955200612086</id><published>2008-12-05T15:18:00.002-03:00</published><updated>2008-12-05T15:20:02.918-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Persistência de dados entre execuções em OpenStep</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 100px; height: 105px; border: none;" src="http://1.bp.blogspot.com/_rGfO7DAuOSE/SRT62RK9EZI/AAAAAAAAAKg/53tVzG0MiP8/s200/gnustep.jpg" alt="GNUstep" /&gt; &lt;a href="http://pt.wikipedia.org/wiki/OpenStep"&gt;OpenStep&lt;/a&gt; facilita a persistência de dados entre uma execução e outra do programa através da classe &lt;code&gt;NSUserDefaults&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Para persistir dados para a próxima execução, basta criar um dicionário (&lt;code&gt;NSDictionary&lt;/code&gt;) representando um &lt;em&gt;hash&lt;/em&gt; dos dados a serem persistidos.&lt;br /&gt;&lt;br /&gt;Digamos que o dicionário seja &lt;code&gt;defaults&lt;/code&gt; e &lt;code&gt;APP_NAME&lt;/code&gt; é uma &lt;em&gt;string&lt;/em&gt; (&lt;code&gt;NSString&lt;/code&gt;) representando o nome da aplicação:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;[[NSUserDefaults standardUserDefaults]&lt;br /&gt;    setPersistentDomain: defaults&lt;br /&gt;    forName: APP_NAME&lt;br /&gt;];&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E para recuperar os dados persistidos da última execução:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;NSDictionary *defaults = [&lt;br /&gt;    [NSUserDefaults standardUserDefaults]&lt;br /&gt;    persistentDomainForName: APP_NAME&lt;br /&gt;];&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Então &lt;code&gt;defaults&lt;/code&gt; será um dicionário contendo os dados persistidos!&lt;br /&gt;&lt;br /&gt;Simples assim. =)&lt;br /&gt;&lt;br /&gt;Referência: &lt;a href="http://www.gnustep.org/resources/documentation/Developer/Base/Reference/"&gt;GNUstep Base&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-5444979955200612086?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/5444979955200612086/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=5444979955200612086' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5444979955200612086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5444979955200612086'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2008/12/persistencia-de-dados-em-openstep.html' title='Persistência de dados entre execuções em OpenStep'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_rGfO7DAuOSE/SRT62RK9EZI/AAAAAAAAAKg/53tVzG0MiP8/s72-c/gnustep.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-1718094671209626306</id><published>2008-11-20T09:38:00.011-03:00</published><updated>2009-11-27T20:32:13.359-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='Smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Lua'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Base64</title><content type='html'>De vez enquando, não tem como não, nós programadores sempre esbarramos na &lt;a href="http://pt.wikipedia.org/wiki/Base64"&gt;Base64&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Base64 é um protocolo de codificação que usa apenas seis &lt;em&gt;bits&lt;/em&gt;, o que significa um conjunto de sessenta e quatro (64) elementos &amp;ndash; daí Base&lt;strong&gt;64&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;A conversão de oito (&lt;em&gt;byte&lt;/em&gt;) para seis &lt;em&gt;bits&lt;/em&gt; é feita da seguinte forma:&lt;br /&gt;&lt;center&gt;&lt;code&gt;xxxxxx.xx xxxx.xxxx xx.xxxxxx&lt;/code&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;Ou ainda:&lt;br /&gt;&lt;center&gt;&lt;code&gt;aaaaaabb bbbbcccc ccdddddd&lt;/code&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;Os elementos usados são caracteres simples, começando com as letras maiúsculas, &lt;code&gt;A&lt;/code&gt; (0) a &lt;code&gt;Z&lt;/code&gt; (25), então as letras minúsculas, &lt;code&gt;a&lt;/code&gt; (26) a &lt;code&gt;z&lt;/code&gt; (51), os números, &lt;code&gt;0&lt;/code&gt; (52) a &lt;code&gt;9&lt;/code&gt; (61), e os caracteres &lt;code&gt;+&lt;/code&gt; (62) e &lt;code&gt;/&lt;/code&gt; (63).&lt;br /&gt;&lt;br /&gt;Na conversão de &lt;em&gt;bytes&lt;/em&gt; (8b) para Base64 (6b), cada três &lt;em&gt;bytes&lt;/em&gt; é convertido em quatro dígitos, então um código Base64 é sempre pensado em grupos de quatro. Se o tamanho de um código Base64 não for múltiplo de quatro, caracteres &lt;code&gt;=&lt;/code&gt; são acrescentados ao final até que o tamanho seja múltiplo de quatro.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Python&lt;/h3&gt;&lt;br /&gt;Em &lt;a href="http://python.org/"&gt;Python&lt;/a&gt;, Base64 é tão simples que nem tem graça:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;print "Kodumaro".encode("base64")&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;S29kdW1hcm8=&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;print "S29kdW1hcm8=".decode("base64")&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Kodumaro&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Lua&lt;/h3&gt;&lt;br /&gt;Em &lt;a href="http://www.lua.org/"&gt;Lua&lt;/a&gt;, é preciso baixar o módulo &lt;a href="http://www.tecgraf.puc-rio.br/~diego/professional/luasocket/mime.html"&gt;Mime&lt;/a&gt; do &lt;a href="http://www.tecgraf.puc-rio.br/~diego/professional/luasocket/"&gt;LuaSocket&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;require "mime"&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;print(mime.b64 "Kodumaro")&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;S29kdW1hcm8=&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; &lt;strong&gt;print(mime.unb64 "S29kdW1hcm8=")&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Kodumaro&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Smalltalk&lt;/h3&gt;&lt;br /&gt;Sendo muito sincero sobre o assunto, &lt;strong&gt;não sei&lt;/strong&gt; como fazer conversão de Base64 em &lt;a href="http://smalltalk.org/"&gt;Smalltalk&lt;/a&gt;. =(&lt;br /&gt;&lt;br /&gt;Mas sei que os módulos do &lt;a href="http://seaside.st/"&gt;Seaside&lt;/a&gt; providenciam isso!&lt;br /&gt;&lt;br /&gt;Se alguém souber, por favor informe!&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update 2009-11-27]&lt;/tt&gt;&lt;br /&gt;Sugestão do &lt;a href="http://www.blogger.com/profile/06182924594031018840"&gt;Hugo&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;No Squeak tem isso aqui:&lt;/em&gt;&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(Base64MimeConverter mimeEncode: 'base64' readStream) contents&lt;br /&gt;(Base64MimeConverter mimeDecode: 'S29kdW1hcm8' as: ByteString) contents&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;E no Pharo tem métodos para &lt;/em&gt;strings&lt;em&gt;:&lt;/em&gt;&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;'base64' base64Encoded&lt;br /&gt;'S29kdW1hcm8' base64Decoded&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;A implementação usa as coisas do Squeak:&lt;/em&gt;&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;String&amp;gt;&amp;gt;base64Decoded&lt;br /&gt;↑ (Base64MimeConverter mimeDecode: self as: self class)&lt;br /&gt;&lt;br /&gt;String&amp;gt;&amp;gt;base64Encoded&lt;br /&gt;↑ (Base64MimeConverter mimeEncode: self readStream) contents&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Para outros Smalltalks eu não sei…&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Legal né? =)&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Muito legal sim, Hugo, valeu!&lt;br /&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;C&lt;/h3&gt;&lt;br /&gt;Aha! Aqui começa de verdade a brincadeira!&lt;br /&gt;&lt;br /&gt;É claro que você pode usar as funcionalidades de Base64 da &lt;em&gt;gLibC&lt;/em&gt;, mas descobri que nem todas as versões dela apresentam tais funcionalidades:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#include &amp;lt;glib/gbase64.h&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Vamos precisar usar os cabeçalhos &lt;code&gt;stdlib.h&lt;/code&gt;, &lt;code&gt;string.h&lt;/code&gt; e &lt;code&gt;sys/types.h&lt;/code&gt;. Como também vamos criar um cabeçalho para «compartilhar» algumas funções, ele também será incluído no início de nosso arquivo &lt;code&gt;base64.c&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;#include &amp;lt;string.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;#include "base64.h"&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora vamos criar um &lt;em&gt;array&lt;/em&gt; com todos os possíveis caracteres Base64 em sua ordem natural:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;static const char b64all[] =&lt;br /&gt;    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"&lt;br /&gt;    "ghijklmnopqrstuvwxyz0123456789+/";&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Também vamos precisar de três funções locais: uma para obter o índice de um elemento (&lt;code&gt;_getindex&lt;/code&gt;), outra para codificar para Base64 um grupo de três &lt;em&gt;bytes&lt;/em&gt; (&lt;code&gt;_encode&lt;/code&gt;) e mais uma para decodificar um grupo de quatro elementos Base64 (&lt;code&gt;_decode&lt;/code&gt;):&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;int _decode(u_int8_t *, const u_int8_t *);&lt;br /&gt;void _encode(u_int8_t *, const u_int8_t *, int);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Não é preciso uma função para &lt;code&gt;_getindex&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#define _getindex(c) (int) (index(b64all, c) - b64all)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Repara que, em vez de &lt;code&gt;char&lt;/code&gt;, estamos usando &lt;code&gt;u_int8_t&lt;/code&gt;, que é mais conveniente quando queremos lidar com &lt;em&gt;bytes&lt;/em&gt; enquanto &lt;em&gt;bytes&lt;/em&gt;, não caracteres.&lt;br /&gt;&lt;br /&gt;A partir daqui, se preferir, organize as funções em ordem alfabética &amp;ndash; ou na ordem que quiser.&lt;br /&gt;&lt;br /&gt;A primeira função que implementaremos será para codificar uma &lt;em&gt;string&lt;/em&gt; C (&lt;code&gt;const char *&lt;/code&gt;) para Base64. Como a &lt;em&gt;string&lt;/em&gt; pode não ser bem formada, a função deverá receber também seu tamanho:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;const char *b64encode(const char *original, int length) {&lt;br /&gt;    // Se o tamanho não for informado, consideramos uma string bem&lt;br /&gt;    // formada&lt;br /&gt;    if (length == 0)&lt;br /&gt;        length = strlen(original);&lt;br /&gt;&lt;br /&gt;    // Inteiro com o tamanho do código a ser gerado&lt;br /&gt;    int b64length = ((length + 2) / 3) * 4 + 1;&lt;br /&gt;&lt;br /&gt;    // Contadores para percorrer as strings&lt;br /&gt;    int i=0, j=0;&lt;br /&gt;&lt;br /&gt;    // Alocando memória para o código&lt;br /&gt;    char *b64 = (char *) malloc(sizeof(char) * b64length);&lt;br /&gt;    memset(b64, 0, b64length);&lt;br /&gt;&lt;br /&gt;    while (i &amp;lt; length) {&lt;br /&gt;        // Codifica um grupo de três bytes...&lt;br /&gt;        _encode(&lt;br /&gt;            (u_int8_t *) b64 + j,&lt;br /&gt;            (const u_int8_t *) original + i,&lt;br /&gt;            (length - i)&lt;br /&gt;        );&lt;br /&gt;&lt;br /&gt;        // E segue para o próximo grupo&lt;br /&gt;        i += 3;&lt;br /&gt;        j += 4;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Retorna o código&lt;br /&gt;    return (const char *) b64;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A próxima função deve fazer o contrário, converter um código Base64 para uma &lt;em&gt;string&lt;/em&gt;. Como a &lt;em&gt;string&lt;/em&gt; resultante pode não ser bem formada &amp;ndash; pode não ser terminada em carácter nulo ou possuir caracteres nulos no meio &amp;ndash;, é preciso uma forma de informar seu tamanho, então ela receberá um ponteiro para um inteiro:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;const char *b64decode(const char *b64, int *length) {&lt;br /&gt;    // Inteiro com o tamanho do código&lt;br /&gt;    int b64length = strlen(b64);&lt;br /&gt;&lt;br /&gt;    // Se não for múltiplo de quatro, há algo errado&lt;br /&gt;    if (b64length % 4 != 0)&lt;br /&gt;        return NULL;&lt;br /&gt;&lt;br /&gt;    // Tamanho máximo da string decifrada&lt;br /&gt;    int prob = (b64length / 4) * 3 + 1;&lt;br /&gt;&lt;br /&gt;    // Contadores para percorrer as strings&lt;br /&gt;    int i=0, j=0;&lt;br /&gt;&lt;br /&gt;    // Alocando memória para o resultado&lt;br /&gt;    char *s = (char *) malloc(sizeof(char) * prob);&lt;br /&gt;&lt;br /&gt;    while (j &amp;lt; b64length) {&lt;br /&gt;        // Decifra um grupo de quatro elementos&lt;br /&gt;        // e conta o resultado&lt;br /&gt;        i += _decode(&lt;br /&gt;            (u_int8_t *) s + i,&lt;br /&gt;            (const u_int8_t *) b64 + j&lt;br /&gt;        );&lt;br /&gt;&lt;br /&gt;        // Segue para o próximo grupo&lt;br /&gt;        j += 4;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Se foi fornecido um inteiro para contagem, informa o tamanho&lt;br /&gt;    if (length != NULL)&lt;br /&gt;        *length = i;&lt;br /&gt;&lt;br /&gt;    // Retorna a string decifrada&lt;br /&gt;    return (const char *) s;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora precisamos das funções específica para as conversões.&lt;br /&gt;&lt;br /&gt;Primeiro para codificar:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;void _encode(u_int8_t *dest, const u_int8_t *src, int len) {&lt;br /&gt;    // Menor que 1, nada a fazer&lt;br /&gt;    if (len &amp;lt; 1)&lt;br /&gt;        return;&lt;br /&gt;&lt;br /&gt;    // Dados a serem retornados&lt;br /&gt;    int aux[] = { 0, 0, 0, 0 };&lt;br /&gt;&lt;br /&gt;    // Primeiro elemento: os 6 bits mais significativos do primeiro&lt;br /&gt;    // byte&lt;br /&gt;    aux[0] = src[0] &amp;gt;&amp;gt; 2;&lt;br /&gt;&lt;br /&gt;    // Segundo elemento: os 2 bits menos significativos do primeiro e&lt;br /&gt;    // os quatro bits mais significativos do segundo byte&lt;br /&gt;    aux[1] = (src[0] &amp;amp; 0x03) &amp;lt;&amp;lt; 4;&lt;br /&gt;&lt;br /&gt;    if (len &amp;gt; 1) {&lt;br /&gt;        // SE houver um segundo...&lt;br /&gt;        aux [1] |= (src[1] &amp;amp; 0xf0) &amp;gt;&amp;gt; 4;&lt;br /&gt;&lt;br /&gt;        // Terceiro elemento: os quatro bits menos significativos do&lt;br /&gt;        // segundo e os dois mais significativos do terceiro byte&lt;br /&gt;        aux [2] = (src[1] &amp;amp; 0x0f) &amp;lt;&amp;lt; 2;&lt;br /&gt;&lt;br /&gt;        if (len &amp;gt; 2) {&lt;br /&gt;            // Se houver um terceiro...&lt;br /&gt;            aux[2] |= src[2] &amp;gt;&amp;gt; 6;&lt;br /&gt;&lt;br /&gt;            // Quarto elemento: os seis bits menos significatos do&lt;br /&gt;            // terceiro byte&lt;br /&gt;            aux[3] = src[2] &amp;amp; 0x3f;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Codifica agora os valores numéricos para string&lt;br /&gt;    dest[0] = b64all[aux[0]];&lt;br /&gt;    dest[1] = b64all[aux[1]];&lt;br /&gt;    dest[2] = '=';&lt;br /&gt;    dest[3] = '=';&lt;br /&gt;    if (len &amp;gt; 1) {&lt;br /&gt;        dest[2] = b64all[aux[2]];&lt;br /&gt;        if (len &amp;gt; 2)&lt;br /&gt;            dest[3] = b64all[aux[3]];&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int _decode(u_int8_t *dest, const u_int8_t *src) {&lt;br /&gt;    // Representação numérica do código&lt;br /&gt;    int aux[] = { 0, 0, 0, 0 };&lt;br /&gt;&lt;br /&gt;    // Contador&lt;br /&gt;    int i, c = 1;&lt;br /&gt;&lt;br /&gt;    // Converte código para valores numéricos&lt;br /&gt;    for (i = 0; i &amp;lt; 4; ++i)&lt;br /&gt;        aux[i] = _getindex(src[i]);&lt;br /&gt;&lt;br /&gt;    // Primeiro byte: primeiro elemento seguido dos quatro bits mais&lt;br /&gt;    // significativos do segundo&lt;br /&gt;    dest[0] = (u_int8_t) (aux[0] &amp;lt;&amp;lt; 2) | ((aux[1] &amp;amp; 0x30) &amp;gt;&amp;gt; 4);&lt;br /&gt;&lt;br /&gt;    // Zera os bytes seguintes&lt;br /&gt;    dest[1] = '\0';&lt;br /&gt;    dest[2] = '\0';&lt;br /&gt;&lt;br /&gt;    if (aux[2] != -1) {&lt;br /&gt;        // Se houver um terceiro elemento...&lt;br /&gt;        ++c;&lt;br /&gt;&lt;br /&gt;        // Segundo byte: quatro bits menos significativos do segundo&lt;br /&gt;        // elemento seguidos pelos quatro bits mais significativos do&lt;br /&gt;        // terceiro&lt;br /&gt;        dest[1] = (u_int8_t) ((aux[1] &amp;amp; 0x0f) &amp;lt;&amp;lt; 4) | (aux[2] &amp;gt;&amp;gt; 2);&lt;br /&gt;&lt;br /&gt;        if (aux[3] != -1) {&lt;br /&gt;            // Se houver um quarto elemento...&lt;br /&gt;            ++c;&lt;br /&gt;&lt;br /&gt;            // Terceiro byte: dois bits menos significativos do&lt;br /&gt;            // terceiro elemento seguidos pelo quarto elemento&lt;br /&gt;            dest[2] = (u_int8_t)&lt;br /&gt;              ((aux[2] &amp;amp; 0x03) &amp;lt;&amp;lt; 6) |&lt;br /&gt;              aux[3];&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Retorna o tamanho da string&lt;br /&gt;    return c;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Cabeçalho&lt;/h3&gt;&lt;br /&gt;Por último criamos o cabeçalho &lt;code&gt;base64.h&lt;/code&gt;, tornando públicas as duas funções de codificação e decodificação:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#ifndef _BASE64_H&lt;br /&gt;#define _BASE64_H&lt;br /&gt;&lt;br /&gt;const char *b64decode(const char *, int *);&lt;br /&gt;const char *b64encode(const char *, int);&lt;br /&gt;&lt;br /&gt;#endif&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conclusão&lt;/h3&gt;&lt;br /&gt;Mesmo que ninguém vá implementar uma biblioteca de conversão Base64, espero que este artigo sirva para ajudar a entender melhor do que se trata Base64.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;tt&gt;[update]&lt;/tt&gt;&lt;/center&gt;&lt;br /&gt;Se quiser acrescentar algum açucar sintático, coloque em &lt;code&gt;base64.c&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#ifdef C_PLUS_PLUS&lt;br /&gt;const char *b64decode(const char *b64, int &amp;length) {&lt;br /&gt;    return b64decode(b64, &amp;length);&lt;br /&gt;}&lt;br /&gt;#endif&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E mude o conteúdo de &lt;code&gt;base64.h&lt;/code&gt; para:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#ifndef _BASE64_H&lt;br /&gt;#define _BASE64_H&lt;br /&gt;&lt;br /&gt;#ifdef C_PLUS_PLUS&lt;br /&gt;extern "C" {&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;const char *b64decode(const char *, int *);&lt;br /&gt;const char *b64encode(const char *, int);&lt;br /&gt;&lt;br /&gt;#ifdef C_PLUS_PLUS&lt;br /&gt;}&lt;br /&gt;const char *b64decode(const char *, int &amp;);&lt;br /&gt;#else&lt;br /&gt;#define _b64decode(s, len) b64decode(s, &amp;len)&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;#endif&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;center&gt;&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-1718094671209626306?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/1718094671209626306/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=1718094671209626306' title='8 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/1718094671209626306'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/1718094671209626306'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2008/11/base64.html' title='Base64'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-7582239185123234603</id><published>2008-11-13T21:52:00.011-03:00</published><updated>2009-01-16T13:37:21.626-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Objective C</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 100px; height: 105px; border: none;" src="http://1.bp.blogspot.com/_rGfO7DAuOSE/SRT62RK9EZI/AAAAAAAAAKg/53tVzG0MiP8/s200/gnustep.jpg" alt="GNUstep" /&gt; Escrevi recentemente um &lt;a href="http://kodumaro.blogspot.com/2008/11/desenvolvendo-aplicacoes-gnustep.html"&gt;artigo&lt;/a&gt; com um exemplo bem simples de desenvolvimento de uma aplicação para ambiente &lt;a href="http://gnustep.org/"&gt;GNUstep&lt;/a&gt;, mas cometi a gafe de não dedicar algum tempo falando da linguagem de programação em questão, &lt;a href="http://pt.wikipedia.org/wiki/Objective-C"&gt;Objective C&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Objective C, ou Objective-C, ou ObjC, é uma linguagem de programação &lt;a href="http://pt.wikipedia.org/wiki/Reflexão_(programação)"&gt;reflectiva&lt;/a&gt; orientada a objetos criada nos idos da década de 1980 &amp;ndash; mais ou menos na mesma época que o &lt;a href="http://www.cplusplus.com/"&gt;C++&lt;/a&gt; &amp;ndash; pelos fundadores da &lt;a href="http://en.wikipedia.org/wiki/Stepstone"&gt;Stepstone&lt;/a&gt;, mais tarde adquirida pela &lt;a href="http://pt.wikipedia.org/wiki/NeXT"&gt;NeXT&lt;/a&gt;. É na verdade uma &lt;strong&gt;camada bem fina&lt;/strong&gt; sobre a linguagem C padrão.&lt;br /&gt;&lt;br /&gt;Isso significa que, se você sabe programar em C, conseguirá programar em ObjC sem muito esforço.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Diferenças para C&lt;/h3&gt;&lt;br /&gt;Sobre a linguagem C, ObjC adiciona os seguintes recursos:&lt;br /&gt;&lt;ul&gt; &lt;li&gt;Orientação a objetos, adaptada de &lt;a href="http://smalltalk.org/"&gt;Smalltalk&lt;/a&gt;.&lt;/li&gt; &lt;li&gt;Tipo boleano &amp;ndash; &lt;code&gt;BOOL&lt;/code&gt;. Verdadeiro é &lt;code&gt;YES&lt;/code&gt; e falso é &lt;code&gt;NO&lt;/code&gt;.&lt;/li&gt; &lt;li&gt;Comentário de linha, iniciado por &lt;code&gt;//&lt;/code&gt; (na época C não suportava).&lt;/li&gt; &lt;li&gt;A diretiva de preprocessador &lt;code&gt;#import&lt;/code&gt;, que funciona como &lt;code&gt;#include&lt;/code&gt;, mas só inclui o cabeçalho &lt;strong&gt;se&lt;/strong&gt; ele não foi incluído ainda.&lt;/li&gt; &lt;li&gt;O tipo &lt;code&gt;id&lt;/code&gt;, similar a &lt;code&gt;void&amp;nbsp;*&lt;/code&gt; de C/C++.&lt;/li&gt; &lt;li&gt;A constante &lt;code&gt;nil&lt;/code&gt;, que é um objeto &lt;code&gt;id&lt;/code&gt; sem valor: &lt;code&gt;(id)0&lt;/code&gt;.&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;A maior parte dos comandos referentes a orientação a objetos começam com &lt;code&gt;@&lt;/code&gt;, como &lt;code&gt;@interface&lt;/code&gt;, &lt;code&gt;@implementation&lt;/code&gt;, &lt;code&gt;@end&lt;/code&gt;, &lt;code&gt;@private&lt;/code&gt;, &lt;code&gt;@protected&lt;/code&gt;, &lt;code&gt;@public&lt;/code&gt;, &lt;code&gt;@protocol&lt;/code&gt;, etc.&amp;hellip; Entre colchetes é avaliado o ambiente de mensagem, com uma sintaxe muito parecida com a de Smalltalk.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Criando uma classe&lt;/h3&gt;&lt;br /&gt;Como exemplo, vamos criar a classe &lt;code&gt;Point&lt;/code&gt;, com os atributos &lt;code&gt;x&lt;/code&gt; e &lt;code&gt;y&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Para tanto, primeiro criamos a interface no arquivo &lt;code&gt;Point.h&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#ifndef _POINT_H&lt;br /&gt;#define _POINT_H&lt;br /&gt;&lt;br /&gt;#import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;&lt;br /&gt;@interface Point : NSObject&lt;br /&gt;{&lt;br /&gt;    int x;&lt;br /&gt;    int y;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;+ (id) newWithX: (int)valuex Y: (int)valuey;&lt;br /&gt;- (id) initWithX: (int)valuex Y: (int)valuey;&lt;br /&gt;- (int) diagonal;&lt;br /&gt;- (int) getX;&lt;br /&gt;- (int) getY;&lt;br /&gt;- (void) setX: (int)value;&lt;br /&gt;- (void) setY: (int)value;&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;&lt;br /&gt;#endif&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As diretivas &lt;code&gt;#ifndef&lt;/code&gt;, &lt;code&gt;#define&lt;/code&gt; e &lt;code&gt;#endif&lt;/code&gt; já são velhas conhecidas dos programadores C/C++. O &lt;code&gt;#import&lt;/code&gt; já foi explicado, funciona parecido com &lt;code&gt;#include&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;O cabeçalho &lt;code&gt;Foundation/Foundation.h&lt;/code&gt; inclui a classe &lt;code&gt;NSObject&lt;/code&gt;, definida pela API &lt;a href="http://www.gnustep.org/resources/OpenStepSpec/OpenStepSpec.html"&gt;OpenStep&lt;/a&gt;, usada aqui como classe pai de nossa classe &lt;code&gt;Point&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;O comando &lt;code&gt;@interface&lt;/code&gt; inicia a descrição da interface e o comando &lt;code&gt;@end&lt;/code&gt; encerra. O pequeno escopo entre chaves define os atributos de instância, protegidos por padrão &amp;ndash; para defini-los como públicos a sintaxe &lt;strong&gt;seria&lt;/strong&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;{&lt;br /&gt;    @public&lt;br /&gt;        int x;&lt;br /&gt;        int y;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As linhas começadas por um sinal de menos (&lt;code&gt;-&lt;/code&gt;) indicam métodos de instância &amp;ndash; métodos de classe são iniciados por &lt;code&gt;+&lt;/code&gt;. Por exemplo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;- (id) initWithX: (int)valuex Y: (int)valuey;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Significa um método de instância que recebe dois atributos inteiros &amp;ndash; &lt;code&gt;valuex&lt;/code&gt; e &lt;code&gt;valuey&lt;/code&gt;, e retorna um &lt;code&gt;id&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Agora precisamos implementar a interface. Para isso vamos criar o arquivo &lt;code&gt;Point.m&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#include &amp;lt;math.h&amp;gt;&lt;br /&gt;#import "Point.h"&lt;br /&gt;&lt;br /&gt;@implementation Point&lt;br /&gt;&lt;br /&gt;+ (id) newWithX: (int)valuex Y: (int)valuey {&lt;br /&gt;    return [[Point alloc]&lt;br /&gt;        initWithX: valuex Y: valuey];&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (id) initWithX: (int)valuex Y: (int)valuey {&lt;br /&gt;    if ((self = [super init])) {&lt;br /&gt;        x = valuex;&lt;br /&gt;        y = valuey;&lt;br /&gt;    }&lt;br /&gt;    return self;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (int) diagonal {&lt;br /&gt;    return (int) sqrt((double) ((x * x) + (y * y)));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (int) getX {&lt;br /&gt;    return x;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (int) getY {&lt;br /&gt;    return y;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void) setX: (int)value {&lt;br /&gt;    x = value;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;- (void) setY: (int)value {&lt;br /&gt;    y = value;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@end&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O código é muito parecido com C, e até mesmo com C++, cabendo apenas alguns comentários:&lt;br /&gt;&lt;ul&gt; &lt;li&gt;&lt;code&gt;self&lt;/code&gt; é uma palavra reservada que representa a instância, como &lt;code&gt;this&lt;/code&gt; de Java e C++.&lt;/li&gt; &lt;li&gt;&lt;code&gt;super&lt;/code&gt; referencia a classe pai, como em Java.&lt;/li&gt; &lt;li&gt;Repare no comando &lt;code&gt;[super&amp;nbsp;init]&lt;/code&gt;: aqui é passada uma mensagem para &lt;code&gt;super&lt;/code&gt; e o valor retornado é atribuído a &lt;code&gt;self&lt;/code&gt;.&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Para instanciar um objeto, a sintaxe é:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;id point = [Point newWithX: 4 Y: 5];&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ou, com tipagem estática:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;Point *point = [Point newWithX: 4 Y: 5];&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Para obter o valor de &lt;code&gt;x&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;printf("x = %d&amp;#92;n", [point getX]);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E para mudar seu valor:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;[point setX: 2];&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;OpenStep&lt;/h3&gt;&lt;br /&gt;OpenStep é a API aberta para desenvolvimento de aplicações para &lt;a href="http://pt.wikipedia.org/wiki/NEXTSTEP"&gt;NEXTSTEP&lt;/a&gt;, resultado de um trabalho colaborativo da NeXT com a &lt;a href="http://www.sun.com"&gt;SUN Microsystems&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Diversos sistemas e ambientes oferecem suporte a OpenStep, como &lt;a href="http://www.apple.com/macosx/"&gt;OS X&lt;/a&gt; e GNUstep.&lt;br /&gt;&lt;br /&gt;Diversos recursos interessantes são oferecidos nessa API, desde vantagens semelhantes à &lt;a href="http://www.cplusplus.com/reference/"&gt;STL&lt;/a&gt; de C++, até conjunto de &lt;em&gt;widgets&lt;/em&gt; para construção de janelas, &lt;em&gt;toolkit&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Já vimos uma classe dessa API, &lt;code&gt;NSObject&lt;/code&gt;. Outra interessante é &lt;code&gt;NSString&lt;/code&gt;, cuja finalidade é a mesma de &lt;code&gt;std::string&lt;/code&gt; de C++ e &lt;code&gt;String&lt;/code&gt; de Java.&lt;br /&gt;&lt;br /&gt;A criação de uma &lt;code&gt;NSString&lt;/code&gt; é:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;id url = [NSString stringWithCString: "http://kodumaro.blogspot.com/"];&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Há ainda um apelido sintático:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;id url = @"http://kodumaro.blogspot.com/";&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Um forma legal de conhecer mais sobre OpenStep é ler os manuais de referência do &lt;a href="http://www.gnustep.org/resources/documentation/Developer/Base/Reference/"&gt;GNUstep&lt;/a&gt; (&lt;em&gt;toolkit&lt;/em&gt; &lt;a href="http://www.gnustep.org/resources/documentation/Developer/Gui/Reference/"&gt;aqui&lt;/a&gt;) e do &lt;a href="http://developer.apple.com/documentation/Cocoa/ObjectiveCLanguage-date.html"&gt;OS X&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-7582239185123234603?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/7582239185123234603/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=7582239185123234603' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/7582239185123234603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/7582239185123234603'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2008/11/objective-c.html' title='Objective C'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_rGfO7DAuOSE/SRT62RK9EZI/AAAAAAAAAKg/53tVzG0MiP8/s72-c/gnustep.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-4168562966807122189</id><published>2008-11-07T23:29:00.019-03:00</published><updated>2009-08-25T22:50:11.998-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Desenvolvendo aplicações GNUstep</title><content type='html'>&lt;img style="float: left; margin: 0 10px 10px 0; cursor: crosshair; width: 100px; height: 105px; border: none;" src="http://1.bp.blogspot.com/_rGfO7DAuOSE/SRT62RK9EZI/AAAAAAAAAKg/53tVzG0MiP8/s200/gnustep.jpg" alt="GNUstep" id="BLOGGER_PHOTO_ID_5266109674532180370" /&gt; Sempre fui fascinado pelo &lt;a href="http://pt.wikipedia.org/wiki/NEXTSTEP"&gt;NeXTSTEP&lt;/a&gt; e gostaria muito tivesse dado certo. Por mais que a &lt;a href="http://www.apple.com/"&gt;Apple&lt;/a&gt; negue, seu &lt;a href="http://pt.wikipedia.org/wiki/Mac_OS_X"&gt;Mac OS X&lt;/a&gt; não é muito mais do que uma versão nova de um NeXTSTEP portado para equipamentos &lt;a href="http://pt.wikipedia.org/wiki/Macintosh"&gt;MacIntosh&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Mas não só o OS X herdou os recursos do NeXTSTEP. No começo da década de 1990, em colaboração com a &lt;a href="http://www.sun.com/"&gt;SUN Microsystems&lt;/a&gt; a NeXT lançou o &lt;a href="http://pt.wikipedia.org/wiki/OpenStep"&gt;OpenStep&lt;/a&gt;, uma especificação aberta que define a &lt;a href="http://pt.wikipedia.org/wiki/API"&gt;API&lt;/a&gt; para o NeXTSTEP.&lt;br /&gt;&lt;br /&gt;Assim ambientes baseados em NeXTSTEP podem rodar em quaisquer sistemas operacionais e aplicações portáteis podem ser criadas.&lt;br /&gt;&lt;br /&gt;A &lt;a href="http://www.fsf.org/"&gt;Free Software Foundation&lt;/a&gt; lançou um projeto de implementação da API OpenStep para sistemas &lt;a href="http://www.gnu.org/"&gt;GNU&lt;/a&gt;, o &lt;a href="http://gnustep.org/"&gt;GNUstep&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Mais do que uma API de programação, GNUstep é todo um ambiente, desde a API até aplicações e ambiente operacional.&lt;br /&gt;&lt;br /&gt;Inicialmente o ambiente gráfico / &lt;a href="http://pt.wikipedia.org/wiki/Gerenciador_de_janela"&gt;geranciador de janelas&lt;/a&gt; era o &lt;a href="http://afterstep.org/"&gt;AfterStep&lt;/a&gt;. Certo dia, na lista de discussão para definir os rumos da versão 2 do AfterStep, um brasileiro chamado &lt;a href="http://pt.wikipedia.org/wiki/Alfredo_Kojima"&gt;Alfredo Kojima&lt;/a&gt; sugeriu a reescrita do código do zero.&lt;br /&gt;&lt;br /&gt;Enquanto o grupo continuava debadendo, Kojima decidiu iniciar o desenvolvimento da versão 2 do AfterStep, codinome WindowMaker, por conta própria e depois apresentou-o à comunidade. O &lt;a href="http://windowmaker.info/"&gt;Window Maker&lt;/a&gt; então substituiu o AfterStep como gerenciador de janelas do projeto GNUstep e o AfterStep continuou seu desenvolvimento a parte.&lt;br /&gt;&lt;br /&gt;Diversas versões do Window Maker foram lançadas, apesar de nunca ter chegado a uma versão 1.0, um eterno &lt;em&gt;beta&lt;/em&gt; &amp;ndash; atualmente se encontra na versão 0.92. Porém seu desenvolvimento esfriou gradativamente.&lt;br /&gt;&lt;br /&gt;Ano passado o projeto voltou a esquentar e promessas de novas versões estão no ar, o que me inspirou a escrever este artigo.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;small&gt;Consulte o &lt;a href="http://wmaker.cyaneus.net/"&gt;&lt;em&gt;blog&lt;/em&gt; do Bardo&lt;/a&gt;.&lt;/small&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;GNUstep&lt;/h3&gt;&lt;br /&gt;Mas este artigo não é sobre Window Maker, e sim sobre GNUstep.&lt;br /&gt;&lt;br /&gt;Para desenvolver aplicações GNUstep, você precisa baixar seu &lt;em&gt;core&lt;/em&gt; antes. Acesse a &lt;a href="http://gnustep.org/resources/downloads.php"&gt;página de recursos&lt;/a&gt;, vá ao tópico &lt;em&gt;GNUstep Core&lt;/em&gt; e baixe as versões estáveis de cada pacote. Descompacte, compile e instale na ordem em que os pacotes aparecem na tabela (&lt;em&gt;startup&lt;/em&gt;, &lt;em&gt;make&lt;/em&gt;, &lt;em&gt;base&lt;/em&gt;, &lt;em&gt;gui&lt;/em&gt; e &lt;em&gt;backend&lt;/em&gt;). O &lt;em&gt;core&lt;/em&gt; do GNUstep deverá ser instalado em &lt;code&gt;/usr/GNUstep/&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Você precisa acrescentar &lt;code&gt;/usr/GNUstep/System/Tools&lt;/code&gt; a seu &lt;em&gt;path&lt;/em&gt; de executáveis, &lt;code&gt;/usr/GNUstep/System/Library/Libraries&lt;/code&gt; a sua lista de diretórios de bibliotecas &amp;ndash; em ambiente GNU/Linux, acrescente esse &lt;em&gt;path&lt;/em&gt; ao arquivo &lt;code&gt;/etc/ld.so.conf&lt;/code&gt; e execute &lt;code&gt;ldconfig&lt;/code&gt; &amp;ndash; e crie uma variável de ambiente &lt;code&gt;GNUSTEP_MAKEFILES&lt;/code&gt; com o valor &lt;code&gt;/usr/GNUstep/System/Library/Makefiles&lt;/code&gt; e outra &lt;code&gt;GNUSTEP_INSTALLATION_DOMAIN&lt;/code&gt; com o valor &lt;code&gt;SYSTEM&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Tendo o GNUstep instalado, podemos partir para as ferramentas de desenvolvimento, &lt;a href="http://www.gnustep.org/experience/Gorm.html"&gt;Gorm&lt;/a&gt; e &lt;a href="http://www.gnustep.org/experience/ProjectCenter.html"&gt;Project Center&lt;/a&gt;. Você também encontrará apontadores para as versões estáveis na mesma máquina de recursos, no tópico &lt;em&gt;GNUstep Development Tools&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Criando um projeto&lt;/h3&gt;&lt;br /&gt;Vamos criar nosso primeiro projeto GNUstep!&lt;br /&gt;&lt;br /&gt;Primeiro abrimos o Project Center com o comando:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;openapp ProjectCenter&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Vá em &lt;code&gt;Project&lt;/code&gt; &amp;rarr; &lt;code&gt;New...&lt;/code&gt; (ou pressione &lt;code&gt;M-n&lt;/code&gt;), vai abrir uma janela de diálogo pedindo o nome do projeto. Selecione o tipo &lt;code&gt;Application&lt;/code&gt; e forneça o nome &lt;code&gt;Temperature&lt;/code&gt; e clique &lt;code&gt;Ok&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Por enquanto nossa brincadeira com Project Center acaba por aqui. Pode salvar &amp;ndash; &lt;code&gt;Project&lt;/code&gt; &amp;rarr; &lt;code&gt;Save&lt;/code&gt; ou &lt;code&gt;M-s&lt;/code&gt; &amp;ndash; e sair &amp;ndash; &lt;code&gt;Quit&lt;/code&gt; ou &lt;code&gt;M-q&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Criando uma aplicação&lt;/h3&gt;&lt;br /&gt;Agora vamos trabalhar no Gorm, execute:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;openapp Gorm&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Um segredinho: nas versões anteriores você mandava abrir o &lt;code&gt;Temperature.gorm&lt;/code&gt; a partir do Project Center e ele já abria o Gorm para a aplicação atual. Na versão que experimentei &amp;ndash; Gorm 1.2.6 e Project Center 0.5.0 &amp;ndash; há um &lt;em&gt;bug&lt;/em&gt;. O truque é abrir o Gorm a parte e &lt;strong&gt;criar uma nova aplicação&lt;/strong&gt;.&lt;br /&gt;&lt;blockquote&gt;Se quiser testar se está funcionando &amp;ndash; em algumas lugares que testei funcionou &amp;ndash; para abrir o Gorm, na janela principal do Project Center clique em &lt;code&gt;Interfaces&lt;/code&gt; e duplo clique em &lt;code&gt;Temperature.gorm&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;No Gorm, crie uma janela e marque como &lt;code&gt;Visible at launch time&lt;/code&gt;.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;No Gorm então acesse &lt;code&gt;Document&lt;/code&gt; &amp;rarr; &lt;code&gt;New Application&lt;/code&gt;, depois vá em &lt;code&gt;Document&lt;/code&gt; &amp;rarr; &lt;code&gt;Save As...&lt;/code&gt;. Na janela de diálogo encontre seu projeto &lt;code&gt;Temperature&lt;/code&gt;, dentro dele &lt;code&gt;Resources&lt;/code&gt; e, dentro desse, salve como &lt;code&gt;Temperature.gorm&lt;/code&gt; &amp;ndash; confirme o &lt;code&gt;Replace&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Vão abrir três janelas: &lt;code&gt;Main Menu&lt;/code&gt;, &lt;code&gt;My Window&lt;/code&gt; e &lt;code&gt;Temperature.gorm&lt;/code&gt;. Se as janelas &lt;code&gt;Palettes&lt;/code&gt; e &lt;code&gt;Inspector&lt;/code&gt; não estiverem abertas, encontre-as no menu &lt;code&gt;Tools&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Selecione a janela &lt;code&gt;My Window&lt;/code&gt; &amp;ndash; ela representa a janela principal da aplicação &amp;ndash; e veja em &lt;code&gt;Inspector&lt;/code&gt; o campo &lt;code&gt;Title&lt;/code&gt; contendo &lt;code&gt;My Window&lt;/code&gt; &amp;ndash; se não estiver vendo, mude o seletor para &lt;code&gt;Attributes&lt;/code&gt;. Mude o título para &lt;code&gt;Temperature Converter&lt;/code&gt; &amp;ndash; repare que o título da janela &lt;code&gt;My Window&lt;/code&gt; também mudou.&lt;br /&gt;&lt;br /&gt;Repare que na janela &lt;code&gt;Palettes&lt;/code&gt; tem alguns &lt;em&gt;widgets&lt;/em&gt;. Para acrescentar um &lt;em&gt;widget&lt;/em&gt; à janela é só segurar e arrastar (&lt;em&gt;drag'n'drop&lt;/em&gt;). Vamos acrescentar três tipos de &lt;em&gt;widget&lt;/em&gt;: &lt;code&gt;Text&lt;/code&gt;, &lt;code&gt;System Bold&lt;/code&gt; e &lt;code&gt;Button&lt;/code&gt;. Adicione componentes até ficar mais ou menos com a cara deste corte:&lt;br /&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: crosshair; width: 300px; height: 104px; border: none;" src="http://3.bp.blogspot.com/_rGfO7DAuOSE/SRT6oI_4k9I/AAAAAAAAAKY/DJkNA1luv7o/s320/shot-1.jpg" alt="screenshot 1" id="BLOGGER_PHOTO_ID_5266109431820096466" /&gt;&lt;br /&gt;&lt;br /&gt;Para mudar o texto de um &lt;em&gt;widget&lt;/em&gt;, use o duplo clique. Você também pode mudar a borda no &lt;code&gt;Inspector&lt;/code&gt;. Altere os &lt;em&gt;widgets&lt;/em&gt; até ficarem mais ou menos assim:&lt;br /&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: crosshair; width: 248px; height: 121px; border: none;" src="http://4.bp.blogspot.com/_rGfO7DAuOSE/SRT6aGxRzBI/AAAAAAAAAKQ/CyH9pcV14jk/s320/shot-2.jpg" alt="screenshot 2" id="BLOGGER_PHOTO_ID_5266109190703795218" /&gt;&lt;br /&gt;&lt;br /&gt;Agora é hora de criar a classe para gerenciar essa janela! &lt;small&gt;Hora de &lt;em&gt;codar&lt;/em&gt;? Ainda não&amp;hellip;&lt;/small&gt;&lt;br /&gt;&lt;br /&gt;Na janela &lt;code&gt;Temperature.gorm&lt;/code&gt;, na barra principal clique em &lt;code&gt;Classes&lt;/code&gt; e selecione &lt;code&gt;NSObject&lt;/code&gt; &amp;ndash; futuca um pouco que você acha. No menu &lt;code&gt;Operations&lt;/code&gt; selecione &lt;code&gt;SubClass&lt;/code&gt;. Na lista da direita vai aparecer &lt;code&gt;NewClass&lt;/code&gt; e o &lt;code&gt;Inspector&lt;/code&gt; vai selecioná-lo &amp;ndash; veja a caixa &lt;code&gt;Class&lt;/code&gt; com &lt;code&gt;NewClass&lt;/code&gt;. Mude o nome da classe para &lt;code&gt;ConverterManager&lt;/code&gt;. Apenas confirme na janela &lt;code&gt;Modifying Class&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Podemos agora criar os atributos (&lt;em&gt;outlets&lt;/em&gt;) e métodos da classe (&lt;em&gt;actions&lt;/em&gt;).&lt;br /&gt;&lt;br /&gt;Vamos criar um atributo para cada caixa de texto que criamos &amp;ndash; incluside a de Kelvin.&lt;br /&gt;&lt;br /&gt;Na janela &lt;code&gt;Inspector&lt;/code&gt; há a aba &lt;code&gt;Outlets (0)&lt;/code&gt; com o botão &lt;code&gt;Add&lt;/code&gt;. Clique nesse botão e teremos &lt;code&gt;NewOutlet&lt;/code&gt; com um duplo clique você será capaz de mudar seu nome para &lt;code&gt;degreeC&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Crie mais dois atributos: &lt;code&gt;degreeF&lt;/code&gt; e &lt;code&gt;kelvin&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Para criar o primeiro método acesse a aba &lt;code&gt;Actions (0)&lt;/code&gt; e siga o mesmo procedimento anterior. Os métodos serão chamados &lt;code&gt;convertC2F:&lt;/code&gt; e &lt;code&gt;convertF2C:&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;E a classe já está pronta!&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Instanciando a classe&lt;/h3&gt;&lt;br /&gt;Mantendo a classe &lt;code&gt;ConverterManager&lt;/code&gt;, no menu principal do Gorm selecione &lt;code&gt;Classes&lt;/code&gt; &amp;rarr; &lt;code&gt;Instantiate&lt;/code&gt;. Na janela &lt;code&gt;Temperature.gorm&lt;/code&gt; aparecerá um objeto &lt;code&gt;ConverterManager&lt;/code&gt;: é agora que vem parte da mágica&amp;hellip;&lt;br /&gt;&lt;br /&gt;Precisamos inicialmente ligar o atributo &lt;code&gt;degreeC&lt;/code&gt; dessa instância à primeira caixa de texto da janela (ao lado do rótulo &lt;code&gt;&amp;deg;C&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;Segure a tecla &lt;code&gt;Ctrl&lt;/code&gt;, clique sobre a instância, segure e arraste, solte sobre a caixa de diálogo &amp;ndash; vai aparecer um &lt;code&gt;T&lt;/code&gt; na caixa &amp;ndash;, então, na janela &lt;code&gt;Inspector&lt;/code&gt; selecione &lt;code&gt;degreeC&lt;/code&gt; e clique no botão &lt;code&gt;Connect&lt;/code&gt;. Vai aparecer um &lt;code&gt;S&lt;/code&gt; sobre a instância e, na janela &lt;code&gt;Inspector&lt;/code&gt;, em &lt;code&gt;Connections&lt;/code&gt;, vai aparecer: &lt;code&gt;degreeC (TextField(0))&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Faça o mesmo para as outras caixas ligando cada caixa a um atributo.&lt;br /&gt;&lt;br /&gt;Agora precisamos fazer com que os botões acionem métodos da instância, para isso o procedimento é o inverso: segurando a tecla &lt;code&gt;Ctrl&lt;/code&gt; clique sobre o botão &lt;code&gt;Celsius to Fahrenheit&lt;/code&gt;, segure, arraste e solte sobre a instância de &lt;code&gt;ConverterManager&lt;/code&gt; na janela &lt;code&gt;Temperature.gorm&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Na janela &lt;code&gt;Inspector&lt;/code&gt; clique em &lt;code&gt;target&lt;/code&gt; &amp;rarr; &lt;code&gt;convertC2F:&lt;/code&gt; e então clique no botão &lt;code&gt;Connect&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Faça o mesmo para conectar o outro botão ao outro método. Agora todas as ações estão conectadas!&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Salvando tudo&lt;/h3&gt;&lt;br /&gt;Na janela &lt;code&gt;Temperature.gorm&lt;/code&gt;, selecione &lt;code&gt;Classes&lt;/code&gt; e encontre a classe &lt;code&gt;ConverterManager&lt;/code&gt;. Selecione-a, então, no menu principal do Gorm clique em &lt;code&gt;Classes&lt;/code&gt; &amp;rarr; &lt;code&gt;Create Class Files&lt;/code&gt;. Apenas confirme as duas janelas de diálogo. Isso criará os dois arquivos &lt;code&gt;ConverterManager.m&lt;/code&gt; e &lt;code&gt;ConverterManager.h&lt;/code&gt; dentro de &lt;code&gt;Resources&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Agora clique em &lt;code&gt;Document&lt;/code&gt; &amp;rarr; &lt;code&gt;Save All&lt;/code&gt; e &lt;code&gt;Quit&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;De volta ao Project Center&lt;/h3&gt;&lt;br /&gt;Volte ao Project Center e clique em &lt;code&gt;Project&lt;/code&gt; &amp;rarr; &lt;code&gt;Open...&lt;/code&gt; e abra o arquivo &lt;code&gt;PC.project&lt;/code&gt; do projeto &lt;code&gt;Temperature&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Na janela principal do projeto dê um duplo clique em &lt;code&gt;Classes&lt;/code&gt; e depois em &lt;code&gt;ConverterManager.m&lt;/code&gt;, isso adicionará o código ao projeto do Project Center.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Finalmente o código!&lt;/h3&gt;&lt;br /&gt;Precisamos finalmente editar o conteúdo dos métodos. Duplo clique sobre &lt;code&gt;ConverterManager.m&lt;/code&gt; na janela principal e vai abrir a janela do editor:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;/* All Rights reserved */&lt;br /&gt;&lt;br /&gt;#include &amp;lt;AppKit/AppKit.h&amp;gt;&lt;br /&gt;#include "ConverterManager.h"&lt;br /&gt;&lt;br /&gt;@implementation ConverterManager&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;- (void) convertC2F: (id)sender&lt;br /&gt;{&lt;br /&gt;  /* insert your code here */&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;- (void) convertF2C: (id)sender&lt;br /&gt;{&lt;br /&gt;  /* insert your code here */&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@end&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O código é &lt;a href="http://pt.wikipedia.org/wiki/Objective-C"&gt;Objective C&lt;/a&gt;, um variante orientado a objetos de C que lembra um pouco &lt;a href="http://smalltalk.org/"&gt;Smalltalk&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;O método &lt;code&gt;covertC2F&lt;/code&gt; deve obter o valor do atributo &lt;code&gt;degreeC&lt;/code&gt; &amp;ndash; que está ligado à caixa de diálogo com o valor em graus Celsius &amp;ndash;, calcular e ajustar os valores em Fahrenreit e Kelvin:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;- (void) convertC2F: (id)sender&lt;br /&gt;{&lt;br /&gt;  float celsius = [degreeC floatValue];&lt;br /&gt;  float fahrenreit = (9.0f * celsius / 5.0f) + 32.0f;&lt;br /&gt;&lt;br /&gt;  [degreeF setStringValue: [NSString stringWithFormat: @"%1.2f",&lt;br /&gt;    fahrenreit]];&lt;br /&gt;&lt;br /&gt;  [kelvin setStringValue: [NSString stringWithFormat: @"%1.2fK",&lt;br /&gt;    (celsius + 273.15f)]];&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O método &lt;code&gt;convertF2C&lt;/code&gt; deve fazer o contrário:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;- (void) convertF2C: (id)sender&lt;br /&gt;{&lt;br /&gt;  float fahrenreit = [degreeF floatValue];&lt;br /&gt;  float celsius = 5.0f * (fahrenreit - 32.0f) / 9.0f;&lt;br /&gt;&lt;br /&gt;  [degreeC setStringValue: [NSString stringWithFormat: @"%1.2f",&lt;br /&gt;    celsius]];&lt;br /&gt;&lt;br /&gt;  [kelvin setStringValue: [NSString stringWithFormat: @"%1.2fK",&lt;br /&gt;    (celsius + 273.15f)]];&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Salve agora (&lt;code&gt;M-s&lt;/code&gt;) e feche o editor. Clique no ícone com a chave de fenda para compilar:&lt;br /&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: crosshair; width: 44px; height: 43px; border: none;" src="http://4.bp.blogspot.com/_rGfO7DAuOSE/SRT6D8HyoII/AAAAAAAAAKI/gaevTgCX-7o/s320/shot-3.jpg" alt="Build" id="BLOGGER_PHOTO_ID_5266108809888309378" /&gt;&lt;br /&gt;&lt;br /&gt;Na janela de &lt;em&gt;build&lt;/em&gt; há outro ícone igual, clique nele para compilar. Se tudo correr bem você verá uma bela mensagem:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;=== Build succeeded! ===&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Se falhar, volte e veja o que está errado.&lt;br /&gt;&lt;br /&gt;Clique então no ícone do foguete para rodar:&lt;br /&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: crosshair;width: 43px; height: 43px; border: none;" src="http://1.bp.blogspot.com/_rGfO7DAuOSE/SRT5yacRN5I/AAAAAAAAAKA/ujrdNQJQzPE/s320/shot-4.jpg" alt="Launch" id="BLOGGER_PHOTO_ID_5266108508789618578" /&gt;&lt;br /&gt;&lt;br /&gt;Na janela &lt;code&gt;Launch&lt;/code&gt; clique no mesmo ícone e a janela irá abrir. Faça alguns testes para ver se funciona bem.&lt;br /&gt;&lt;br /&gt;Para sair clique com o botão direito e escolha &lt;code&gt;Quit&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Se tudo funcionar bem, seu programa está pronto! Salve tudo em &lt;code&gt;Project&lt;/code&gt; &amp;rarr; &lt;code&gt;Save&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Instalando a aplicação&lt;/h3&gt;&lt;br /&gt;Para instalar, abra um terminal:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;cd Temperature/&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;make&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;sudo make install&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Assim sua aplicação estará instalada em &lt;code&gt;/usr/GNUstep/System/Applications/Temperature.app&lt;/code&gt; &amp;ndash; ou &lt;code&gt;/usr/GNUstep/Local/Applications/Temperature.app&lt;/code&gt;, se você se esqueceu de ajustar o conteúdo da variável de ambiente &lt;code&gt;GNUSTEP_INSTALLATION_DOMAIN&lt;/code&gt; &amp;ndash; e você executá-la com o comando:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;openapp Temperature&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conclusão&lt;/h3&gt;&lt;br /&gt;Espero que com este artigo algumas pessoas se interessem pelo desenvolvimento de aplicações para ambiente GNUstep, que aliás roda sobre Mac OS X também &amp;ndash; em plataforma OS X, o &lt;a href="http://www.windowmaker.info/development.php?show=wings"&gt;WINGs&lt;/a&gt; (&lt;em&gt;toolkit&lt;/em&gt; de &lt;em&gt;widgets&lt;/em&gt; para Window Maker) e o GNUstep são abstrações do &lt;a href="http://pt.wikipedia.org/wiki/Cocoa"&gt;Cocoa&lt;/a&gt;, &lt;em&gt;toolkit&lt;/em&gt; de &lt;em&gt;widgets&lt;/em&gt; do OS X.&lt;br /&gt;&lt;br /&gt;A facilidade de desenvolvimento de aplicações gráficas para GNUstep com Project Center e Gorm é incrível, apesar de seu jeitão esquisito e do uso da tremendamente estranha linguagem de programação Objective C.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas&lt;br /&gt;&lt;br /&gt;&lt;small&gt;PS: Eu já estava morrendo de sono quando escrevi este artigo, portanto alguns erros de português podem ocorrer. Por favor me avisem!&lt;/small&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-4168562966807122189?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/4168562966807122189/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=4168562966807122189' title='4 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/4168562966807122189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/4168562966807122189'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2008/11/desenvolvendo-aplicacoes-gnustep.html' title='Desenvolvendo aplicações GNUstep'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_rGfO7DAuOSE/SRT62RK9EZI/AAAAAAAAAKg/53tVzG0MiP8/s72-c/gnustep.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-1735364715635785801</id><published>2008-10-16T21:21:00.015-03:00</published><updated>2008-10-23T22:59:50.821-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Lua'/><title type='text'>Portando GDBM para Lua</title><content type='html'>&lt;img style="border: medium none ; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://photos1.blogger.com/x/blogger/6505/3295/200/690565/lua.jpg" alt="Lua" /&gt; Espero que este artigo seja interessante. =)&lt;br /&gt;&lt;br /&gt;Além de ser um linguagem de programação brasileira, desenvolvida na &lt;a href="http://www.puc-rio.br/"&gt;PUC Rio&lt;/a&gt;, &lt;a href="http://www.lua.org/portugues.html"&gt;Lua&lt;/a&gt; possui uma &lt;a href="http://www.lua.org/pil/24.html"&gt;poderosa API com C&lt;/a&gt;, na minha opinião, sua maior vantagem.&lt;br /&gt;&lt;br /&gt;A outra parte importante deste artigo é &lt;a href="http://www.gnu.org/software/gdbm/gdbm.html"&gt;GDBM&lt;/a&gt;, um conjunto de sub-rotinas de banco de dados baseado em &lt;em&gt;hash&lt;/em&gt;, uma alternativa livre ao Unix DBM.&lt;br /&gt;&lt;br /&gt;A ideia aqui é demonstrar um pouco dos recursos da biblioteca GDBM e como é simples estender a linguagem Lua.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;O objeto&lt;/h3&gt;&lt;br /&gt;Pessoalmente, quando crio extensões para Lua, gosto de criar primeiro uma classe que represente meu objeto principal, ou uma classe para cada tipo de objeto que será usado nos &lt;em&gt;scripts&lt;/em&gt;; depois crio um módulo que porta cada recurso para Lua.&lt;br /&gt;&lt;br /&gt;Neste caso vamos criar uma classe &lt;code&gt;GdbmObject&lt;/code&gt; que faça a interface com a base de dados, &lt;code&gt;GDBM_FILE&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;É claro que poderia ter usado direto &lt;code&gt;GDBM_FILE&lt;/code&gt;, aliás comecei fazendo assim, mas acabei voltando ao procedimento que me é natural.&lt;br /&gt;&lt;br /&gt;Quanto a objetos &lt;code&gt;datum&lt;/code&gt;, não vi necessidade de criar uma interface, já que &lt;code&gt;datum&lt;/code&gt; não passa de uma representação mais flexível de &lt;em&gt;string&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;O cabeçalho, &lt;code&gt;gdbmobj.h&lt;/code&gt;, começa então com as instruções de preprocessamento triviais e a inclusão do cabeçalho &lt;code&gt;gdbm.h&lt;/code&gt;, essencial para lidar com GDBM:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#ifndef _GDBMOBJ_H_&lt;br /&gt;#define _GDBMOBJ_H_&lt;br /&gt;&lt;br /&gt;#include &amp;lt;gdbm.h&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Podemos então criar a classe e começar os métodos públicos pelo construtor e o destruidor.&lt;br /&gt;&lt;br /&gt;O Construtor precisa criar o &lt;code&gt;GDBM_FILE&lt;/code&gt;. Para tanto, temos a função &lt;code&gt;gdbm_open&lt;/code&gt;, que recebe cinco parâmetros:&lt;br /&gt;&lt;ol&gt; &lt;li&gt;o nome do arquivo&lt;/li&gt; &lt;li&gt;o tamanho de blocos para leitura e gravação em &lt;em&gt;bytes&lt;/em&gt; (mínimo 512)&lt;/li&gt; &lt;li&gt;o modo de leitura e gravação&lt;/li&gt; &lt;li&gt;as permissões do arquivo, para caso ele seja criado&lt;/li&gt; &lt;li&gt;uma função de &lt;em&gt;callback&lt;/em&gt; a ser chamada quando ocorrer um erro fatal&lt;/li&gt; &lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Assim, pelo menos alguns desses parâmetros precisam ser argumentos do construtor. Para simplificar, vamos reduzir: caso o &lt;em&gt;callback&lt;/em&gt; seja nulo, é usada uma função padrão. Vamos ficar com ela:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;class GdbmObject {&lt;br /&gt;    public:&lt;br /&gt;        GdbmObject(&lt;br /&gt;            const char *name,&lt;br /&gt;            int block=512,&lt;br /&gt;            int mode=GDBM_READER,&lt;br /&gt;            int perm=0644&lt;br /&gt;        );&lt;br /&gt;        ~GdbmObject();&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Nosso construtor então recebe os elementos essencias para &lt;code&gt;gdbm_open&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Os outros métodos públicos importantes precisam representar as funções de &lt;code&gt;gdbm.h&lt;/code&gt; que queremos acessar, em ordem alfabética: &lt;code&gt;gdbm_close&lt;/code&gt;, &lt;code&gt;gdbm_delete&lt;/code&gt;, &lt;code&gt;gdbm_exists&lt;/code&gt;, &lt;code&gt;gdbm_fetch&lt;/code&gt;, &lt;code&gt;gdbm_firstkey&lt;/code&gt;, &lt;code&gt;gdbm_nextkey&lt;/code&gt;, &lt;code&gt;gdbm_reorganize&lt;/code&gt;, &lt;code&gt;gdbm_setopt&lt;/code&gt;, &lt;code&gt;gdbm_store&lt;/code&gt; e &lt;code&gt;gdbm_sync&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;        bool gclose(void);&lt;br /&gt;        bool gdelete(const char *);&lt;br /&gt;        bool gexists(const char *);&lt;br /&gt;        double gfetch_number(const char *);&lt;br /&gt;        const char *gfetch_string(const char *);&lt;br /&gt;        const char *gnext(const char *key=NULL);&lt;br /&gt;        bool greorganize(void);&lt;br /&gt;        bool gsetopt(int, int);&lt;br /&gt;        bool gstore(const char *, const char *);&lt;br /&gt;        bool gstore(const char *, double);&lt;br /&gt;        bool gsync(void);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora um método para verificar se a base está fechada um método para retornar a última mensagem de erro:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;        bool isclosed(void) const;&lt;br /&gt;        const char *last_error(void) const;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Entrando em território privado, precisamos de dois atributos: um &lt;em&gt;flag&lt;/em&gt; que indique se a base está fechada e o &lt;code&gt;GDBM_FILE&lt;/code&gt; em si:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    private:&lt;br /&gt;        bool closed;&lt;br /&gt;        GDBM_FILE fd;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Então um método privado para converter &lt;code&gt;datum&lt;/code&gt; em &lt;em&gt;string&lt;/em&gt; e outro para fazer o &lt;code&gt;gdbm_fetch&lt;/code&gt; comum a &lt;code&gt;gfetch_number&lt;/code&gt; e &lt;code&gt;gfetch_string&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;        static const char *get_string(datum);&lt;br /&gt;        datum gfetch(const char *);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;#endif /* _GDBMOBJ_H_ */&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Código dos métodos&lt;/h3&gt;&lt;br /&gt;A lógica em si vai no arquivo &lt;code&gt;gdbmobj.cc&lt;/code&gt;, que deve iniciar incluindo nosso cabeçalho e o cabeçalho &lt;code&gt;cstring&lt;/code&gt;, para que possamos usar &lt;code&gt;strlen&lt;/code&gt; nas conversões entre &lt;em&gt;strings&lt;/em&gt; e &lt;code&gt;datum&lt;/code&gt;.&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#include &amp;lt;cstring&amp;gt;&lt;br /&gt;#include "gdbmobj.h"&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O código do construtor é simples: basta pegar os argumentos e passá-lo como parâmetro para &lt;code&gt;gdbm_close&lt;/code&gt; &amp;ndash; não esqueça de ajudar &lt;code&gt;closed&lt;/code&gt; como &lt;code&gt;false&lt;/code&gt;!&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;GdbmObject::GdbmObject(&lt;br /&gt;    const char *name, int block, int mode, int perm&lt;br /&gt;): closed(false)&lt;br /&gt;{&lt;br /&gt;    this-&amp;gt;fd = gdbm_open(&lt;br /&gt;        const_cast&amp;lt;char *&amp;gt;(name),&lt;br /&gt;        block, mode, perm, NULL&lt;br /&gt;    );&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O destruidor deve apenas fechar a base, caso esqueçam de fazê-lo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;GdbmObject::~GdbmObject() {&lt;br /&gt;    this&amp;gt;gclose();&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Precisamos fazer o &lt;code&gt;gclose&lt;/code&gt;. Ele deve:&lt;br /&gt;&lt;ol&gt; &lt;li&gt;verificar se a base já não está fechada&lt;/li&gt; &lt;li&gt;fechar a base&lt;/li&gt; &lt;li&gt;verificar se não houve erro&lt;/li&gt; &lt;li&gt;marcar o objeto como fechado&lt;/li&gt; &lt;/ol&gt;&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;bool GdbmObject::gclose(void) {&lt;br /&gt;    if (this-&amp;gt;closed)&lt;br /&gt;        return false;&lt;br /&gt;&lt;br /&gt;    gdbm_close(this-&amp;gt;fd);&lt;br /&gt;&lt;br /&gt;    if (gdbm_errno == GDBM_NO_ERROR) {&lt;br /&gt;        this-&amp;gt;closed = true;&lt;br /&gt;        return true;&lt;br /&gt;    } else&lt;br /&gt;        return false;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora o método &lt;code&gt;gdelete&lt;/code&gt;: primeiro verificar se já não está fechado &amp;ndash; todos os métodos precisam verificar isso &amp;ndash;, em seguida converter a chave &lt;em&gt;string&lt;/em&gt; em &lt;code&gt;datum&lt;/code&gt; &amp;ndash; para isso o cabeçalho &lt;code&gt;cstring&lt;/code&gt; &amp;ndash; e então fazer o que tem de ser feito:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;bool GdbmObject::gdelete(const char *key) {&lt;br /&gt;    if (this-&amp;gt;close)&lt;br /&gt;        return false;&lt;br /&gt;&lt;br /&gt;    datum dkey;&lt;br /&gt;    dkey.dptr = const_cast&amp;lt;char *&amp;gt;(key);&lt;br /&gt;    dkey.dsize = strlen(key);&lt;br /&gt;&lt;br /&gt;    gdbm_delete(this-&amp;gt;fd, dkey);&lt;br /&gt;&lt;br /&gt;    return gdbm_errno == GDBM_NO_ERROR;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O próximo método verifica se uma chave existe e funciona similar ao &lt;code&gt;gdelete&lt;/code&gt;, só o retorno é que tem um significado diferente:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;bool GdbmObject::gexists(const char *key) {&lt;br /&gt;    if (this-&amp;gt;close)&lt;br /&gt;        return false;&lt;br /&gt;&lt;br /&gt;    datum dkey;&lt;br /&gt;    dkey.dptr = const_cast&amp;lt;char *&amp;gt;(key);&lt;br /&gt;    dkey.dsize = strlen(key);&lt;br /&gt;&lt;br /&gt;    return static_cast&amp;lt;bool&amp;gt;(gdbm_exists(this-&amp;gt;fd, dkey));&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Os métodos &lt;code&gt;gfetch_number&lt;/code&gt; e &lt;code&gt;gfetch_string&lt;/code&gt; devem retornar um valor para uma chave, um retornando &lt;code&gt;double&lt;/code&gt; e outro &lt;em&gt;string&lt;/em&gt; (&lt;code&gt;const char *&lt;/code&gt;), ambos usando o método privado &lt;code&gt;gfetch&lt;/code&gt; para obter a chave em formato &lt;code&gt;datum&lt;/code&gt; antes:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;double GdbmObject::gfetch_number(const char *key) {&lt;br /&gt;    datum data = this-&amp;gt;gfetch(key);&lt;br /&gt;    double resp = -1.;&lt;br /&gt;&lt;br /&gt;    if (data.dsize == sizeof(double)) {&lt;br /&gt;        double *aux = reinterpret_cast&amp;lt;double *&amp;gt;(data.ptr);&lt;br /&gt;        resp = *aux;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    delete[] data.dptr;&lt;br /&gt;    return resp;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;const char *GdbmObject::gfetch_string(const char *key) {&lt;br /&gt;    if (this-&amp;gt;closed)&lt;br /&gt;        return NULL;&lt;br /&gt;&lt;br /&gt;    datum data = this-&amp;gt;gfetch(key);&lt;br /&gt;    const char *aux = get_string(data);&lt;br /&gt;&lt;br /&gt;    delete[] data.dptr;&lt;br /&gt;    return aux;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O método &lt;code&gt;gnext&lt;/code&gt; é mais complexo, pois faz interface com &lt;code&gt;gdbm_firstkey&lt;/code&gt; (quando a chave for nula) e com &lt;code&gt;gdbm_nextkey&lt;/code&gt;.&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;const char *GdbmObject::gnext(const char *key) {&lt;br /&gt;    if (this-&amp;gt;closed)&lt;br /&gt;        return NULL;&lt;br /&gt;&lt;br /&gt;    datum next;&lt;br /&gt;    next.dptr = NULL;&lt;br /&gt;    next.dsize = 0;&lt;br /&gt;&lt;br /&gt;    if (key == NULL)&lt;br /&gt;        next = gdbm_firstkey(this-&amp;gt;fd);&lt;br /&gt;&lt;br /&gt;    else {&lt;br /&gt;        datum current;&lt;br /&gt;        current.dptr = const_cast&amp;lt;char *&amp;gt;(key);&lt;br /&gt;        current.dsize = strlen(key);&lt;br /&gt;        next = gdbm_nextkey(this-&amp;gt;fd, current);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (next.dptr != NULL) {&lt;br /&gt;        const char *aux = get_string(next);&lt;br /&gt;&lt;br /&gt;        delete[] next.dptr;&lt;br /&gt;        return aux;&lt;br /&gt;    } else&lt;br /&gt;        return NULL;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O método &lt;code&gt;greorganize&lt;/code&gt; é similar a &lt;code&gt;gclose&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;bool GdbmObject::greorganize(void) {&lt;br /&gt;    if (this-&amp;gt;closed)&lt;br /&gt;        return false;&lt;br /&gt;&lt;br /&gt;    gdbm_reorganize(this-&amp;gt;fd);&lt;br /&gt;    return gdbm_errno == GDBM_NO_ERROR;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O método &lt;code&gt;gsetopt&lt;/code&gt; precisa tornar transparente algumas peculiaridades de &lt;code&gt;gdbm_setopt&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;bool GdbmObject::gsetopt(int option, int value) {&lt;br /&gt;    if (this-&amp;gt;closed)&lt;br /&gt;        return false;&lt;br /&gt;&lt;br /&gt;    gdbm_setopt(this-&amp;gt;fd, option, &amp;amp;value, sizeof(int));&lt;br /&gt;    return gdbm_errno == GDBM_NO_ERROR;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Temos dois métodos &lt;code&gt;gstore&lt;/code&gt;: um para armazenar números, outro para &lt;em&gt;strings&lt;/em&gt;, mas a lógica é a mesma: converter tudo pra &lt;code&gt;datum&lt;/code&gt; e usar &lt;code&gt;gdbm_store&lt;/code&gt; para armazenar. Vamos usar apenas o &lt;em&gt;flag&lt;/em&gt; &lt;code&gt;GDBM_REPLACE&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;bool GdbmObject::gstore(const char *key, double value) {&lt;br /&gt;    if (this-&amp;gt;closed)&lt;br /&gt;        return false;&lt;br /&gt;&lt;br /&gt;    datum dkey, data;&lt;br /&gt;&lt;br /&gt;    dkey.dptr = const_cast&amp;lt;char *&amp;gt;(key);&lt;br /&gt;    dkey.dsize = strlen(key);&lt;br /&gt;    data.dptr = reinterpret_cast&amp;lt;char *&amp;gt;(&amp;amp;value);&lt;br /&gt;    data.dsize = sizeof(double);&lt;br /&gt;&lt;br /&gt;    gdbm_store(this-&amp;gt;fd, dkey, data, GDBM_REPLACE);&lt;br /&gt;    return gdbm_errno == GDBM_NO_ERROR;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;bool GdbmObject::gstore(const char *key, const char *value) {&lt;br /&gt;    if (this-&amp;gt;closed)&lt;br /&gt;        return false;&lt;br /&gt;&lt;br /&gt;    datum dkey, data;&lt;br /&gt;&lt;br /&gt;    dkey.dptr = const_cast&amp;lt;char *&amp;gt;(key);&lt;br /&gt;    dkey.dsize = strlen(key);&lt;br /&gt;    data.dptr = const_cast&amp;lt;char *&amp;gt;(&amp;amp;value);&lt;br /&gt;    data.dsize = sizeof(double);&lt;br /&gt;&lt;br /&gt;    gdbm_store(this-&amp;gt;fd, dkey, data, GDBM_REPLACE);&lt;br /&gt;    return gdbm_errno == GDBM_NO_ERROR;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O método &lt;code&gt;gsync&lt;/code&gt; é quase idêntico a &lt;code&gt;greorganize&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;bool GdbmObject::gsync(void) {&lt;br /&gt;    if (this-&amp;gt;closed)&lt;br /&gt;        return false;&lt;br /&gt;&lt;br /&gt;    gdbm_sync(this-&amp;gt;fd);&lt;br /&gt;    return gdbm_errno == GDBM_NO_ERROR;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora os métodos constantes, &lt;code&gt;isclosed&lt;/code&gt; (está fechado) e &lt;code&gt;last_error&lt;/code&gt; (último erro):&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;bool GdbmObject::isclosed(void) const {&lt;br /&gt;    return this-&amp;gt;closed;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;const char *GdbmObject::last_error(void) const {&lt;br /&gt;    if (this-&amp;gt;closed)&lt;br /&gt;        return "database closed";&lt;br /&gt;&lt;br /&gt;    else&lt;br /&gt;        return const_cast&amp;lt;const char *&amp;gt;(gdbm_strerror(gdbm_errno));&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O método &lt;code&gt;gfetch&lt;/code&gt; faz a verdadeira interface com &lt;code&gt;gdbm_fetch&lt;/code&gt; para &lt;code&gt;gfetch_number&lt;/code&gt; e &lt;code&gt;gfetch_string&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;datum GdbmObject::gfetch(const char *key) {&lt;br /&gt;    datum data;&lt;br /&gt;    data.dptr = NULL;&lt;br /&gt;    data.dsize = 0;&lt;br /&gt;&lt;br /&gt;    if (!this-&amp;gt;closed) {&lt;br /&gt;        datum dkey;&lt;br /&gt;        dkey.dptr = const_cast&amp;lt;char *&amp;gt;(key);&lt;br /&gt;        dkey.dsize = strlen(key);&lt;br /&gt;&lt;br /&gt;        data = gdbm_fetch(this-&amp;gt;fd, dkey);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return data;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O método estático &lt;code&gt;get_string&lt;/code&gt; precisa converter &lt;code&gt;datum&lt;/code&gt; em &lt;em&gt;string&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;const char *GdbmObject::get_string(datum data) {&lt;br /&gt;    if (data.dptr == NULL)&lt;br /&gt;        return NULL;&lt;br /&gt;&lt;br /&gt;    char *aux = new char[data.dsize + 1];&lt;br /&gt;&lt;br /&gt;    for (int i=0; i&amp;lt;data.dsize; ++i)&lt;br /&gt;        aux[i] = data.dptr[i];&lt;br /&gt;    aux[data.dsize] = '\0';&lt;br /&gt;&lt;br /&gt;    return const_cast&amp;lt;const char *&amp;gt;(aux);&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Aqui cabe um comentário para justificar o uso de &lt;code&gt;for&lt;/code&gt; em lugar de &lt;code&gt;strcpy&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;O ponteiro de &lt;code&gt;datum&lt;/code&gt; &lt;strong&gt;não é uma &lt;em&gt;string&lt;/em&gt;&lt;/strong&gt;, é um ponteiro para um grupo de &lt;em&gt;bytes&lt;/em&gt; &amp;ndash; mais ou menos similiar a uma &lt;em&gt;string&lt;/em&gt; de Pascal, que tem a vantagem de suportar carácter nulo como parte. Portanto pode não ter um carácter nulo ou ter caracteres nulos dentro do grupo de &lt;em&gt;bytes&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Então a função &lt;code&gt;strcpy&lt;/code&gt; não é aplicável.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Que entre a Lua!&lt;/h3&gt;&lt;br /&gt;Vamos introduzir então a API com Lua, no arquivo &lt;code&gt;luagdbm.cc&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;O código precisa começar incluindo o cabeçalho de nossa classe e o cabeçalho de Lua para C++:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#include &amp;lt;lua.hpp&amp;gt;&lt;br /&gt;#include "gdbmobj.h"&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Algumas configurações importantes são dados de versão e nome do módulo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#define VERSION "1.0"&lt;br /&gt;#define MODULE "gdbm"&lt;br /&gt;const char *modulename = MODULE;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Quando Lua carrega uma extensão, chama a função &lt;code&gt;luaopen_&lt;em&gt;nome_da_função&lt;/em&gt;&lt;/code&gt;, no caso &lt;code&gt;luaopen_gdbm&lt;/code&gt;, que deve receber um ponteiro para um estado Lua e deve responder com um inteiro representando a quantidade de elementos empilhados para o estado Lua ao final.&lt;br /&gt;&lt;br /&gt;Outra função interessante é &lt;code&gt;set_info&lt;/code&gt;, que serve para separar de &lt;code&gt;luaopen_*&lt;/code&gt; os dados de diretos, &lt;em&gt;strings&lt;/em&gt; e números.&lt;br /&gt;&lt;br /&gt;Também vamos criar uma função para empilhar um objeto &lt;code&gt;GdbmObject&lt;/code&gt; para o estado Lua:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;extern "C" int luaopen_gdbm(lua_State *);&lt;br /&gt;static void set_info(lua_State *);&lt;br /&gt;static void pushdb(lua_State *, GdbmObject *);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora vamos declarar uma função para cada método público de &lt;code&gt;GdbmObject&lt;/code&gt; &amp;ndash; é nossa interface com Lua:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;extern "C" {&lt;br /&gt;    static int luagdbm_close(lua_State *);&lt;br /&gt;    static int luagdbm_delete(lua_State *);&lt;br /&gt;    static int luagdbm_exists(lua_State *);&lt;br /&gt;    static int luagdbm_fetch_number(lua_State *);&lt;br /&gt;    static int luagdbm_fetch_string(lua_State *);&lt;br /&gt;    static int luagdbm_isclosed(lua_State *);&lt;br /&gt;    static int luagdbm_next(lua_State *);&lt;br /&gt;    static int luagdbm_open(lua_State *);&lt;br /&gt;    static int luagdbm_reorganize(lua_State *);&lt;br /&gt;    static int luagdbm_setopt(lua_State *);&lt;br /&gt;    static int luagdbm_store(lua_State *);&lt;br /&gt;    static int luagdbm_sync(lua_State *);&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Podemos implementar cada uma dessas funções.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Função de carregamento&lt;/h3&gt;&lt;br /&gt;Como já foi dito, a função de carrgamento é &lt;code&gt;luaopen_gdbm&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Ela deve criar um vetor de &lt;code&gt;luaL_reg&lt;/code&gt; relacionando cada função com as chaves no módulo em lua, terminando com nulo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;int luaopen_gdbm(lua_State *L) {&lt;br /&gt;    static const luaL_reg gdbm_funcs[] = {&lt;br /&gt;        {"close", luagdbm_close },&lt;br /&gt;        {"delete", luagdbm_delete },&lt;br /&gt;        {"exists", luagdbm_exists },&lt;br /&gt;        {"fetch_number", luagdbm_fetch_number },&lt;br /&gt;        {"fetch_string", luagdbm_fetch_string },&lt;br /&gt;        {"isclosed", luagdbm_isclosed },&lt;br /&gt;        {"next", luagdbm_next },&lt;br /&gt;        {"open", luagdbm_open },&lt;br /&gt;        {"reorganize", luagdbm_reorganize },&lt;br /&gt;        {"setopt", luagdbm_setopt },&lt;br /&gt;        {"store", luagdbm_store },&lt;br /&gt;        {"sync", luagdbm_sync },&lt;br /&gt;        { NULL, NULL }&lt;br /&gt;    };&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Então o módulo deve ser registrado com as funções. Para poder usar o módulo como metatabela para os objetos &lt;code&gt;GdbmObject&lt;/code&gt;, vamos também criar também a chave &lt;code&gt;__index&lt;/code&gt; apontando para o próprio módulo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    luaLregister(L, modulename, gdbm_funcs);&lt;br /&gt;    lua_pushliteral(L, "__index");&lt;br /&gt;    lua_getglobal(L, modulename);&lt;br /&gt;    lua_settable(L, -3);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora só falta chamar &lt;code&gt;set_info&lt;/code&gt; e informar que uma estrutura &amp;ndash; o módulo &amp;ndash; foi empilhada:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    set_info(L);&lt;br /&gt;    return 1;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Função para empilhar um objeto de banco de dados&lt;/h3&gt;&lt;br /&gt;É a função &lt;code&gt;pushdb&lt;/code&gt;, que recebe a pilha e um ponteiro para o objeto a ser empilhado.&lt;br /&gt;&lt;br /&gt;A função também deve associar ao objeto o próprio módulo como metatabela:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;void pushdb(lua_State *L, GdbmObject *db) {&lt;br /&gt;    lua_pushlightuserdata(L, db);&lt;br /&gt;    lua_getglobal(L, modulename);&lt;br /&gt;    lua_setmetatable(L, -2);&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Vamos deixar &lt;code&gt;set_info&lt;/code&gt; para o final&amp;hellip;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Funções de interface com os métodos público&lt;/h3&gt;&lt;br /&gt;Praticamente todas funções devem:&lt;br /&gt;&lt;ol&gt; &lt;li&gt;carregar o ponteiro para objeto &lt;code&gt;GdbmObject&lt;/code&gt; do estado&lt;/li&gt; &lt;li&gt;verificar se ele ele não está nulo&lt;/li&gt; &lt;li&gt;fazer o que tem de ser feito&lt;/li&gt; &lt;li&gt;retornar o que foi solicitado ou uma mensagem de erro&lt;/li&gt; &lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Repare que todas as funções retornam a quantidade de elementos empilhados (&lt;code&gt;lua_push*&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;Assim como começamos pelo método &lt;code&gt;gclose&lt;/code&gt;, vamos começar pela função &lt;code&gt;luagdbm_close&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;int luagdbm_close(lua_State *L) {&lt;br /&gt;    GdbmObject *db =&lt;br /&gt;        reinterpret_cast&amp;lt;GdbmObject *&amp;gt;(lua_touserdata(L, 1));&lt;br /&gt;&lt;br /&gt;    if (db == NULL) {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, "no database");&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (db-&amp;gt;gclose()) {&lt;br /&gt;        delete db;&lt;br /&gt;        lua_pushboolean(L, 1);&lt;br /&gt;        return 1;&lt;br /&gt;&lt;br /&gt;    } else {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, db-&amp;gt;last_error());&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A função &lt;code&gt;luagdbm_delete&lt;/code&gt; ainda precisa recuperar a chave a ser deletada:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;int luagdbm_delete(lua_State *L) {&lt;br /&gt;    GdbmObject *db =&lt;br /&gt;        reinterpret_cast&amp;lt;GdbmObject *&amp;gt;(lua_touserdata(L, 1));&lt;br /&gt;&lt;br /&gt;    if (db == NULL) {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, "no database");&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    const char *key = lua_tostring(L, 2);&lt;br /&gt;&lt;br /&gt;    if (db-&amp;gt;gdelete(key)) {&lt;br /&gt;        lua_pushboolean(L, 1);&lt;br /&gt;        return 1;&lt;br /&gt;&lt;br /&gt;    } else {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, db-&amp;gt;last_error());&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A função &lt;code&gt;luagdbm_exists&lt;/code&gt; é similar à anterior, só que mais simples:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;int luagdbm_exists(lua_State *L) {&lt;br /&gt;    GdbmObject *db =&lt;br /&gt;        reinterpret_cast&amp;lt;GdbmObject *&amp;gt;(lua_touserdata(L, 1));&lt;br /&gt;&lt;br /&gt;    if (db == NULL) {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, "no database");&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    const char *key = lua_tostring(L, 2);&lt;br /&gt;&lt;br /&gt;    lua_pushboolean(L, static_cast&amp;lt;int&amp;gt;(db-&amp;gt;gexists(key)));&lt;br /&gt;    return 1;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As funções &lt;code&gt;luagdbm_fetch_number&lt;/code&gt; e &lt;code&gt;luagdbm_fetch_string&lt;/code&gt; são similares, só que, assim como os métodos &lt;code&gt;gfetch_number&lt;/code&gt; e &lt;code&gt;gfetch_string&lt;/code&gt;, retornam número e &lt;em&gt;string&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;int luagdbm_fetch_number(lua_State *L) {&lt;br /&gt;    GdbmObject *db =&lt;br /&gt;        reinterpret_cast&amp;lt;GdbmObject *&amp;gt;(lua_touserdata(L, 1));&lt;br /&gt;&lt;br /&gt;    if (db == NULL) {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, "no database");&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    const char *key = lua_tostring(L, 2);&lt;br /&gt;    double value = db-&amp;gt;getch_number(key);&lt;br /&gt;&lt;br /&gt;    lua_pushnumber(L, value);&lt;br /&gt;&lt;br /&gt;    if (value == -1.) {&lt;br /&gt;        lua_pushstring(L, db-&amp;gt;last_error());&lt;br /&gt;        return 2;&lt;br /&gt;&lt;br /&gt;    } else&lt;br /&gt;        return 1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int luagdbm_fetch_string(lua_State *L) {&lt;br /&gt;    GdbmObject *db =&lt;br /&gt;        reinterpret_cast&amp;lt;GdbmObject *&amp;gt;(lua_touserdata(L, 1));&lt;br /&gt;&lt;br /&gt;    if (db == NULL) {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, "no database");&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    const char *key = lua_tostring(L, 2);&lt;br /&gt;    const char *value = db-&amp;gt;getch_string(key);&lt;br /&gt;&lt;br /&gt;    if (value == NULL) {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, db-&amp;gt;last_error());&lt;br /&gt;        return 2;&lt;br /&gt;&lt;br /&gt;    } else {&lt;br /&gt;        lua_pushstring(L, value);&lt;br /&gt;        return 1;&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A função &lt;code&gt;luagdbm_isclose&lt;/code&gt; é extremamente simples:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;int luagdbm_isclosed(lua_State *L) {&lt;br /&gt;    GdbmObject *db =&lt;br /&gt;        reinterpret_cast&amp;lt;GdbmObject *&amp;gt;(lua_touserdata(L, 1));&lt;br /&gt;&lt;br /&gt;    if (db == NULL) {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, "no database");&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    lua_pushboolean(L, static_cast&amp;lt;int&amp;gt;(db-&amp;gt;isclosed()));&lt;br /&gt;    return 1;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A função &lt;code&gt;luagdbm_next&lt;/code&gt; também não é complicada, apenas é preciso verificar se o parâmetro chave foi fornecido:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;int luagdbm_next(lua_State *L) {&lt;br /&gt;    GdbmObject *db =&lt;br /&gt;        reinterpret_cast&amp;lt;GdbmObject *&amp;gt;(lua_touserdata(L, 1));&lt;br /&gt;&lt;br /&gt;    if (db == NULL) {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, "no database");&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    const char *key = NULL;&lt;br /&gt;    if (lua_type(L, 2) == LUA_TSTRING)&lt;br /&gt;        key = lua_tostring(L, 2);&lt;br /&gt;&lt;br /&gt;    const char *value = db-&amp;gt;gnext(key);&lt;br /&gt;&lt;br /&gt;    if (value == NULL) {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, db-&amp;gt;last_error());&lt;br /&gt;        return 2;&lt;br /&gt;&lt;br /&gt;    } else {&lt;br /&gt;        lua_pushstring(L, value);&lt;br /&gt;        return 1;&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Vamos deixar a função &lt;code&gt;luagdbm_open&lt;/code&gt;, devido a sua complexidade, então passamos direto para &lt;code&gt;luagdbm_reorganize&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;int luagdbm_reorganize(lua_State *L) {&lt;br /&gt;    GdbmObject *db =&lt;br /&gt;        reinterpret_cast&amp;lt;GdbmObject *&amp;gt;(lua_touserdata(L, 1));&lt;br /&gt;&lt;br /&gt;    if (db == NULL) {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, "no database");&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (db-&amp;gt;greorganize()) {&lt;br /&gt;        lua_pushboolean(L, 1);&lt;br /&gt;        return 1;&lt;br /&gt;&lt;br /&gt;    } else {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, db-&amp;gt;last_error());&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A função &lt;code&gt;luagdbm_setopt&lt;/code&gt; precisa obter dois inteiros, representando a opção e o valor a ser ajustado:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;int luagdbm_setopt(lua_State *L) {&lt;br /&gt;    GdbmObject *db =&lt;br /&gt;        reinterpret_cast&amp;lt;GdbmObject *&amp;gt;(lua_touserdata(L, 1));&lt;br /&gt;&lt;br /&gt;    if (db == NULL) {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, "no database");&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    int option = static_cast&amp;lt;int&amp;gt;(lua_tonumber(L, 2));&lt;br /&gt;    int value = static_cast&amp;lt;int&amp;gt;(lua_tonumber(L, 3));&lt;br /&gt;&lt;br /&gt;    if (db-&amp;gt;gsetopt(option, value)) {&lt;br /&gt;        lua_pushboolean(L, 1);&lt;br /&gt;        return 1;&lt;br /&gt;    } else {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, db-&amp;gt;last_error());&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Outra função um pouco mais complicada é &lt;code&gt;luagdbm_store&lt;/code&gt;, que deve armazenar um par chave-valor.&lt;br /&gt;&lt;br /&gt;A complexidade não está no armazenamento em si, mas na tomada de decisão do tipo da chave, número ou &lt;em&gt;string&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Começamos como as outras funções:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;int luagdbm_store(lua_State *L) {&lt;br /&gt;    GdbmObject *db =&lt;br /&gt;        reinterpret_cast&amp;lt;GdbmObject *&amp;gt;(lua_touserdata(L, 1));&lt;br /&gt;&lt;br /&gt;    if (db == NULL) {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, "no database");&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    const char *key = lua_tostring(L, 2);&lt;br /&gt;    bool resp = false;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Então precisamos decidir se o próximo parâmetro é número ou &lt;em&gt;string&lt;/em&gt; e usar uma variável do tipo conveniente:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    switch (lua_type(L, 3)) {&lt;br /&gt;        case LUA_TSTRING: {&lt;br /&gt;            const char *aux = lua_tostring(L, 3);&lt;br /&gt;            resp = db-&amp;gt;gstore(key, aux);&lt;br /&gt;            break;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        case LUA_TNUMBER: {&lt;br /&gt;            double aux = lua_tonumber(L, 3);&lt;br /&gt;            resp = db-&amp;gt;gstore(key, aux);&lt;br /&gt;            break;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        default:&lt;br /&gt;            lua_pushnil(L);&lt;br /&gt;            lua_pushstring(L, "not compatible data");&lt;br /&gt;            return 2;&lt;br /&gt;    }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Podemos então retornar convenientemente:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    if (resp) {&lt;br /&gt;        lua_pushboolean(L, 1);&lt;br /&gt;        return 1;&lt;br /&gt;&lt;br /&gt;    } else {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, db-&amp;gt;last_error());&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A última função é &lt;code&gt;luagdbm_sync&lt;/code&gt;, que não tem segredos:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;int luagdbm_sync(lua_State *L) {&lt;br /&gt;    GdbmObject *db =&lt;br /&gt;        reinterpret_cast&amp;lt;GdbmObject *&amp;gt;(lua_touserdata(L, 1));&lt;br /&gt;&lt;br /&gt;    if (db == NULL) {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, "no database");&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (db-&amp;gt;gsync()) {&lt;br /&gt;        lua_pushboolean(L, 1);&lt;br /&gt;        return 1;&lt;br /&gt;&lt;br /&gt;    } else {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, db-&amp;gt;last_error());&lt;br /&gt;        return 2;&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Abertura de uma base de dados&lt;/h3&gt;&lt;br /&gt;Finalmente chegamos à função &lt;code&gt;luagdbm_open&lt;/code&gt;!&lt;br /&gt;&lt;br /&gt;Ela é bem complexa, pois pode receber parâmetros diferentes.&lt;br /&gt;&lt;br /&gt;Se o parâmetro for &lt;em&gt;string&lt;/em&gt;, será considerada como o nome do arquivo de base de dados e para todas as demais configurações são usados os valores por defeito.&lt;br /&gt;&lt;br /&gt;Se for uma tabela:&lt;br /&gt;&lt;ul&gt; &lt;li&gt;o valor para a chave &lt;code&gt;name&lt;/code&gt; representará o nome do arquivo;&lt;/li&gt; &lt;li&gt;o valor para a chave &lt;code&gt;block&lt;/code&gt; representará o tamanho do bloco;&lt;/li&gt; &lt;li&gt;o valor para a chave &lt;code&gt;mode&lt;/code&gt; representará o modo de leitura e/ou gravação;&lt;/li&gt; &lt;li&gt;o valor para a chave &lt;code&gt;permission&lt;/code&gt; representará as permissões para a criação do arquivo.&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;No entanto, mais de um parâmetros podem ser passados para o modo, como por exemplo &lt;code&gt;GDBM_WRCREAT&lt;/code&gt; e &lt;code&gt;GDBM_SYNC&lt;/code&gt;. Para esses casos, o valor para a chave &lt;code&gt;mode&lt;/code&gt; deve ser uma tabela indexada contendo os modos desejados &amp;ndash; e a função precisa estar preparada para processar isso!&lt;br /&gt;&lt;br /&gt;A primeira parte da função é carregar os valores por defeito:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;int luagdbm_open(lua_State *L) {&lt;br /&gt;    const char *name = NULL;&lt;br /&gt;    int block = 512;&lt;br /&gt;    int mode = GDBM_READER;&lt;br /&gt;    int perm = 0644;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Então precisamos verificar se o parâmetro é &lt;em&gt;string&lt;/em&gt; (nome do arquivo, tudo mais ajustado por defeito) ou tabela:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    switch(lua_type(L, 1)) {&lt;br /&gt;        case LUA_TSTRING:&lt;br /&gt;            name = lua_tostring(L, 1);&lt;br /&gt;            break;&lt;br /&gt;&lt;br /&gt;        case LUA_TTABLE: {&lt;br /&gt;            lua_getfield(L, 1, "name");&lt;br /&gt;&lt;br /&gt;            if (lua_type(L, -1) == LUA_TSTRING) {&lt;br /&gt;                name = lua_tostring(L, -1);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora precisamos pegar o valor de &lt;code&gt;block&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;                lua_getfield(L, 1, "block");&lt;br /&gt;                if (lua_type(L, -1) == LUA_TNUMBER)&lt;br /&gt;                    block = static_cast&amp;lt;int&amp;gt;(lua_tonumber(L, -1));&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ao trazermos o valor de &lt;code&gt;mode&lt;/code&gt; para cima, precisamos ainda verificar seu tipo:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;                lua_getfield(L, 1, "mode");&lt;br /&gt;                switch (lua_type(L, -1)) {&lt;br /&gt;                    case LUA_TNUMBER:&lt;br /&gt;                        mode = static_cast&amp;lt;int&amp;gt;(lua_tonumber(L, -1));&lt;br /&gt;                        break;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora, caso seja uma tabela, é preciso percorrer seus valores enquantos estes forem números:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;                    case LUA_TTABLE: {&lt;br /&gt;                        int i = 1;&lt;br /&gt;                        lua_rawgeti(L, -1, i);&lt;br /&gt;                        mode = 0;&lt;br /&gt;                        while (lua_type(L, -1) == LUA_TNUMBER) {&lt;br /&gt;                            mode |= static_cast&amp;lt;int&amp;gt;(&lt;br /&gt;                                lua_tonumber(L, -1)&lt;br /&gt;                            );&lt;br /&gt;                            lua_pop(L, 1);&lt;br /&gt;                            lua_rawgeti(L, -1, ++i);&lt;br /&gt;                        }&lt;br /&gt;&lt;br /&gt;                        mode = (mode == 0) ? GDBM_READER : mode;&lt;br /&gt;                        break;&lt;br /&gt;                    }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Repare que &lt;code&gt;lua_rawgeti(L,&amp;nbsp;-1,&amp;nbsp;i)&lt;/code&gt; empilha o &lt;code&gt;i&lt;/code&gt;-ésimo elemento da tabela no fim da pilha (-1) e &lt;code&gt;lua_pop(L,&amp;nbsp;1)&lt;/code&gt; desempilha para voltarmos à tabela.&lt;br /&gt;&lt;br /&gt;Agora, caso não seja nem número, nem tabela, ignora:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;                    default:&lt;br /&gt;                        break;&lt;br /&gt;                }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Obter as permissões é tão simples quanto obter o tamanho do bloco. Aproveitamos e já encerramos o &lt;code&gt;switch&lt;/code&gt; o parâmetro ignorando outros tipos:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;                lua_getfield(L, 1, "permission");&lt;br /&gt;                if (lua_type(L, -1) == LUA_TNUMBER)&lt;br /&gt;                    perm = static_cast&amp;lt;int&amp;gt;(lua_tonumber(L, -1));&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            break;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        default:&lt;br /&gt;            break;&lt;br /&gt;    }&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Repare bem em uma coisa: &lt;code&gt;lua_to*(L,&amp;nbsp;1)&lt;/code&gt; retorna o primeiro parâmetro passado à função, &lt;code&gt;lua_to*(L,&amp;nbsp;2)&lt;/code&gt; retorna o segundo parâmetro. &lt;code&gt;lua_to*(L,&amp;nbsp;-1)&lt;/code&gt; retorna o último elemento empilhado por &lt;code&gt;lua_push*&lt;/code&gt;, &lt;code&gt;lua_getglobal&lt;/code&gt;, &lt;code&gt;lua_getfield&lt;/code&gt;, &lt;code&gt;lua_rawget&lt;/code&gt;, &lt;code&gt;lua_rawgeti&lt;/code&gt; ou qualquer outra função da API que empilhe elementos.&lt;br /&gt;&lt;br /&gt;Agora é preciso verificar se, após todo esse trabalho, o nome do arquivo foi realmente ajustado:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    if (name == NULL) {&lt;br /&gt;        lua_pushnil(L);&lt;br /&gt;        lua_pushstring(L, "file not supplied");&lt;br /&gt;        return 2;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Finalmente podemos abrir o arquivo de banco de dados e, se tudo correr bem, retorná-lo para o estado Lua &amp;ndash; caso contrário, retornar um erro:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    } else {&lt;br /&gt;        GdbmObject *db = new GdbmObject(name, block, mode, perm);&lt;br /&gt;&lt;br /&gt;        if (gdbm_errno == GDBM_NO_ERROR) {&lt;br /&gt;            if (db == NULL) {&lt;br /&gt;                lua_pushnil(L);&lt;br /&gt;                lua_pushstring(L,&lt;br /&gt;                    "no error, but no database returned"&lt;br /&gt;                );&lt;br /&gt;                return 2;&lt;br /&gt;&lt;br /&gt;            } else {&lt;br /&gt;                pushdb(L, db);&lt;br /&gt;                return 1;&lt;br /&gt;            }&lt;br /&gt;        } else {&lt;br /&gt;            delete db;&lt;br /&gt;            lua_pushnil(L);&lt;br /&gt;            lua_pushstring(L, gdbm_strerror(gdbm_errno));&lt;br /&gt;            return 2;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Informações&lt;/h3&gt;&lt;br /&gt;A função &lt;code&gt;set_info&lt;/code&gt; é na verdade a mais chata: primeiro ajusta dados padrão sobre o módulo, depois carrega as constantes usadas pelo GDBM com nomes similares.&lt;br /&gt;&lt;br /&gt;É bastante extenso e se não quiser, não precisa ler agora. Está aqui apenas para quem quiser programá-lo.&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;void set_info(lua_State *L) {&lt;br /&gt;    lua_pushliteral(L, "_COPYRIGHT");&lt;br /&gt;    lua_pushliteral(L, "Copyright (C) 2008 Rodrigo Cacilhas");&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "_DESCRIPTION");&lt;br /&gt;    lua_pushliteral(L, "GDBM interface");&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "_NAME");&lt;br /&gt;    lua_pushliteral(L, MODULE);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "_VERSION");&lt;br /&gt;    lua_pushliteral(L, VERSION);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;&lt;br /&gt;    lua_pushliteral(L, "READER");&lt;br /&gt;    lua_pushnumber(L, GDBM_READER);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "WRITER");&lt;br /&gt;    lua_pushnumber(L, GDBM_WRITER);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "WRCREAT");&lt;br /&gt;    lua_pushnumber(L, GDBM_WRCREAT);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "NEWDB");&lt;br /&gt;    lua_pushnumber(L, GDBM_NEWDB);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "FAST");&lt;br /&gt;    lua_pushnumber(L, GDBM_FAST);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "SYNC");&lt;br /&gt;    lua_pushnumber(L, GDBM_SYNC);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "NOLOCK");&lt;br /&gt;    lua_pushnumber(L, GDBM_NOLOCK);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;&lt;br /&gt;    lua_pushliteral(L, "INSERT");&lt;br /&gt;    lua_pushnumber(L, GDBM_INSERT);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "REPLACE");&lt;br /&gt;    lua_pushnumber(L, GDBM_REPLACE);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    lua_pushliteral(L, "CACHESIZE");&lt;br /&gt;    lua_pushnumber(L, GDBM_CACHESIZE);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "FASTMODE");&lt;br /&gt;    lua_pushnumber(L, GDBM_FASTMODE);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "SYNCMODE");&lt;br /&gt;    lua_pushnumber(L, GDBM_SYNCMODE);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "CENTFREE");&lt;br /&gt;    lua_pushnumber(L, GDBM_CENTFREE);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "COALESCEBLKS");&lt;br /&gt;    lua_pushnumber(L, GDBM_COALESCEBLKS);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    lua_pushliteral(L, "NO_ERROR");&lt;br /&gt;    lua_pushnumber(L, GDBM_NO_ERROR);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "MALLOC_ERROR");&lt;br /&gt;    lua_pushnumber(L, GDBM_MALLOC_ERROR);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "BLOCK_SIZE_ERROR");&lt;br /&gt;    lua_pushnumber(L, GDBM_BLOCK_SIZE_ERROR);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "FILE_OPEN_ERROR");&lt;br /&gt;    lua_pushnumber(L, GDBM_FILE_OPEN_ERROR);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "FILE_WRITE_ERROR");&lt;br /&gt;    lua_pushnumber(L, GDBM_FILE_WRITE_ERROR);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "FILE_SEEK_ERROR");&lt;br /&gt;    lua_pushnumber(L, GDBM_FILE_SEEK_ERROR);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "FILE_READ_ERROR");&lt;br /&gt;    lua_pushnumber(L, GDBM_FILE_READ_ERROR);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "BAD_MAGIC_NUMBER");&lt;br /&gt;    lua_pushnumber(L, GDBM_BAD_MAGIC_NUMBER);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "EMPTY_DATABASE");&lt;br /&gt;    lua_pushnumber(L, GDBM_EMPTY_DATABASE);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "CANT_BE_READER");&lt;br /&gt;    lua_pushnumber(L, GDBM_CANT_BE_READER);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "CANT_BE_WRITER");&lt;br /&gt;    lua_pushnumber(L, GDBM_CANT_BE_WRITER);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "READER_CANT_DELETE");&lt;br /&gt;    lua_pushnumber(L, GDBM_READER_CANT_DELETE);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "READER_CANT_STORE");&lt;br /&gt;    lua_pushnumber(L, GDBM_READER_CANT_STORE);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "READER_CANT_REORGANIZE");&lt;br /&gt;    lua_pushnumber(L, GDBM_READER_CANT_REORGANIZE);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "UNKNOWN_UPDATE");&lt;br /&gt;    lua_pushnumber(L, GDBM_UNKNOWN_UPDATE);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "ITEM_NOT_FOUND");&lt;br /&gt;    lua_pushnumber(L, GDBM_ITEM_NOT_FOUND);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "REORGANIZE_FAILED");&lt;br /&gt;    lua_pushnumber(L, GDBM_REORGANIZE_FAILED);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "CANNOT_REPLACE");&lt;br /&gt;    lua_pushnumber(L, GDBM_CANNOT_REPLACE);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "ILLEGAL_DATA");&lt;br /&gt;    lua_pushnumber(L, GDBM_ILLEGAL_DATA);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "OPT_ALREADY_SET");&lt;br /&gt;    lua_pushnumber(L, GDBM_OPT_ALREADY_SET);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;    lua_pushliteral(L, "OPT_ILLEGAL");&lt;br /&gt;    lua_pushnumber(L, GDBM_OPT_ILLEGAL);&lt;br /&gt;    lua_settable(L, -3);&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Compilando&lt;/h3&gt;&lt;br /&gt;Uma forma legal de compilar é através de um arquivo &lt;code&gt;Makefile&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Esse arquivo começa com um comentário informando data e seu criador, e logo em seguida os recursos usados: compilador (&lt;code&gt;CC&lt;/code&gt;), &lt;em&gt;link&lt;/em&gt;-editor (&lt;code&gt;LD&lt;/code&gt;), &lt;em&gt;flags&lt;/em&gt; de compilação (&lt;code&gt;CFLAGS&lt;/code&gt;) e bibliotecas envolvidas (&lt;code&gt;LIBS&lt;/code&gt;), no caso:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;# $Id: luagdbm,v 1.0 2008/10/16 23:25:31 cacilhas Exp $&lt;br /&gt;&lt;br /&gt;CC ?= c++&lt;br /&gt;LD ?= c++&lt;br /&gt;RM ?= rm -f&lt;br /&gt;&lt;br /&gt;CFLAGS ?= &lt;br /&gt;LIBS ?= -lm -llua -lgdbm -lstdc++&lt;br /&gt;&lt;br /&gt;# **********************************************************************&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Então os procedimentos de compilação.&lt;br /&gt;&lt;br /&gt;O procedimento para compilar os arquivos fontes (&lt;code&gt;*.cc&lt;/code&gt;) em objetos (&lt;code&gt;*.o&lt;/code&gt;) é:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;.cc.o:&lt;br /&gt;    $(CC) -c $&amp;lt; $(CFLAGS) -o $@&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Finalmente fazemos a &lt;em&gt;link&lt;/em&gt;-edição de tudo na biblioteca compartilhada &lt;code&gt;gdbm.so&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;gdbm.so: gdbmobj.o luagdbm.o&lt;br /&gt;    $(LD) -shared $? ($LIBS) -o $@&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora precisamos informar ao &lt;em&gt;make&lt;/em&gt; o que fazer por defeito:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;all: gdbm.so&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E como limpar a bagunça:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;clean:&lt;br /&gt;    $(RM) luagdbm.o&lt;br /&gt;    $(RM) gdbmobj.o&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Feito isso já podemos compilar:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; make&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Se tudo correu bem, a biblioteca &lt;code&gt;gdbm.so&lt;/code&gt; terá sido gerada, se não, verifique os erros e volte corrigindo-os. Caso encontre algum erro neste artigo, por favor informe para que eu possa corrigi-lo!&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Fazendo funcionar&lt;/h3&gt;&lt;br /&gt;Agora mova a biblioteca para um diretório onde Lua possa encontrá-la. Aqui para mim é &lt;code&gt;/usr/lib/lua/5.1/&lt;/code&gt;, mas aí para você pode ser qualquer coisa. O conteúdo da variável de ambiente &lt;code&gt;LUA_CPATH&lt;/code&gt; pode dar uma dica.&lt;br /&gt;&lt;br /&gt;Na ausência dessa variável, entrando no interpretador Lua, a chave &lt;code&gt;package.cpath&lt;/code&gt; informa o local correto.&lt;br /&gt;&lt;br /&gt;Feito isso, podemos iniciar um interpretador Lua e fazer testes:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; lua&lt;br /&gt;&lt;em&gt;Lua 5.1.3  Copyright (C) 1994-2008 Lua.org, PUC-Rio&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; require "gdbm"&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; db = assert(gdbm.open { name = "dbtest.db", mode = gdbm.WRCREAT })&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; db:store("first", "a")&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; db:store("second", "b")&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; db:store("thirt", "c")&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; db:close()&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Saindo do interpretador, você poderá ver o arquivo &lt;code&gt;dbtest.db&lt;/code&gt; criado. Vamos reler seu conteúdo:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; db = assert(gdbm.open "dbtest.db")&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; k = db:next()&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; while k do print(k, db:fetch_string(k)) k = db:next(k) end&lt;br /&gt;&lt;em&gt;first   a&lt;/em&gt;&lt;br /&gt;&lt;em&gt;second  b&lt;/em&gt;&lt;br /&gt;&lt;em&gt;thirt   c&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&amp;gt;&lt;/em&gt; db:close()&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A ordem de &lt;code&gt;gdbm_next&lt;/code&gt; não é necessariamente a ordem de registro.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conclusão&lt;/h3&gt;&lt;br /&gt;Acho que este artigo está cheio de informações e é bastante longo, mas se você conseguiu lê-lo até aqui, significa que consegui fazê-lo útil.&lt;br /&gt;&lt;br /&gt;Para saber mais, leia a &lt;em&gt;manpage&lt;/em&gt; de &lt;code&gt;gdbm&lt;/code&gt; e o &lt;a href="http://www.lua.org/pil/"&gt;PiL&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;tt&gt;[update 2008-10-23]&lt;/tt&gt;Valeu pela divulgação no &lt;a href="http://br-linux.org/2008/kodumaro-portando-o-gdbm-para-lua/"&gt;BR-Linux.org&lt;/a&gt;, Augusto!&lt;tt&gt;[/update]&lt;/tt&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-1735364715635785801?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/1735364715635785801/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=1735364715635785801' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/1735364715635785801'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/1735364715635785801'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2008/10/portando-gdbm-para-lua.html' title='Portando GDBM para Lua'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-6765803184619517544</id><published>2008-10-15T21:08:00.002-03:00</published><updated>2008-10-15T21:15:04.848-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tcl'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><title type='text'>Tcl/Tk</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left;" src="http://photos1.blogger.com/blogger/6505/3295/200/tcl.jpg" alt="tcl.jpg" /&gt; Uma linguagem de &lt;em&gt;script&lt;/em&gt; muito subestimada é &lt;a href="http://wiki.tcl.tk/"&gt;Tcl/Tk&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Tcl significa &lt;em&gt;Tool Command Language&lt;/em&gt; e foi criada por &lt;a href="http://pt.wikipedia.org/wiki/John_Ousterhout"&gt;John Ousterhout&lt;/a&gt; para ser uma extensão de C, uma linguagem de agregação de componentes, mais ou menos como o &lt;a href="http://pt.wikipedia.org/wiki/Shell_script"&gt;Shell Script&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Tk é uma extensão gráfica para Tcl escrita em C. É um acrónimo para &lt;em&gt;toolkit&lt;/em&gt;, nome comumente usado para &lt;em&gt;frameworks&lt;/em&gt; gráficos. Em cada plataforma operacional, Tk oferece uma interface homogénia com o sistema de janelas. Outras linguagens também pode acessar a biblioteca Tk &amp;ndash; como por exemplo &lt;a href="http://wiki.python.org/moin/TkInter"&gt;Tkinter&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Tcl e Tk são de código aberto.&lt;br /&gt;&lt;br /&gt;Vamos a alguns exemplos:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; tclsh&lt;br /&gt;&lt;em&gt;%&lt;/em&gt; puts stdout {Olá Mundo!}&lt;br /&gt;&lt;em&gt;Olá Mundo!&lt;/em&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Uma característica fortíssima de Tcl/Tk é que &lt;strong&gt;tudo são &lt;em&gt;strings&lt;/em&gt;&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;Cada &lt;em&gt;token&lt;/em&gt; é uma &lt;em&gt;string&lt;/em&gt; e &lt;em&gt;strings&lt;/em&gt; não precisam de delimitadores, mas aspas (&lt;code&gt;"&lt;/code&gt;) e chaves (&lt;code&gt;{&lt;/code&gt; e &lt;code&gt;}&lt;/code&gt;) podem ser usados como.&lt;br /&gt;&lt;br /&gt;No exemplo acima, &lt;code&gt;puts&lt;/code&gt;, &lt;code&gt;stdout&lt;/code&gt; e &lt;code&gt;{Olá&amp;nbsp;Mundo!}&lt;/code&gt; são &lt;em&gt;strings&lt;/em&gt;. A primeira &lt;em&gt;string&lt;/em&gt; da linha referencia o comando a ser executado, no caso &lt;code&gt;puts&lt;/code&gt; «coloca» uma &lt;em&gt;string&lt;/em&gt; em um fluxo (&lt;em&gt;stream&lt;/em&gt;).&lt;br /&gt;&lt;br /&gt;A segunda &lt;em&gt;string&lt;/em&gt; (&lt;code&gt;stdout&lt;/code&gt;) indica qual o fluxo de saída, no caso a saída padrão.&lt;br /&gt;&lt;br /&gt;A terceira &lt;em&gt;string&lt;/em&gt; é aquela que será direcionada para a saída selecionada. No caso exibe &lt;code&gt;Olá Mundo!&lt;/code&gt; na saída padrão.&lt;br /&gt;&lt;br /&gt;Vamos a um exemplo um pouco mais complicado:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;puts -nonewline stdout {Informe um número: }&lt;br /&gt;gets stdin num&lt;br /&gt;set dob [expr [set num] * 2]&lt;br /&gt;puts stdout "O dobro é [set dob]"&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Como já vimos, &lt;code&gt;puts&lt;/code&gt; exibe uma &lt;em&gt;string&lt;/em&gt; em uma saída, no caso novamente na saída padrão (&lt;code&gt;stdout&lt;/code&gt;). A &lt;em&gt;string&lt;/em&gt; &lt;code&gt;-nonewline&lt;/code&gt; é um parâmetro que indica a &lt;code&gt;puts&lt;/code&gt; para não inserir mudança de linha ao final.&lt;br /&gt;&lt;br /&gt;O comando &lt;code&gt;gets&lt;/code&gt; recebe uma &lt;em&gt;string&lt;/em&gt; de uma entrada &amp;ndash; no caso &lt;code&gt;stdin&lt;/code&gt;, entrada padrão: o teclado &amp;ndash; e a atribui a uma variável referenciada pela última &lt;em&gt;string&lt;/em&gt;, &lt;code&gt;num&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;O comando &lt;code&gt;set&lt;/code&gt; retorna o conteúdo de uma variável, se receber uma terceira &lt;em&gt;string&lt;/em&gt;, atribui esta à variável e retorna.&lt;br /&gt;&lt;br /&gt;Os colchetes executam o comando interno e tudo é substituído pela &lt;em&gt;string&lt;/em&gt; retornada.&lt;br /&gt;&lt;br /&gt;O comando &lt;code&gt;expr&lt;/code&gt; trata todas as &lt;em&gt;strings&lt;/em&gt; como uma expressão matemática, retornando o resultado.&lt;br /&gt;&lt;br /&gt;Assim, &lt;code&gt;[set&amp;nbsp;num]&lt;/code&gt; retorna o valor da variável &lt;code&gt;num&lt;/code&gt;, o &lt;code&gt;expr&lt;/code&gt; pega esse valor de &lt;code&gt;num&lt;/code&gt;, tratado como um número, e múltiplica por dois (2), retornando.&lt;br /&gt;&lt;br /&gt;Daí os colchetes substituem novamente toda a expressão pelo valor retornado, ou seja, uma &lt;em&gt;string&lt;/em&gt; representando o dobro do valor de &lt;code&gt;num&lt;/code&gt;, então o &lt;code&gt;set&lt;/code&gt; mais externo atribui essa valor à variável &lt;code&gt;dob&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;No final o último comando exibe na saída padrão a &lt;em&gt;string&lt;/em&gt;, substituindo o que estiver entre colchetes. Como &lt;code&gt;set&amp;nbsp;dob&lt;/code&gt; retorna o valor de &lt;code&gt;dob&lt;/code&gt;, acho que é óbvio o que é exibido.&lt;br /&gt;&lt;br /&gt;Só que Tcl/Tk suporta um «apelido» para &lt;code&gt;set&lt;/code&gt;, que é o cifrão (&lt;code&gt;$&lt;/code&gt;), como em Shell e &lt;a href="http://perl.com/"&gt;Perl&lt;/a&gt; (não como em PHP):&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;puts -nonewline stdout {Informe um número: }&lt;br /&gt;gets stdin num&lt;br /&gt;set dob [expr $num * 2]&lt;br /&gt;puts stdout "O dobro é $dob"&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Isso deixa o código bem mais limpo. =)&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Outras extensões&lt;/h3&gt;&lt;br /&gt;Há ainda outras linguagens baseadas em Tcl/Tk que valem a pena serem citadas.&lt;br /&gt;&lt;br /&gt;A primeira é &lt;a href="http://incrtcl.sourceforge.net/itcl/"&gt;&lt;code&gt;[incr Tcl]&lt;/code&gt;&lt;/a&gt;, uma variação orientada a objetos.&lt;br /&gt;&lt;br /&gt;Outra é &lt;a href="http://sourceforge.net/projects/tclx"&gt;TclX&lt;/a&gt; (Tcl estendido), que, além de suportar todas os recursos de Tcl/Tk ainda suporta outros similares ao &lt;a href="http://pt.wikipedia.org/wiki/Bash"&gt;bash&lt;/a&gt;, como &lt;code&gt;echo&lt;/code&gt;, &lt;code&gt;loop&lt;/code&gt; e &lt;code&gt;&amp;amp;&lt;/code&gt; (para execução paralela).&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Finalizando&lt;/h3&gt;&lt;br /&gt;Este artigo é apenas um esboço. Outro mais completo pode ser encontrado nas &lt;a href="http://montegasppa.blogspot.com/2006/10/tcltk.html"&gt;Reflexões de Monte Gasppa e Giulia C.&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-6765803184619517544?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/6765803184619517544/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=6765803184619517544' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/6765803184619517544'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/6765803184619517544'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2008/10/tcltk.html' title='Tcl/Tk'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-5700841585524781840</id><published>2008-09-24T17:32:00.004-03:00</published><updated>2008-10-04T10:29:14.193-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>HTML Unescape em Python</title><content type='html'>Toda linguagem tem seus pontos altos e baixos, e suas próprias idiossincracias. Ontem eu esbarrei em algo interessante com relação a biblioteca padrão do Python.&lt;br /&gt;&lt;br /&gt;Eu precisava de uma função que fosse mais ou menos equivalente ao &lt;a class="http reference external" href="http://www.php.net/html_entity_decode"&gt;&lt;code&gt;html_entity_decode&lt;/code&gt;&lt;/a&gt; do PHP.&lt;br /&gt;&lt;br /&gt;Eu estava usando a biblioteca &lt;a class="http reference external" href="http://docs.pylonshq.com/thirdparty/webhelpers/html/html.html"&gt;&lt;code&gt;webhelpers&lt;/code&gt;&lt;/a&gt;, que tem uma função &lt;code&gt;escape&lt;/code&gt;, mas cadê a &lt;code&gt;unescape&lt;/code&gt;? Olhando o código, descubro que a &lt;code&gt;webhelpers&lt;/code&gt; usa uma função definida em &lt;code&gt;webhelpers.utils&lt;/code&gt;, chamada &lt;code&gt;cgi_escape&lt;/code&gt;, que seria uma implementação melhor de cgi.escape.&lt;br /&gt;&lt;br /&gt;Minhas esperanças então se concentratam no &lt;a class="http reference external" href="http://docs.python.org/lib/module-cgi.html"&gt;módulo &lt;code&gt;cgi&lt;/code&gt;&lt;/a&gt;. Mas uma olhada mais atenta me frustrou de novo: temos &lt;code&gt;escape&lt;/code&gt;, mas não &lt;code&gt;unescape&lt;/code&gt;. Até que um comentário num &lt;a class="http reference external" href="http://codare.net/2006/09/17/python-escapar-caracteres-especiais-em-html-entities/"&gt;&lt;em&gt;post&lt;/em&gt; do codare&lt;/a&gt; que, vejam só a ironia, mostrava como implementar um &lt;code&gt;escape&lt;/code&gt;, me trouxe a solução: &lt;code&gt;xml.sax.saxutils.unescape&lt;/code&gt; (e sua par, &lt;code&gt;xml.sax.saxutils.escape&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;Sei que teria sido muito fácil implementar uma função assim eu mesmo &amp;ndash; até mesmo trivial. O ponto é que algo que eu considerava intuitivo e esperava encontrar naquele lugar, se mostrou muito mais difícil de achar do que minha intuição supôs. E eu não gosto de ter minha intuição enganada.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-5700841585524781840?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/5700841585524781840/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=5700841585524781840' title='5 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5700841585524781840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5700841585524781840'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2008/09/html-unescape-em-python.html' title='HTML Unescape em Python'/><author><name>Walter Cruz</name><uri>http://www.blogger.com/profile/10836863572075307104</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://bp3.blogger.com/_QrHWeNioH_k/R49C4RsNH6I/AAAAAAAAACc/iaDJgilsVjk/S220/Bodao.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-2221675061179082117</id><published>2008-07-12T18:55:00.006-03:00</published><updated>2008-08-08T14:11:27.377-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Math'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Regressão linear</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://photos1.blogger.com/blogger/6505/3295/200/python.png" alt="" /&gt; Em meu trabalho ora me envolvo em projetos de &lt;em&gt;frontend&lt;/em&gt; &amp;ndash; aplicações &lt;em&gt;web&lt;/em&gt; &amp;ndash;, ora me envolvo em projetos de &lt;em&gt;backend&lt;/em&gt;. Ora trabalho em projetos de uma frente a outra.&lt;br /&gt;&lt;br /&gt;No entanto sou fascinado por problemas conceituais e soluções matemáticas, portanto gosto muito mais de &lt;em&gt;backend&lt;/em&gt; do que de &lt;em&gt;frontend&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Em problemas conceituais, uma coisa magnífica é poder prever estados de um sistema por meio de regressão.&lt;br /&gt;&lt;br /&gt;Há alguns tipos de regressão: regressão linear, regressão por potência, regressão logarítmica e regressão exponencial, mas todas podem ser reduzidas à regressão linear.&lt;br /&gt;&lt;br /&gt;A função da regressão linear é simples:&lt;br /&gt;&lt;img style="border: none; text-align: center; cursor: crosshair;" src="http://cacilhas.info/bin/mimetex.cgi?%5Chat%7By_i%7D=%5calpha%20+%20%5Cbeta%20x_i" alt="&amp;ycirc;=&amp;alpha; + &amp;beta;x" /&gt;&lt;br /&gt;&lt;br /&gt;Ou seja, a ordenada estimada é igual à intercepção (&amp;alpha;) mais a inclinação (&amp;beta;) vezes a abscissa. O problema real é calcular &amp;alpha; e &amp;beta;.&lt;br /&gt;&lt;br /&gt;Há muitas e muitas formas de calcular esses, umas mais simples, outras mais interessantes. =)&lt;br /&gt;&lt;br /&gt;Uma forma legal é usando o produto de uma matriz quadrada pelo vetor de coeficientes.&lt;br /&gt;&lt;img style="border: none; text-align: center; cursor: crosshair;" src="http://cacilhas.info/bin/mimetex.cgi?%5Cleft%28%5Cbegin%7Barray%7D%7Bcc%7Dn%26%5Csum_%7Bi=0%7D%5E%7Bn-1%7D%7Bx_i%7D%5C%5C%5Csum_%7Bi=0%7D%5E%7Bn-1%7D%7Bx_i%7D%26%5Csum_%7Bi=0%7D%5E%7Bn-1%7D%7Bx_i%5E2%7D%5Cend%7Barray%7D%5Cright%29%5Cleft%28%5Cbegin%7Barray%7D%7Bc%7D%5Calpha%5C%5C%5Cbeta%5Cend%7Barray%7D%5Cright%29=%5Cleft%28%5Cbegin%7Barray%7D%7Bc%7D%5Csum_%7Bi=0%7D%5E%7Bn-1%7D%7By_i%7D%5C%5C%5Csum_%7Bi=0%7D%5E%7Bn-1%7D%7Bx_iy_i%7D%5Cend%7Barray%7D%5Cright%29" alt="--" /&gt;&lt;br /&gt;&lt;br /&gt;Assim sendo, o primeiro procedimento deve ser montar as matrizes. Hoje vamos trabalhar com &lt;a href="http://python.org/"&gt;Python&lt;/a&gt;.&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;from __future__ import division&lt;br /&gt;__metaclass__ = type&lt;br /&gt;&lt;br /&gt;class LinearRegression:&lt;br /&gt;    def __init__(self, pointset):&lt;br /&gt;        # pointset deve ser uma lista de pares x, y&lt;br /&gt;        self.__set = pointset&lt;br /&gt;&lt;br /&gt;        self.__createMatrices()&lt;br /&gt;        self.__calculateAlpha()&lt;br /&gt;        self.__calculateBeta()&lt;br /&gt;&lt;br /&gt;    def __createMatrices(self):&lt;br /&gt;        s = self.__set&lt;br /&gt;&lt;br /&gt;        m11 = len(s)&lt;br /&gt;        m21 = sum([e[0] for e in s])&lt;br /&gt;        m12 = m21&lt;br /&gt;        m22 = sum([e[0] ** 2 for e in s])&lt;br /&gt;&lt;br /&gt;        self.__m = [m11, m21, m12, m22]&lt;br /&gt;&lt;br /&gt;        self.__rvector = [&lt;br /&gt;            sum([e[1] for e in s]),&lt;br /&gt;            sum ([e[0] * e[1] for e in s])&lt;br /&gt;        ]&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora é preciso resolver o produto de matriz por vetor. Podemos traduzir isso por meio de determinantes:&lt;br /&gt;&lt;img style="border: none; text-align: center; cursor: crosshair;" src="http://cacilhas.info/bin/mimetex.cgi?v_0=%5Cfrac%7B%5Cleft%7C%5Cbegin%7Barray%7D%7Bcc%7Dr_0%26a_%7B12%7D%5C%5Cr_1%26a_%7B22%7D%5Cend%7Barray%7D%5Cright%7C%7D%7B%5Cleft%7C%5Cbegin%7Barray%7D%7Bcc%7Da_%7B11%7D%26a_%7B12%7D%5C%5Ca_%7B21%7D%26a_%7B22%7D%5Cend%7Barray%7D%5Cright%7C%7D" alt="--" /&gt;&lt;br /&gt;&lt;br /&gt;Daí:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    def __calculateAlpha(self):&lt;br /&gt;        r = self.__rvector&lt;br /&gt;        m = self.__m&lt;br /&gt;&lt;br /&gt;        num = r[0] * m[3] - r[1] * m[2]&lt;br /&gt;        den = m[0] * m[3] - m[1] * m[2]&lt;br /&gt;&lt;br /&gt;        self.__alpha = num / den&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Também é possível calcular &amp;beta; através de determinantes:&lt;br /&gt;&lt;img style="border: none; text-align: center; cursor: crosshair;" src="http://cacilhas.info/bin/mimetex.cgi?v_1=%5Cfrac%7B%5Cleft%7C%5Cbegin%7Barray%7D%7Bcc%7Da_%7B11%7D%26r_0%5C%5Ca_%7B21%7D%26r_1%5Cend%7Barray%7D%5Cright%7C%7D%7B%5Cleft%7C%5Cbegin%7Barray%7D%7Bcc%7Da_%7B11%7D%26a_%7B12%7D%5C%5Ca_%7B21%7D%26a_%7B22%7D%5Cend%7Barray%7D%5Cright%7C%7D" alt="--" /&gt;&lt;br /&gt;&lt;br /&gt;Daí:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    def __calculateBeta(self):&lt;br /&gt;        r = self.__rvector&lt;br /&gt;        m = self.__m&lt;br /&gt;&lt;br /&gt;        num = m[0] * r[1] - m[1] * r[0]&lt;br /&gt;        den = m[0] * m[3] - m[1] * m[2]&lt;br /&gt;&lt;br /&gt;        self.__beta = num / den&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Falta somente agora o método para prever um estado estrapolado:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;    def predict(self, x):&lt;br /&gt;        return self.__alpha + (self.__beta * x)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Esta mesma lógica pode ser implementada em outras linguagens. Há ainda outros algoritmos mais simples para calcular regressão linear, mas o apresentado é o mais didático.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-2221675061179082117?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/2221675061179082117/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=2221675061179082117' title='10 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/2221675061179082117'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/2221675061179082117'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2008/07/regressao-linear.html' title='Regressão linear'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-810023189142853509</id><published>2008-06-29T13:48:00.003-03:00</published><updated>2008-06-30T10:32:20.798-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='OO'/><title type='text'>Embaralhando palavras</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://3.bp.blogspot.com/_rGfO7DAuOSE/SByvpfxLTOI/AAAAAAAAAFQ/nea8UWGDh5A/s200/squeak.jpg" alt="Squeak" /&gt; Outro dia o &lt;a href="http://waltercruz.com/"&gt;Walter&lt;/a&gt; estava falando sobre um comportamento irregular da implementação de &lt;a href="http://www.opengroup.org/onlinepubs/007908799/xbd/re.html"&gt;expressões regulares&lt;/a&gt; em &lt;a href="http://python.org"&gt;Python&lt;/a&gt;, especificamente o &lt;em&gt;token&lt;/em&gt; &lt;code&gt;&amp;#92;b&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Havia uma &lt;a href="http://www.rubyquiz.com/quiz76.html"&gt;brincadeira&lt;/a&gt; em &lt;a href="http://www.ruby-lang.org/"&gt;Ruby&lt;/a&gt; com &lt;em&gt;regex&lt;/em&gt; que seleciona cada palavra em uma frase e embaralha a ordem das letras, mantendo a primeira e a última em seus lugares.&lt;br /&gt;&lt;br /&gt;Para separar as palavras e os elementos de espaçamento entre elas, usava-se uma &lt;em&gt;regex&lt;/em&gt; com &lt;code&gt;&amp;#92;b&lt;/code&gt;. Resolvi fazer a brincadeira em &lt;a href="http://smalltalk.org/"&gt;Smalltalk&lt;/a&gt;, mas descobri que o &lt;em&gt;token&lt;/em&gt; também não funciona, portanto precisei fazer uma expressão que representasse cada bloco: &lt;code&gt;((&amp;#92;w+)|(&amp;#92;W+))&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Para reproduzir essa brincadeira, usando &lt;a href="http://squeak.org/"&gt;Squeak&lt;/a&gt;, primeiro usando o System Browser crie um método &lt;code&gt;shaked&lt;/code&gt; na categoria &lt;code&gt;copying&lt;/code&gt; da classe &lt;code&gt;String&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;shaked&lt;br /&gt;    | aux fst i lst temp |&lt;br /&gt;&lt;br /&gt;    (self size &amp;lt;= 3) ifTrue: [ &amp;uarr; self copy ].&lt;br /&gt;&lt;br /&gt;    fst := (self byteAt: 1) asCharacter asString.&lt;br /&gt;    lst := (self byteAt: self size) asCharacter asString.&lt;br /&gt;    aux := self copyFrom: 2 to: self size - 1.&lt;br /&gt;    temp := Array new: aux size factorial.&lt;br /&gt;&lt;br /&gt;    i := 0.&lt;br /&gt;    aux permutationsDo: [ :s |&lt;br /&gt;        i := i + 1.&lt;br /&gt;        temp at: i put: (fst, s, lst).&lt;br /&gt;    ].&lt;br /&gt;&lt;br /&gt;    &amp;uarr; temp at: temp size atRandom.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora, em um &lt;em&gt;workspace&lt;/em&gt;, execute o seguinte código:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;| phr |&lt;br /&gt;&lt;br /&gt;" Esta é a frase a ser embaralhada "&lt;br /&gt;phr := 'Kodumaro: as sombras da programação'.&lt;br /&gt;&lt;br /&gt;Transcript open.&lt;br /&gt;phr regex: '((&amp;#92;w+)|(&amp;#92;W+))' matchesDo: [ :s |&lt;br /&gt;    Transcript show: s shaked.&lt;br /&gt;].&lt;br /&gt;&lt;br /&gt;Transcript cr.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Selecione tudo (&lt;tt&gt;M-a&lt;/tt&gt;) e execute (&lt;tt&gt;M-d&lt;/tt&gt;).&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-810023189142853509?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/810023189142853509/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=810023189142853509' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/810023189142853509'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/810023189142853509'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2008/06/embaralhando-palavras.html' title='Embaralhando palavras'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_rGfO7DAuOSE/SByvpfxLTOI/AAAAAAAAAFQ/nea8UWGDh5A/s72-c/squeak.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-1245036921709216203</id><published>2008-06-11T23:50:00.015-03:00</published><updated>2009-01-10T07:24:00.723-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='Math'/><category scheme='http://www.blogger.com/atom/ns#' term='Smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><category scheme='http://www.blogger.com/atom/ns#' term='Lisp'/><title type='text'>Cálculos estatísticos: polinómio de Lagrange</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://4.bp.blogspot.com/_rGfO7DAuOSE/Rgv00nwEXZI/AAAAAAAAAB8/r59qEVD0qOE/s200/haskell.jpg" alt="Paradigma funcional" /&gt; Dando sequência aos artigos sobre &lt;a href="http://pt.wikipedia.org/wiki/Estatística"&gt;cálculos estatísticos&lt;/a&gt; no &lt;a href="http://kodumaro.blogspot.com/"&gt;Kodumaro&lt;/a&gt; &amp;ndash; e em outros &lt;em&gt;blogs&lt;/em&gt; amigos &amp;ndash;, tive a ideia de falar sobre &lt;a href="http://pt.wikipedia.org/wiki/Interpolação_polinomial"&gt;interpolação polinomial&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Por ser um método simples, decidi usar o &lt;a href="http://pt.wikipedia.org/wiki/Polinómio_de_Lagrange"&gt;polinómio de Lagrange&lt;/a&gt;:&lt;br /&gt;&lt;img style="border: none; text-align: center; cursor: crosshair;" src="http://cacilhas.info/bin/mimetex.cgi?y=\sum_{i=0}^{n-1}\Big(y_i\prod_{j=0\\j\neq%20i}^{n-1}\frac{x-x_j}{x_i-x_j}\Big)" alt="y=\sum_{i=0}^{n-1}\Big(y_i\prod_{j=0\\j\neq i}^{n-1}\frac{x-x_j}{x_i-x_j}\Big)" /&gt;&lt;br /&gt;&lt;br /&gt;Não é preciso calcular os coeficientes &amp;ndash; é possível simplificar o cálculo final transformando parte do polinómio em um vetor de coeficientes, mas é mais fácil de visualizar sem fazê-lo.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;C++&lt;/h3&gt;&lt;br /&gt;Dessa vez não vou usar &lt;a href="http://pt.wikipedia.org/wiki/C_(linguagem_de_programação)"&gt;C&lt;/a&gt;, mas &lt;a href="http://www.cplusplus.com/"&gt;C++&lt;/a&gt;, para poder usar recursos de &lt;a href="http://pt.wikipedia.org/wiki/Orientação_a_objetos"&gt;orientação a objetos&lt;/a&gt;, como &lt;a href="http://pt.wikipedia.org/wiki/Encapsulamento"&gt;encapsulamento&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Primeiro vamos criar um &lt;code&gt;namespace kodumaro&lt;/code&gt; e uma classe &lt;code&gt;Lagrange&lt;/code&gt;. Abra o arquivo &lt;code&gt;lagrange.h&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#ifndef LAGRANGE_H_&lt;br /&gt;#define LAGRANGE_H_&lt;br /&gt;&lt;br /&gt;namespace kodumaro {&lt;br /&gt;    class Lagrange {&lt;br /&gt;        public:&lt;br /&gt;            Lagrange(const double *, const double *, int);&lt;br /&gt;            ~Lagrange() {}&lt;br /&gt;&lt;br /&gt;            double getY(double);&lt;br /&gt;&lt;br /&gt;        private:&lt;br /&gt;            const double *vector_x;&lt;br /&gt;            const double *vector_y;&lt;br /&gt;            int           length;&lt;br /&gt;    };&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;#endif /*LAGRANGE_H_*/&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;O construtor irá receber um vetor de abscissas, um vetor de ordenadas e o tamanho dos vetores. Esses vetores representarão as coordenadas dos pontos a serem interpolados.&lt;br /&gt;&lt;br /&gt;O método &lt;code&gt;getY()&lt;/code&gt; retornará a ordenada para uma determinada abscissa, de acordo com a interpolação de Lagrange.&lt;br /&gt;&lt;br /&gt;Agora o arquivo &lt;code&gt;lagrange.cc&lt;/code&gt; contendo a implementação dos métodos:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;#include "lagrange.h"&lt;br /&gt;&lt;br /&gt;using namespace kodumaro;&lt;br /&gt;&lt;br /&gt;Lagrange::Lagrange(const double *vx, const double vy, int len):&lt;br /&gt;    vector_x(vx), vetory(vy), length(len) {}&lt;br /&gt;&lt;br /&gt;double Lagrange::getY(double x) {&lt;br /&gt;    double y = 0;&lt;br /&gt;&lt;br /&gt;    for (int i = 0; i &amp;lt; length; ++i) { // ciclo do somatório&lt;br /&gt;        double aux = vector_y[i];&lt;br /&gt;        for (int j = 0; j &amp;lt; length; ++j) // ciclo do produtório&lt;br /&gt;            if (i != j)&lt;br /&gt;                aux *= (x - vector_x[j]) / (vector_x[i] - vector_x[j]);&lt;br /&gt;        y += aux;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return y;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E está pronto! Basta incluir &lt;code&gt;lagrange.h&lt;/code&gt; e compilar &lt;code&gt;lagrange.cc&lt;/code&gt; junto com seu código teste.&lt;br /&gt;&lt;br /&gt;O uso é simples:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;kodumaro::Lagrange lagr(vx, vy, len);&lt;br /&gt;y = lagr.getY(x);&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Common Lisp&lt;/h3&gt;&lt;br /&gt;Não seria legal fazer isso sem usar uma &lt;a href="http://pt.wikipedia.org/wiki/Programação_funcional"&gt;linguagem funcional&lt;/a&gt;. =)&lt;br /&gt;&lt;br /&gt;Também vamos aproveitar orientação a objetos &amp;ndash; sim! É possível combinar orientação a objetos e programação funcional &amp;ndash; para guardar nossos dados.&lt;br /&gt;&lt;br /&gt;A classe será similar à de C++, mas o atributo será uma lista de pares de coordenadas:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(defclass lagrange ()&lt;br /&gt;  ((pairs :initarg :pairs :accessor lagrange-pairs)))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora o método para calcular a ordenada em relação a uma abscissa:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(defmethod lagrange-get-y ((a-lagrange lagrange) x)&lt;br /&gt;  (reduce '+&lt;br /&gt;    (loop&lt;br /&gt;      for '(xi . yi) in (lagrange-pairs a-lagrange)&lt;br /&gt;      for i from 0&lt;br /&gt;      collect (* yi (reduce '*&lt;br /&gt;        (loop&lt;br /&gt;          for '(xj . yj) in (lagrange-pairs a-lagrange)&lt;br /&gt;          for j from 0&lt;br /&gt;          collect (if (= i j)&lt;br /&gt;            1&lt;br /&gt;            (/ (- x xj) (- xi xj)))))))))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A relação entre esse código e a expressão matemática acima é praticamente 1:1.&lt;br /&gt;&lt;br /&gt;O uso é:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;(let ((a-lagrange (make-instance 'lagrange :pairs coordinates)))&lt;br /&gt;  (setq y (lagrange-get-y a-lagrange x)))&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Smalltalk&lt;/h3&gt;&lt;br /&gt;Se foi legal usar orientação a objetos numa linguagem onde a orientação foi &lt;em&gt;costurada&lt;/em&gt; como em uma colcha de retalhos e em uma linguagem funcional, imaginem em uma linguagem &lt;strong&gt;realmente&lt;/strong&gt; orientada a objetos!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://smalltalk.org/"&gt;Smalltalk&lt;/a&gt; é uma das linguagens mãe da orientação a objetos: criada antes de C a partir de &lt;a href="http://staff.um.edu.mt/jskl1/talk.html"&gt;Simula&lt;/a&gt;, é praticamente a linguagem que define os conceitos de orientação a objetos.&lt;br /&gt;&lt;br /&gt;Como já disse antes, tornei-me fã do &lt;a href="http://squeak.org/"&gt;Squeak&lt;/a&gt;, devido a sua &lt;a href="http://www2.dc.ufscar.br/~junia/Construcionismo.htm"&gt;aplicabilidade educacional&lt;/a&gt; e ao &lt;a href="http://wiki.laptop.org/go/Smalltalk_Development_on_XO"&gt;XO&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;No Squeak, abra o System Browser, se não houver um pacote &lt;code&gt;Kodumaro&lt;/code&gt; crie-o e, dentro dele, uma categoria &lt;code&gt;Kodumaro-Interpolation&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Na categoria, crie um classe:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;PointArray subclass: #Lagrange&lt;br /&gt;    instanceVariableNames = ''&lt;br /&gt;    classVariableNames = ''&lt;br /&gt;    poolDictionaries: ''&lt;br /&gt;    category: 'Kodumaro-Interpolation'&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora crie o método para calcular a ordenada para uma abscissa:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;getY: x&lt;br /&gt;    | y |&lt;br /&gt;&lt;br /&gt;    y := 0.&lt;br /&gt;    1 to: self size do: [ :i | | aux |&lt;br /&gt;        aux := (self at: i) y.&lt;br /&gt;        1 to: self size do: [ :j |&lt;br /&gt;            (i ~= j) ifTrue: [&lt;br /&gt;                aux := aux * (&lt;br /&gt;                    (x - (self at: j) x)&lt;br /&gt;                    /&lt;br /&gt;                    ((self at: i) x - (self at: j) x)&lt;br /&gt;                )&lt;br /&gt;            ]&lt;br /&gt;        ].&lt;br /&gt;        y := y + aux.&lt;br /&gt;    ].&lt;br /&gt;&lt;br /&gt;    &amp;uarr; y&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E pronto! Você pode testar instanciando &lt;code&gt;Lagrange&lt;/code&gt; &amp;ndash; o método &lt;code&gt;new:&lt;/code&gt; recebe o tamanho do vetor como parâmetro &amp;ndash; e passando a mensagem &lt;code&gt;getY:&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Io&lt;/h3&gt;&lt;br /&gt;&lt;a href="http://iolanguage.com/"&gt;Io&lt;/a&gt; é uma linguagem prototipada baseada principalmente em &lt;a href="http://research.sun.com/self/"&gt;Self&lt;/a&gt; e &lt;a href="http://www.lua.org"&gt;Lua&lt;/a&gt;, mas também em outras, como Smalltalk e Lisp.&lt;br /&gt;&lt;br /&gt;O código Io pode ser:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;Point := Object clone do(&lt;br /&gt;    x := 0&lt;br /&gt;    y := 0&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;Lagrange := List clone do(&lt;br /&gt;    // Gostei da ideia desse método add&lt;br /&gt;    add := method(sx, sy,&lt;br /&gt;        p := Point clone&lt;br /&gt;        p x = sx&lt;br /&gt;        p y = sy&lt;br /&gt;        append(p)&lt;br /&gt;    )&lt;br /&gt;&lt;br /&gt;    getY := method(x,&lt;br /&gt;        y := 0&lt;br /&gt;        for(i, 0, size - 1,&lt;br /&gt;            aux := at(i) y&lt;br /&gt;            for(j, 0, size - 1,&lt;br /&gt;                // Havia feito diferente antes,&lt;br /&gt;                // mas acho o if assim mais claro:&lt;br /&gt;                if(i != j) then(&lt;br /&gt;                    aux = aux * ( &amp;#92;&lt;br /&gt;                        (x - at(j) x) &amp;#92;&lt;br /&gt;                        / &amp;#92;&lt;br /&gt;                        (at(i) x - at(j) x) &amp;#92;&lt;br /&gt;                    )&lt;br /&gt;                )&lt;br /&gt;            )&lt;br /&gt;            y = y + aux&lt;br /&gt;        )&lt;br /&gt;        return y&lt;br /&gt;    )&lt;br /&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Vou dar um exemplo de código pois, devido a ser uma linguagem recente, não há muita documentação.&lt;br /&gt;&lt;br /&gt;Digamos que você salvou o código acima no arquivo &lt;code&gt;lagrange.io&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;Io&amp;gt;&lt;/em&gt; &lt;strong&gt;Importer FileImporter import("lagrange")&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Io&amp;gt;&lt;/em&gt; &lt;strong&gt;v := Lagrange clone&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Io&amp;gt;&lt;/em&gt; &lt;strong&gt;v add(1, 10)&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Io&amp;gt;&lt;/em&gt; &lt;strong&gt;v add(2, 100)&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Io&amp;gt;&lt;/em&gt; &lt;strong&gt;v add(3, 1000)&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Io&amp;gt;&lt;/em&gt; &lt;strong&gt;v getY(2)&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;==&amp;gt; 100&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Io&amp;gt;&lt;/em&gt; &lt;strong&gt;v getY(2.5)&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;==&amp;gt; 448.75&lt;/em&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conclusão&lt;/h3&gt;&lt;br /&gt;Bem, desta vez deixo a conclusão ao leitor e convido a quem quiser fazer também suas implementações.&lt;br /&gt;&lt;br /&gt;Outro método muito interessante é o &lt;a href="http://pt.wikipedia.org/wiki/Polinómio_de_Newton"&gt;polinómio de Newton&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-1245036921709216203?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/1245036921709216203/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=1245036921709216203' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/1245036921709216203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/1245036921709216203'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2008/06/polinomio-de-lagrange.html' title='Cálculos estatísticos: polinómio de Lagrange'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_rGfO7DAuOSE/Rgv00nwEXZI/AAAAAAAAAB8/r59qEVD0qOE/s72-c/haskell.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-5973406988567080836</id><published>2008-06-07T18:44:00.005-03:00</published><updated>2008-06-12T21:17:26.445-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Math'/><category scheme='http://www.blogger.com/atom/ns#' term='Smalltalk'/><category scheme='http://www.blogger.com/atom/ns#' term='Conceitual'/><title type='text'>Variância em Smalltalk</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://3.bp.blogspot.com/_rGfO7DAuOSE/SByvpfxLTOI/AAAAAAAAAFQ/nea8UWGDh5A/s200/squeak.jpg" alt="Squeak" /&gt; Já que o &lt;a href="http://kodumaro.blogspot.com/2008/06/variancia-com-linguagem-funcional.html"&gt;artigo sobre variância&lt;/a&gt; rendeu &lt;a href="http://programandosemcafeina.blogspot.com/2008/06/clculo-da-varincia-com-ruby.html"&gt;outro artigo interessante&lt;/a&gt;, me empolguei e resolvi escrever como implementar o &lt;a href="http://pt.wikipedia.org/wiki/Variância"&gt;cálculo da variância&lt;/a&gt; em &lt;a href="http://smalltalk.org/"&gt;Smalltalk&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Como gostei muito da ferramenta e para privilegiar seu foco &lt;strong&gt;educacional&lt;/strong&gt;, vou usar o &lt;a href="http://squeak.org/"&gt;Squeak&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Abra o System Browser e, se não tiver o pacote &lt;code&gt;Kodumaro&lt;/code&gt;, crie-o. Crie então a categoria &lt;code&gt;Kodumaro-Variance&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Crie então a seguinte classe:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;FloatArray subclass: #VariantiableArray&lt;br /&gt;    instanceVariableNames: ''&lt;br /&gt;    classVariableNames: ''&lt;br /&gt;    poolDictionaries: ''&lt;br /&gt;    category: 'Kodumaro-Variance'&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora os métodos&amp;hellip;&lt;br /&gt;&lt;br /&gt;Na categoria &lt;code&gt;math&amp;nbsp;functions&lt;/code&gt;, crie o método &lt;code&gt;rms&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;rms&lt;br /&gt;    "Calculates and returns the root mean square"&lt;br /&gt;    | aux |&lt;br /&gt;&lt;br /&gt;    aux := 0.&lt;br /&gt;    self do: [ :e |&lt;br /&gt;        aux := aux + (e * e)&lt;br /&gt;    ].&lt;br /&gt;&lt;br /&gt;    &amp;uarr; (aux / self size) sqrt&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;É claro que poderíamos criar um método para retornar o numerador do cálculo, mas vou fazer diferente. =)&lt;br /&gt;&lt;br /&gt;Vamos implementar a variância populacional com média aritmética &amp;ndash; &lt;code&gt;average&lt;/code&gt;, herdado de &lt;code&gt;Collection&lt;/code&gt;, já que costuma ser um valor mais redondo &amp;ndash; e a variância da amostra com média quadrada, ambas também na categoria &lt;code&gt;math&amp;nbsp;functions&lt;/code&gt;.&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;populationalVariance&lt;br /&gt;    "Calculates and returns the populational variance"&lt;br /&gt;    | aux mean |&lt;br /&gt;&lt;br /&gt;    aux := 0.&lt;br /&gt;    mean := self average.&lt;br /&gt;&lt;br /&gt;    self do: [ :e | | temp |&lt;br /&gt;        temp := e - mean.&lt;br /&gt;        aux := aux + (temp * temp).&lt;br /&gt;    ].&lt;br /&gt;&lt;br /&gt;    &amp;uarr; aux / self size&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora a variância amostral:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;sampleVariance&lt;br /&gt;    "Calculates and returns the sample variance"&lt;br /&gt;    | aux mean |&lt;br /&gt;&lt;br /&gt;    aux := 0.&lt;br /&gt;    mean := self rms.&lt;br /&gt;&lt;br /&gt;    self do: [ :e | | temp |&lt;br /&gt;        temp := e - mean.&lt;br /&gt;        aux := aux + (temp * temp).&lt;br /&gt;    ].&lt;br /&gt;&lt;br /&gt;    &amp;uarr; aux / (self size - 1)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Está pronto!&lt;br /&gt;&lt;br /&gt;&amp;mdash; &lt;em&gt;Como assim? Só isso?&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;É, só isso. =)&lt;br /&gt;&lt;br /&gt;Vamos testar, abra um &lt;code&gt;Workspace&lt;/code&gt; e digite:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;| v |&lt;br /&gt;&lt;br /&gt;v := VariantiableArray newFrom: #(1 2 3 4 5).&lt;br /&gt;&lt;br /&gt;Transcript&lt;br /&gt;    open;&lt;br /&gt;    show: 'Média aritmética: ', v average printString; cr;&lt;br /&gt;    show: 'Média quadrada: ', v rms printString; cr;&lt;br /&gt;    show: 'Variância populacional: ', v populationalVariance printString; cr;&lt;br /&gt;    show: 'Variância da amostra: ', v sampleVariance printString; cr.&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Pressione &lt;em&gt;M-a M-d&lt;/em&gt; para executar.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-5973406988567080836?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/5973406988567080836/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=5973406988567080836' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5973406988567080836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/5973406988567080836'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2008/06/variancia-em-smalltalk.html' title='Variância em Smalltalk'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_rGfO7DAuOSE/SByvpfxLTOI/AAAAAAAAAFQ/nea8UWGDh5A/s72-c/squeak.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1387996720436450649.post-916180527495810487</id><published>2008-06-03T22:30:00.001-03:00</published><updated>2008-06-03T22:32:00.298-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Smalltalk'/><title type='text'>Habilitando XML em Io</title><content type='html'>&lt;img style="border: none; margin: 0pt 10px 10px 0pt; float: left; cursor: crosshair;" src="http://4.bp.blogspot.com/_rGfO7DAuOSE/SAgRW_eGesI/AAAAAAAAAEw/GjXZ9uFSIVU/s320/visualworks.png" alt="VisualWorks" /&gt; É extremamente frustrante instalar &lt;a href="http://www.iolanguage.com/"&gt;Io&lt;/a&gt; e descobrir que os recursos de XML não funcionam!&lt;br /&gt;&lt;br /&gt;Mas existe solução. ;)&lt;br /&gt;&lt;br /&gt;Você vai primeiro no &lt;a href="http://www.hick.org/code.html"&gt;Hick.org&lt;/a&gt; e baixa a &lt;a href="http://www.hick.org/code/skape/libsgml/"&gt;libsgml&lt;/a&gt; &amp;ndash; estou usando a &lt;a href="http://www.hick.org/code/skape/libsgml/libsgml-1.1.4.tar.gz"&gt;versão 1.1.4&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Descompacte, configure e compile:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;tar xzvf libsgml-*.tar.gz&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;cd libsgml-*/&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;./configure&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;make&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Antes de instalar, edite o &lt;code&gt;Makefile&lt;/code&gt;, identifique a seguinte linha:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;install -m 644 -o root -g root --directory /usr/local/include/sgml&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;E &lt;strong&gt;substitua-a&lt;/strong&gt; pelo seguinte:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;install -o root -g root --directory /usr/local/include/sgml&lt;br /&gt;install -m 644 -o root -g root include/Variant.h &amp;#92;&lt;br /&gt;    /usr/local/include/sgml/Variant.h&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Não esqueça de respeitar a indentação!&lt;br /&gt;&lt;br /&gt;Feito isso, pode instalar:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;sudo make install&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Agora recompile e reinstale seu pacote Io.&lt;br /&gt;&lt;br /&gt;Para testar:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;em&gt;bash$&lt;/em&gt; &lt;strong&gt;io&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Io 20080120&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Io&amp;gt;&lt;/em&gt; &lt;strong&gt;SGML&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Io&amp;gt;&lt;/em&gt; &lt;strong&gt;xml := URL with("http://kodumaro.blogspot.com/") fetch asXML&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Io&amp;gt;&lt;/em&gt; &lt;strong&gt;links := xml elementsWithName("a") map(attributes at("href"))&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Io&amp;gt;&lt;/em&gt; &lt;strong&gt;links foreach(link, link println)&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Referência: &lt;a href="http://www.iolanguage.com/scm/git/checkout/Io/docs/IoGuide.html#Primitives-XML"&gt;Io Programming Guide&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;[]'s&lt;br /&gt;Cacilhas, La Batalema&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1387996720436450649-916180527495810487?l=kodumaro.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kodumaro.blogspot.com/feeds/916180527495810487/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=1387996720436450649&amp;postID=916180527495810487' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/916180527495810487'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1387996720436450649/posts/default/916180527495810487'/><link rel='alternate' type='text/html' href='http://kodumaro.blogspot.com/2008/06/habilitando-xml-em-io.html' title='Habilitando XML em Io'/><author><name>Darth Batalema</name><uri>http://www.blogger.com/profile/14265747724618147106</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/-qTEYswdhBwA/Td-uAIo2SII/AAAAAAAAAac/ekYfzs4jqbA/s220/darthbatalema-150x108.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_rGfO7DAuOSE/SAgRW_eGesI/AAAAAAA
