sábado, 15 de novembro de 2014

Questions and the trivium

The fundamental questions of interpreting reality are the the five Ws and one H. These are intimately
related to the trivum in the following way:

  •     Grammar : who, what, where, when 
  •     Logic : Why 
  •     Rhetoric : How 


Interestingly, the trivium can be seen in another light and by a different set of names:

  •  Grammar -> Information
  •  Logic       -> Knowledge
  •  Rhetoric   -> Wisdom

quinta-feira, 10 de julho de 2014

O valor

'A saudade nos leva a reflexão,
do que, na vida, é a razão.
Por isso sentir-la tem seu valor,
apesar de toda a dor.'

segunda-feira, 23 de junho de 2014

The taxonomy of emotional mirroring

The taxonomy of emotional mirroring

The taxonomy of emotional mirroring

People usually have the capacity of emotional mirroring based on the state of another person. I.e, to feel certain emotions based on a perceived emotion of another person.
The identification of these emotions, or their general structure, would be helpful in understanding the thymology (general psychology) of humans, and to better predict their purposes and actions.
Luckily, given that, the structure of mirroring can be classified a priori into generic classes based on the fulfillment of happiness (or its negation), both of the mirrored and mirroring actors.
Using this schema, we arrive at the following table:
ϕ ¬ϕ
ω Mudita Envy
¬ω Schadenfreude Sympathy
ϕ→ Mirroring actor happy
ω→ Mirrored actor happy
One important note is that an actor can be indifferent to other actors, and in this context this taxonomy is irrelevant.

segunda-feira, 24 de junho de 2013

Minha análise sobre os recentes protestos.

O movimento que se formou no Brasil não é de 'esquerda' nem de 'direita'. É da moda. A maior parte das pessoas que participam dele não tem um arcabouço teórico pra encaixar e compreender as dificuldades que encontram na vida, e por isso estão com raiva. Essa raiva foi expressa agora pois as manifestações atingiram massa crítica o suficiente pra essas pessoas terem segurança nos números. Essa massa crítica eu desconfio que foi formada graças a inflação monetária constante e a percepção cada vez maior que existe algum problema sério com o modelo que deveria ter dado certo (social democracia). Uma evidência dessa percepção é a raiva contra os partidos políticos, dirigida aos partidos de 'esquerda' e aos de 'direita'.
Minhas previsões:
  • Alguns líderes do MPL e outros assim percebidos pelo governo irão ganhar verbas vultuosas para suas ONGs.
  • Outros serão trazidos mais perto do poder, e virarão políticos.
  • Os membros da tradicional esquerda irão esvaziar o movimento, pois esse se tornou de massa realmente, e a massa no Brasil é extremamente conservadora socialmente (preconceituosa com negros, homossexuais, mulheres e indígenas). Claro, isso não se traduz em liberalismo econômico.
  • A raiva irá se esfriar, mas o rancor permanecerá, e se tornará cada vez mais profundo com o aumento da inflação, o inchamento de cargos públicos e os serviços públicos cada vez mais estatais e, por consequência, piores.
  • Por causa do item acima, veremos no futuro movimentos mais violentos e provavelmente voltados contra alguma válvula de escape (empresas internacionais, minorias vistas (correta e incorretamente) como privilegiadas, etc)

Minha única sugestão para fugir desses cenários é educação econômica dos indivíduos , mas isso é difícil, e é uma tarefa que cada um tem que realizar por si mesmo.

segunda-feira, 29 de outubro de 2012

Programming paradigms, case studies in clojure

Hello there internet. As part of my new job, I've done a small presentation about programming paradigms, and I've sliced and sent it to youtube.

Sorry about the background noise. I need a new mic.

segunda-feira, 11 de junho de 2012

Persistence vs Endurance

Quick post about a distiction that I find important for programmers in general, and specially for those involved with declarative programming. You can thank Ritch Hickey for this post 1 2.

Persistence is a synonim for immutable. That is, any function applied to this structure should produce a new version of it instead of mutating it.

Endurance is the capacity of a thing to resist the passage of time. This is what usually what people refer to as persistance.

2 concepts decomplected. Cool.

terça-feira, 29 de maio de 2012

Transporte coletivo, greve e monopólios

Resumo:

Uma greve de proporções alarmantes de novo se alenta na cidade de Florianópolis. Nessa ilha da magia os cidadãos contabilizam perdas enormes de dinheiro, tempo, liberdade e paciência.

Vou criticar nestas linhas o modelo atual, apontando seu defeito fundamental. Se este defeito fosse consertado, teríamos a redução de custos, greves, filas e um maior conforto e benefício para os consumidores do serviço de transporte coletivo.


O que é monopólio

Se os leitores desejarem uma leitura mais abrangente recomendo a fonte que usei nas palavras a seguir.Sennholz () Ela é muito mais completa e profissional que a amadora resenha que se segue. Pois bem. Existem 2 tipos de monopólio, o bom e o mau.

O bom

O que controla o preço de produtos produzidos por monopolistas em um ambiente de mercado livre? Basicamente a concorrência em potencial, ou seja, mesmo que uma empresa fique tão eficiente que apenas ela reste num determinado setor, ela não pode relaxar e começar a cobrar preços ``abusivos'', pois tal atitude criaria espaço para novos empreendedores e empresas de outros setores adentrarem o setor do monopolista.

Em outras palavras:

A concorrência potencial existe em todas as áreas da produção e do comércio em que haja liberdade de entrada; áreas em que qualquer pessoa seja livre para entrar e competir. Em outras palavras, em qualquer setor em que o governo não impeça a livre entrada por meio de licenças, concessões, parcerias e outras formas de controle, a concorrência potencial irá existir. As empresas e os empreendedores estão continuamente em busca de novos itens e novas linhas de produção. Motivados pela busca do lucro e guiados pelo sistema de preços, eles estão constantemente ávidos para empreender em qualquer área pouco explorada cujos rendimentos potenciais sejam atipicamente altos.

Não havendo regulamentações e burocracias governamentais, a incursão em um outro setor da economia exigirá de uma empresa pouco mais do que uma simples reorganização, atualização e aquisição de novos equipamentos, algo que pode ser feito em algumas semanas ou meses. Ou, no extremo, instalações novas podem ser construídas para se empreender uma vigorosa incursão neste novo setor. Assim, um produtor, seja ele um monopolista, um duopolista ou um concorrente dentre vários, estará sempre enfrentando a concorrência potencial de todos os outros produtores existentes no mercado. Sennholz ()

O mau

O mau é resultado da negação direta da concorrência em potencial, através da única entidade capaz de impedir a entrada de novos empreendedores num determinado mercado, o estado. Se esta entidade garantir uma existência confortável aos monopolistas com certeza estes irão se aproveitar de sua posição dominante e enforçar preços muito mais altos do que os encontrados no mercado livre, além da baixa qualidade e serviços oferecidos.

Novamente fazendo uso das palavras de Sennholz ():

o governo efetivamente restringe a concorrência e cria monopólios locais e nacionais. Toda a regulamentação governamental sobre o mercado tem o objetivo de garantir a determinadas empresas — os membros do monopólio, oligopólio ou cartel — uma renda ``justa'', o que significa uma renda bem maior do que aquela que conseguiriam no livre mercado.

A crise do transporte coletivo em Florianópolis

A análise econômica acima nos ajuda a entender a situação do transporte coletivo de Florianópolis da seguinte forma:

A - Existe concessões exclusivas das linhas de Florianópolis, com a prefeitura agindo como guardiã das mesmas.

B - Por causa dessa atitude surgem micro monopólios maus no transporte coletivo na cidade.

C - Os monopólios causam desperdício, mau uso, má qualidade e preços mais altos do que os encontrados em um mercado livre. (vide seção anterior)

Resumindo, o estado garante a posição das empresas de transporte coletivo (junto com seus sindicatos aparelhados), transferindo os impostos dos moradores de Florianópolis para elas e mantendo o preço nas alturas. Um abraço corporativista que garante farto apoio em épocas de eleições, tanto das empresas quanto dos sindicatos dos trabalhadores das mesmas, em troca de uma condição confortável e suculenta para os parasitas sobre rodas.

Conclusão

No nível teórico, a situação do transporte coletivo de Florianópolis é uma ilustração ótima da teoria do monopólio da escola austríaca de economia Rothbard (1970).

No nível prático, nem as empresas nem o sindicato dos trabalhadores são os principais responsáveis pela situação vergonhosa do transporte coletivo em Florianópolis. O responsável é o governo municipal, que através da sua política de concessões, criou monopólios municipais em detrimento do cidadão.

Bibliografia

Murray N. Rothbard.
Man, economy, and state.
1970.
URL http://mises.org/rothbard/mes/chap10a.asp.

Hans F. Sennholz.
Monopólio bom e monopólio ruim - como são gerados e como são mantidos.
URL http://mises.org.br/Article.aspx?id=1057.

terça-feira, 15 de maio de 2012

A recaptcha downloader in clojure.

A small snippet for the community and for myself in the future. I think the code is simple enough to be self explanatory.
(ns blanket.recaptcha-downloader
  (:require [clj-http.client :as client])
  (:use [clojure.java.io :as io]))

(def recaptcha-address
  "http://www.google.com/recaptcha/api/reload?c=03AHJ_VutgYGIAR51CgxyMvWU_8nVtoUhbTV9w3tCRIKvAxWPN7OMidVd8XCGH_gljkGAdXBvLC3axQ3n4ei4_pe6MFhw_WwhPkGEzPLqHYn1xqcAbE_SFs8zPtW47_yICuNmB35gp_ue8jLlpR6OqKTfoXH4D1fJLNA&k=6Ld4iQsAAAAAAM3nfX_K0vXaUudl2Gk0lpTF3REf&reason=r&type=image")

(defn fetch 
  "Downloads a number of recaptchas into a given directory, or data/
  as a default dir."
  ([N] (fetch N "data/"))
  ([N dir]
     (doseq [i (range N)]
       (let [c-num (second (re-find #"\'(.*)\',"
                                    (:body (client/get recaptcha-address))))]
         (with-open [in (io/input-stream
                         (str "http://www.google.com/recaptcha/api/image?c="
                              c-num))
                     out (io/output-stream (str dir c-num ".jpg"))]
           (io/copy in out))))))



terça-feira, 24 de abril de 2012

Cleaner meaner emacs .init file

Just finished an improved version of my emacs configuration in order to clean up
its increasing complexity. Check out its size:


(defvar *my-default-lib* "~/.emacs.d/lib"
  "Vendor libraries that cannot be installed via the package system")
(defvar *my-conf* "~/.emacs.d/conf/"
  "My configurations")

(add-to-list 'load-path *my-default-lib*)
(add-to-list 'load-path *my-conf*)


(load "package-manager.el")
(load "misc.el")
(load "history.el")
(load "keybindings.el")
(load "ido-conf.el")
(load "autocompletion.el")
(load "eshell-conf.el")
(load "slime-conf.el")
(load "spell-checking.el")
(load "lisp-conf.el")
(load "scheme-conf.el")
(load "ruby-conf.el")
(load "js-conf.el")
(load "haskell-conf.el")


(setq custom-file (concat *my-conf* "custom.el"))
(load custom-file 'noerror)
Basically everything now has its own file. There is also a nice package system that I borrowed from here. That means that everything that can be installed through the package system will be.
(require 'package)
(add-to-list 'package-archives
             '("marmalade" . "http://marmalade-repo.org/packages/")
             '("ELPA"      . "http://tromey.com/elpa/"))

(package-initialize)

(defvar my-packages '(ac-slime
                      highlight-parentheses
                      highlight-symbol
                      paredit
                      rainbow-delimiters
                      ido-ubiquitous
                      smex
                      undo-tree
                      haskell-mode
                      yasnippet
                      yasnippet-bundle
                      clojure-mode
                      zenburn-theme)
  "A list of packages to ensure are installed at launch.")


(defun my-packages-installed-p ()
  (loop for p in my-packages
        when (not (package-installed-p p)) do (progn (message "%s" p) (return nil))
        finally (return t)))

(unless (my-packages-installed-p)
  ;; check for new packages (package versions)
  (message "%s" "Emacs is now refreshing its package database...")
  (package-refresh-contents)
  (message "%s" " done.")
  ;; install the missing packages
  (dolist (p my-packages)
    (when (not (package-installed-p p))
      (package-install p))))


quarta-feira, 11 de abril de 2012

What school is all about

I have just finished a piece of John Taylor
Gatto's book. So far it is brilliant, heavy, and truer than the overwhelming material
I have read on schooling (exceptions go to Seymour Papert and Ivan
Illich). One thing that struck me deep was a poem by a high
school senior in Alton, Illinois, two weeks before he committed
suicide
.
I though of sharing it here, for me to remember what
school is all about.

He drew... the things inside that needed saying.
Beautiful pictures he kept under his pillow.
When he started school he brought them...
To have along like a friend.
It was funny about school, he sat at a square brown
desk Like all the other square brown desks... and his
room Was a square brown room like all the other
rooms, tight And close and stiff.
He hated to hold the pencil and chalk, his arms stiff
His feet flat on the floor, stiff, the teacher watching
And watching. She told him to wear a tie like
All the other boys, he said he didn't like them.
She said it didn't matter what he liked. After that the
class drew.
He drew all yellow. It was the way he felt about
Morning. The Teacher came and smiled, "What's this?
Why don't you draw something like Ken's
drawing?"
After that his mother bought him a tie, and he
always Drew airplanes and rocketships like
everyone else.
He was square inside and brown and his hands were
stiff. The things inside that needed saying didn't
need it
Anymore, they had stopped pushing... crushed, stiff
Like everything else.

quarta-feira, 14 de março de 2012

Dynamic racket pascal




Hello.

Through HN, I have stumbled upon Cletus blog, and I have
read this
post
of his. It enticed me to try out some version of mine for
the dynamic programming version. Here it is, coded in racket with a
contract and a small test case.
#lang racket

(provide (contract-out
          [pascal-triangle (-> exact-positive-integer? vector?)]))

(define (pascal-triangle n)
  (define (loop accumulator row)
    (if (= n row)
        accumulator
        (let* ([previous (vector-ref accumulator
                                     (sub1 (vector-length accumulator)))]
               [current-row
                (vector-append #(1)
                               (for/vector ((i (in-range 1 row)))
                                           (+ (vector-ref previous (sub1 i))
                                              (vector-ref previous i)))
                               #(1))])
          (loop (vector-append accumulator (vector current-row)) (add1 row)))))
  (loop #(#(1)) 1))


(for ([row (pascal-triangle 30)])
     (displayln row))

See you.

quarta-feira, 7 de março de 2012

Codifique livre ou morra(): Porque Hackers geralmente são libertários

Daniel Franke,(traduzido por Eduardo Bellani)


Para qualquer um que tenha habitado a internet por tempo suficiente para
diferenciar ICANN de 4chan ou um netcat de um LOLcat, não vai ser novidade que
hackers são com freqüência libertários. A razão é normalmente entendiada como
algo assim: hackers, por definição, gostam de coisas esquisitas, como desmontar
o tocador de DVD ou pesquisar como uma bomba nuclear funciona. Legisladores, que
falham cronicamente em entender o porque alguém iria gostar dessas coisas ou
porque que elas teriam valor pra alguém, passam leis que interferem com essas
atividades. Justificadamente irados, hackers adotam visões políticas que se
opõem a estas intrusões.

A mais clara exposição deste modelo talvez seja o artigo de 2004 do Paul Graham
chamado "A palavra `hacker'". A idéia geral entretanto já está tacitamente
entendida a muito mais tempo. Ela é a base para o tom de várias histórias do
site Slashdot. Observações da correlação hacker-libertário é ainda mais
antiga; não da pra ler USENET antiga por 10 minutos sem perceber-la.

A rescrição de Gordon ao corolário de Newman sobre a lei de Godwin observa
"Libertarismo (pro, contra, e lutas entre as facções) é o tópico primordial
de discussões do net.news. Qualquer hora que o debate muda para outro lugar, ele
precisa eventualmente voltar a esta fonte de combustível" (Não sei quando isto
foi escrito. Não foi entes de 1990 que a lei de Godwin foi criada, e não depois
de 1994 que Godwin a citou).

Hackers tem uma longa história de conflitos com governo. Uma lista incompleta:


  • 1986: O ``Computer Fraud and Abuse Act" passa no congresso americano,
    tornando pela primeira vez cracking um crime. Enquanto ele é direcionado
    principalmente a crimes não controversos, abuso legal por autoridades
    ignorantes por atos perfeitamente legais como port-scanning se torna
    rotina na década de 90.

  • 1993: Philip Zimmerman é o alvo de uma investigação criminal depois que o
    PGP é sai dos Estados Unidos, em violação de restrições de exportação para
    criptografia (que era classificada como munição na época).

  • 1996: O ``Communications Decency Act" restringe severamente material
    "obsceno ou indecente" na internet. Esta lei é negada pela Suprema Corte
    dos Estados Unidos no ano seguinte

  • 1998: O ``Digital Millennium Copyright Act" passa, tornando crime qualquer
    tentativa de passar pelas medidas de segurança que tem como objetivo proteger
    material com copyright, independentemente da intenção do tentativa.

  • 1999: Jon Johansen et. al. libera o DeCSS, decodificando a `encriptação'
    ridícula usado praticamente em todos os DVDs e tornando possível assistir
    DVDs usando software open-source. No ano seguinte, a casa de Johansen é
    invadida pela polícia Norueguesa.

  • 1999: Amazon recebe a notória patente do 1-click.

  • 2000: 72 pessoas na Califórnia recebem uma intimação proibindo-as de usar
    uma camiseta contendo o código de uma parte do DeCSS.

  • 2001: Dimitry Sklyrov, um programador russo visitando os Estados Unidos, é
    preso pela lei DMCA e detido por vários meses por ter escrito um leitor
    de e-book capaz de ler vários formatos com DRM.

  • 2002: Sarbanes-Oxley torna quase impossível para pequenas startups web
    fazerem abertura de ações

  • 2003: A saga legal da SCO começa. SCO exige que todos os usuários Linux a
    paguem $700 dólares de licença.

  • 2003: O FBI invoca abusivamente o USA PATRIOT ACT para recuperar
    notas de repórteres que entrevistaram Adrian Lamo.

  • 2004: No que Brad Templeton descreve como `spamlitigação', o RIAA começa a
    processar seus clientes em massa, distribuindo mais de 20000 processos
    legais, incluindo crianças, avós e falecidos entre os acusados.

  • 2005: FEC Commissioner Bradley Smith afirma que `a exceção da imprensa' do
    McCain-Feingold Campaign Finance Reform Act não inclui bloggers.


Entretanto, estes casos são insuficientes para explicar as atitudes dos hackers.
A cultura hacker existe desde que as universidades tiveram acesso aos
computadores - desde os anos 60 - e mesmo antes era reconhecida pela sua
incarnação anterior dos operadores de rádio amador. Foi uma cultura libertária
desde sua concepção. Mesmo assim, a lista começa em 1986. Antes do CFAA, era
difícil apontar para qualquer intrusão que incomodasse os hackers em particular.
Uso civil dos computadores não estava no radar do congresso e da polícia até
então.

Para não fazer injustiça a tese de Graham, ela é muito mais abrangente que
qualquer lista de reclamações. Graham observa corretamente que hackers tem suspeita de toda a autoridade, mesmo
onde a teoria libertária diz que esta autoridade é legítima. Hackers ficam tão
nervosos com o chefe que controla seu departamento fala para eles que "Eu
acabo de ler numa revista sobre algo chamado virtualização. Nós deveríamos usar
isso." quanto vão ficar com algum agente do governo. Por isso os hackers já se
incomodavam bastante antes de 1986. O governo chegou tarde para essa festa.

Mas a obvervação que hackers são um grupo de espertinhos reclamações não explica o
porque disto. Se as reclamações não se limitam a intersecção entre governo e
tecnologia, porque esta atitude tem relação com escrever código?

A resposta de Graham a isto é a seguinte:

Deixe-me colocar isto em termos que um oficial do governo iria apreciar.
As liberdades civis não são apenas um ornamento, ou uma velha tradição
americana. Liberdades civis fazem os países enriquecerem. Se você fizer um
gráfico de PIB per capita vs liberdades civis, você verá uma forte
relação. Poderia tais liberdades serem a causa, ao invés da conseqüência
da riqueza? Eu penso que sim. Eu penso que uma sociedade em que as pessoas
podem dizer e fazer o que quiserem irá ser uma onde as soluções mais
eficientes venceriam, ao invés daquelas que fossem patrocinadas pelas
pessoas mais poderosas. Países autoritários se tornam corruptos, países
corruptos se tornam pobres, e países pobres se tornam fracos. Parece que
existe uma curva Laffer para o poder do governo, assim como para impostos.
No mínimo, é provável o suficiente para não se tentar um experimento para
testar a hipótese. Ao contrário de impostos, você não pode repelir o
totalitarismo se ele não funcionar direito.

É por isso que os hackers se preocupam. O governo espionando as pessoas
não faz com que o código que eles escrevem se torne pior. Ele apenas leva
a um mundo onde as idéias ruins vencem. E por causa que isto é tão
importante para os hackers, eles são especialmente sensíveis a isto. Eles
podem sentir o autoritarismo se aproximando a distância, como animais
podem sentir uma tempestade.

Eu acho que isto é uma falácia petitio
principii
. É uma visão libertária
sobre o porque os hackers deveriam ser libertários. Se alguém concorda com a
premissa que as liberdades civis fazem as pessoas enriquecerem, então tudo seque
tranqüilamente. Mas se o governo autoritário "não faz com que o código que eles
escrevem se torne pior", então porque hackers tem uma chance maior de fazer esta
conexão?

Uma resposta tentadoramente lisonjeira para esta pergunta vêm do post de 1992 de
Stuart Reges. Resumidamente, Reges afirma que existem uma certa habilidade
mental - "QI libertário" - que nos faz melhores em formar modelos mentais de
como programas funcionam assim como formular como a sociedade funciona. A
primeira habilidade nos faz bons hackers. A segunda nos da um entendimento
intuitivo de como o libertarismo funciona.

Apesar de cortês, eu acho que este argumento erra o ponto da discussão. Toda a
teoria econômica que vem junto com o libertarismo é um efeito secundário.
Libertarismo não é sobre o que nos faz ricos; é sobre o que é certo.
``We hold these truths to be self-evident''

e tudo mais. Libertários não se opões ao governo porque é atrapalhado e
ineficiente, se opõe porque é maligno.

Além disso, acho que Reges nos dá muito crédito. O conhecimento médio dos
hackers sobre a escola Austríaca ou a de Chicago é mais medíocre do que eles se
permitiriam em qualquer assunto técnico. Comece a falar de externalidades ou o
problema do
parasita

e nós mudaremos de assunto.
Claro, os mais sofisticados irão citar o Teorema de
Coase
, mas a maioria nem
ouviu falar dele.

Eu acho que nós estivemos olhando para o problema do ângulo errado.
Não é que hackers adotam políticas libertárias, nem que existe um terceiro fator
que influencia libertários e hackers. Ao invés disso, pessoas com uma atitude
anti autoritária tendem a serem atraídos para programação.

A frase "conhecimento é poder" é um clichê, mas é também verdadeira num sentido
bem literal. Aquilo que você não entende tem poder sobre você. As pessoas que
não tem interesse em entender os computadores estão totalmente acostumadas a
serem mandadas por eles; é mais um fato da vida. Se você não sabe que você pode
mudar o bit de apenas-leitura ao clicar com o botão direito e editar o atributo
na janela de propriedades, então não ter a permissão de editar o arquivo não é
fundamentalmente diferente de não ser capaz de tocar um arquivo .wma cifrado
porque a Microsoft fechou seu servidor de licença. Tentar fazer com que pessoas
leigas se importem com DRM é inútil. Eles são sujeitos as tiranias de seus
computadores todo o tempo. Porque esta seria pior?

Mas para aqueles de temperamento libertário, isso é um estado inaceitável. Ser
mandado pelo governo já é ruim o suficiente. Mas ser mandado por um objeto
inanimado? Intolerável. Como eu posso controlar essa coisa?

Este modelo da psiquê humana explica bastante nossas idiossincrasias de
personalidade. Quando você não tolera ser ignorante sobre uma tecnologia,
aprender sobre ela é a única saída. A outra é se tornar um
ludita. Hackers se tornam
luditas com freqüência.

Para exemplificar, eu tenho o mais barato celular do mercado. Ele não pode nem
fazer o download de tons. Mas é ótimo para fazer chamadas. Porque é isso que
eles tem que fazer. Eles não são feitos para mandar email. Nem para jogar
tetris. Nem para tirar fotos. São feitos para fazer chamadas. É bastante chato
ter que descobrir como tirar meu telefone do modo de câmera. Eu não quero
descobrir como tirar meu telefone do modo de câmera, porque telefones não são
feitos para tirar fotos. São feitos para fazer chamadas.

Algumas pessoas riem dessa atitude, mas é o mesmo sentimento que hackers tem
quando reclamam de inchaço de software. Todos já escutamos, se já não tivermos
participado, de conversas como:

``Eu não quero que meu editor de texto leia email! Eu quero um editor de
texto!''

``Então use-o como um editor de texto.''

``Mas ai vou ficar com todo esse lixo espalhado no meu computador.''

``Por quê você não ignora isso? Não está nem exposto na interface gráfica.
Você tem que saber o comando correto para ativá-lo. São menos de 80MB de
espaço, e você tem 1TB no seu disco, e a maior parte não chega na RAM até
que você a invoca.''

``Mas é nojento!''

Pode parecer forçado chamar a atitude dos odiadores do emacs de ludismo, e mais
forçado ainda chamá-lo de libertária. Mas a psicologia é a mesma. Ninguém quer
tirar o tempo para entender alguma coisa que eles consideram supérflua.
Racionalmente ou não, hackers irão encontrar qualquer tecnologia que eles não
entendem com suspeita - não de seus mérito, mas de sua segurança. "I eu quero
isso ai ferrando com meu sistema", nós iremos dizer para você, mesmo sabendo
perfeitamente bem que ele irá apenas sentar em um canto do disco rígido. Já
recompilou seu kernel apenas para desabilitar um módulo que você não necessita?
A maior pare de nós já o fez, mas isso desafia qualquer base racional.

Mas essa irracionalidade é comum. As atitudes libertárias geralmente ultrapassam
os princípios libertários. Essencialmente todos os libertários defendem o
direito de portar armas, mas consideram o direito a propriedade privada mais
fundamental. Então, nós compreendemos o direito do de proprietários de proibir
armas em sua propriedade. Mas isso não impede libertários de ficarem perturbados
cada vez que um proprietário exerce esse direito.

Ficamos perturbados com os hoplofóbicos (medo de armas de fogo) pela mesma razão
que arrancamos aquele módulo do kernel: odiamos e tememos sermos controlados.

domingo, 26 de fevereiro de 2012

Python, TCO, paradigms, and online classes

I was working on some code for udacity's class and I have been bitten by something interesting, python's lack of TCO.

I know you can do the "same" things without it, but it was pretty
interesting to realize that I am nowadays so used to work with
functional languages that recursion is one of my first tools to
express loops.

Expressing things in imperative ways is taking me more time now, and I
begin to see how different paradigms really leave an impression on
you. Strange and interesting...

quarta-feira, 8 de fevereiro de 2012

Clojure composition and spirit binding

These days I had to craft something that I didn't even knew existed (don't you love when this happens?). Number composition is the name of the spirit this time.

I will paste the algorithm in clojure below, but I guess the most important thing regarding spirits is not the ritual to bind them, but how you find their names so you can research the ritual itself. My favorite source of arcana regarding spirit names is [1]. I advice it to any wizard, be they apprendice or warlock.

Well, here it goes my version of the ritual, hope you enjoy it.




(defn generate-compositions [num]
  "Returns all possible valid partitions of an integer. An useful
references:

* Skiena's The Algorithm Design Manual, section 14.6 Generating Partitions.

* http://code.activestate.com/recipes/218332/

* http://stackoverflow.com/questions/8375439/composition-algorithm-in-javascript-to-return-all-possible-compositions-of-a-num

This will run in O(2^n), so take care with large inputs."
  (defn accumulate-reduced-compositions
    ([composition-set]
       (accumulate-reduced-compositions composition-set 0 [] (count composition-set)))
    ([composition-set index acc set-lenght]
       (let [next-index (inc index)]
         (if (>= next-index set-lenght)
           acc
           (recur composition-set
                  next-index
                  (conj acc (into (conj (subvec composition-set 0 index)
                                        (+ (nth composition-set index)
                                           (nth composition-set next-index)))
                                  (subvec composition-set (inc next-index))))
                  set-lenght)))))
  
  (loop [all-compositions [(vec (repeat num 1))]
         new-compositions (accumulate-reduced-compositions (first all-compositions))]
    (let [first-new-composition (first new-compositions)]
      (if (= 1 (count first-new-composition))
        (set (conj all-compositions first-new-composition))
        (recur (into all-compositions new-compositions)
               (reduce into (map accumulate-reduced-compositions new-compositions)))))))


[1] Steven Skiena: The Algorithm Design Manual

sábado, 24 de dezembro de 2011

Return to blogging, updates and a first glance look at clojure.

Hello dear internet, it's been a year, I have missed you.

This year has been a very interesting one. I have got a job as a
researcher and technical leader, have been professionally programming
in lisp for artificial intelligence projects, built a concurrent
crawler using racket, started using clojure to integrate with java
projects, and more important, have met some very interesting people.

First, let me tell you about lisp in a professional setting. Simply
put, it rocks. Common lisp+slime is a stupendous development
environment. The ecosystem is very alive, albeit not very organized. I
have to remind myself to publish a small article about how to get to
speed with emacs + slime. It really does pays off.

Racket is without a doubt the best language I have explored so
far. The documentation is top notch, the community is full of
intelligent and helpful people, and there is a slime-like plugin
called geiser that is very nice. On a personal note, It was the first
time I have developed a system using an actor like threading system
(racket has mailbox threading). I must say that it has changed the way
I thing about concurrency.

The last technical note is about clojure. It is very nice, specially
if you have to cooperate with the JVM, something that is very probable
if you are interfacing with big corp. It is a modern language,
embracing concurrency and parallelism, is immutable by default, and at
the same time is a lisp. I encourage anyone who wants to learn
something deep and at the same time "practical", considering the JV.

We can never forget that life is about people, and I have met some
incredible people. Crazy, happy, high, depressed, strange, and
interesting people. Because of them, I have got a bit into security
again, learned more about myself and my emotions, entrepreneurship,
martial arts, Austrian economics, anarchism, and much much more. For
all of you, my deep sincere thanks.

Thanks again everyone, I sorry that I have been away for so long. I'll
try harder this time. Merry Christmas!

segunda-feira, 13 de dezembro de 2010

How many fume cupboards are needed? -- Scheme version




I am going through Principles of Statistics in order to build a more respectable statistical knowledge. When I got to problem 2.6 I though it was computational heavy for such a lazy person such as I. Apparently I am not alone in that thinking.

The result is that I ended building a scheme version of the code
found in the above page. It was a very interesting exercise. You
can see the problem and the code below:



#lang racket
;; In a certain survey of the work of chemical research workers, it was
;; found, on the basis of extensive data, that on average each man
;; required no fume cupboard for 60 per cent of his time, one cupboard
;; for 30 per cent and two cupboards for 10 per cent; three or more were
;; never required. If a group of four chemists worked independently of
;; one another, how many fume cupboards should be availabe in order to
;; provode adequate facilities for at least 95 per cent of the time?
(require "cartesian-product.rkt"
         rackunit
         rackunit/text-ui)

(define probability-of-cupboards
  #hash((0 . 0.6)
        (1 . 0.3)
        (2 . 0.1)))


;; how-many-cupboards-for-% : integer number hash -> number
;; given a minimum % and a table of probabilities, find the number of
;; cupboards that will be adequated for the number of people given.
(define (how-many-cupboards-for-% number-of-people
                                  minimum-%
                                  table-of-probabilities)
  (local [(define possibilities
            (sort (hash-keys table-of-probabilities) <))
          (define (accumulate-trials-probabilities
                   trials
                   accumulated-probabilities)
            (if (empty? trials)
                accumulated-probabilities
                (accumulate-trials-probabilities
                 (rest trials)
                 (update-or-insert-probability
                  accumulated-probabilities
                  (foldl (λ (x y)
                            (+ x y))
                         0 (first trials))
                  (foldl (λ (trial-event probability-of-trial)
                            (* (hash-ref table-of-probabilities
                                         trial-event)
                               probability-of-trial))
                         1.0 (first trials))))))]
         (probability-table->result-with-%-greater-than 
          (accumulate-trials-probabilities
           (cartesian-product (make-list number-of-people possibilities)) (hash))
          minimum-%)))

;; probability-table->result-with-%-greater-than : hash number -> number or false
;; takes a probability table with the accumulated results, adds up then
;; in sequence until it surpasses the threshold. False if there is no it never
;; surpasses the threshold. 
(define (probability-table->result-with-%-greater-than table minimum-%)
  (define (accumulate-result list-of-possibilities
                             acc-probability
                             (last-probability #f))
    (cond ((empty? list-of-possibilities)
           (if (< acc-probability minimum-%) #f last-probability))
          ((> acc-probability minimum-%) last-probability)
          (else (accumulate-result (rest list-of-possibilities)
                                   (+ (hash-ref table
                                                (first list-of-possibilities))
                                      acc-probability)
                                   (first list-of-possibilities)))))
  (accumulate-result (sort (hash-keys table) <) 0))

;; update-or-insert-probability : hash integer number -> hash
(define (update-or-insert-probability table
                                      cupboard-number
                                      probability)
  (hash-update table
               cupboard-number
               (λ (old-probability)
                  (+ old-probability probability))
               0))

(define-test-suite cupboards
  (check-equal? (how-many-cupboards-for-% 4 0.95 probability-of-cupboards) 4)

  (check-equal? (probability-table->result-with-%-greater-than 
                 #hash((0 . 0.1296)
                       (1 . 0.2592)
                       (2 . 0.2808)
                       (3 . 0.1944)
                       (4 . 0.094)
                       (5 . 0.0324)) 0.94)
                4)
  (check-equal? (probability-table->result-with-%-greater-than 
                 #hash() 0.0)
                #f)
  (check-equal? (probability-table->result-with-%-greater-than 
                 #hash((0 . 0.4)
                       (1 . 0.2)) 0.7)
                #f))

(run-tests cupboards)

terça-feira, 7 de dezembro de 2010

Functional Round-Robin scheduler in Common Lisp



A while ago I posted a robin-round tournament scheduler in ruby. Since I am going
through PAIP, I thought to give a functional common lisp version a go.



In my opinion it is more readable and flexible, but I would
attribute that to better design and experience than the
language. But CL's list utilities sure helped.


;;;; round-robin.lisp

(defpackage :round-robin
  (:use :cl :lisp-unit))

(in-package :round-robin)

;; rotate-list-left : (listof X) integer -> (listof X)
(defun rotate-list-left (a-list how-many-moves)
  "rotate the list how-many-moves to the left"
  (if (zerop how-many-moves)
      a-list
      (rotate-list-left (append (rest a-list)
                                (list (first a-list)))
                        (1- how-many-moves))))

;; make-matches : (listof X) -> (listof X)
(defun make-matches (players)
  (if (null players)
      nil
      (cons (cons (first players)
                  (last players))
            (make-matches (butlast (rest players))))))

;; print-matches : (listof (listof X)) -> nil
(defun print-matches (matches)
  (if (null matches)
      nil
      (progn
        (let ((current-match (first matches)))
          (print (format nil "~a against ~a!"
                         (first current-match)
                         (second current-match))))
        (print-matches (rest matches)))))



;; round-robin : (listof X) -> nil
(defun round-robin (players)
  "prints matches in round robin fashion"
  (defun do-matches (full-list-of-players
                     max-number-of-rounds
                     current-round)
    (if (>= current-round max-number-of-rounds)
        nil
        (progn (print-matches
                (make-matches
                 (cons (first full-list-of-players)
                       (rotate-list-left (rest full-list-of-players)
                                         current-round))))
               (do-matches full-list-of-players
                 max-number-of-rounds
                 (1+ current-round)))))
  (let ((full-list (if (zerop (mod (length players) 2))
                       players
                       (append players (list 'DUMMY)))))
    (do-matches full-list (length full-list) 1)))

(define-test round-robin-utilities
  (print-matches '((a f) (b e) (c d))) ;; check output
  (assert-equal (rotate-list-left '(a b c d e f g h) 3)
                '(d e f g h a b c))
  (assert-equal (make-matches '(a b c d e f))
                '((a f) (b e) (c d))))

(define-test round-robin
  (print "Even number of players")
  (round-robin '(a b c d))

  (print "Odd number of players")
  (round-robin '(a b c d e)))

(run-tests)



quinta-feira, 2 de dezembro de 2010

A small view on the history of programming and personal computing

I have just finished a draft of an article that I wanted to write for some time:

A small view on the history of programming and personal computing

Here is a copy of the abstract:

Those who cannot remember the past are condemned to repeat it.
Because programmers usually think they deal with cutting edge tech-
nology, they tend to forget the age and genealogy of the ideas they
are working with. A demonstration of the history of the some crucial
ideas of the programming craft would avoid the repetition of error and
allow better ideas to take hold.

Suggestions and feedback are more than welcome.

terça-feira, 26 de outubro de 2010

Ruby arrays and mutation

Recently I had to develop a robin round [1] scheduler in ruby. After
you understand the process, it is a simple algorithm:



module RoundRobin
  # generate : (arrayof numbers) -> [arrayof [arrayof [arrayof numbers]]]
  def self.generate(list_of_elements)
    # if there is an odd number of players, add a dummy player, represented by nil
    list_of_elements = list_of_elements.size % 2 == 0 ? list_of_elements : list_of_elements << nil 
    list_size = list_of_elements.size
    elements = []
    # fixes an element, in this case I am taking the first one
    # by convinence
    fixed_element = list_of_elements.delete_at(0)
    
    (list_size-1).times do
      rotate(list_of_elements)
      pairs = []
      (0..(list_size/2 -1)).each do |element_number|
        if element_number == 0
          pairs << [fixed_element, list_of_elements[-element_number-1]]
        else
          pairs << [list_of_elements[element_number-1], list_of_elements[-element_number-1]]
        end
      end
      elements.insert(0, pairs)
    end
    elements
  end

  def self.rotate(list)
    first_element = list[0]
    list.shift
    list << first_element
  end
end


require 'test/unit'
require 'round_robin.rb'


class TestRoundRobin < Test::Unit::TestCase
  def test_simple
    @to_3_result = [[[1,nil], [2,3]],
                    [[1,3], [nil,2]],
                    [[1,2], [3,nil]]]

    @to_6_result = [[[1, 6], [2, 5],[3, 4]],
                    [[1, 5], [6, 4],[2, 3]],
                    [[1, 4], [5, 3],[6, 2]],
                    [[1, 3], [4, 2],[5, 6]],
                    [[1, 2], [3, 6],[4, 5]]]
    
    assert_equal(@to_3_result, RoundRobin.generate([1, 2, 3]))
    assert_equal(@to_6_result, RoundRobin.generate([1, 2, 3, 4, 5, 6]))
  end
end



The only reason I'm writing about it is to compare with the usual
functional style and its contrasts with the style that I wrote this in
ruby.

The Array class of ruby does not guide me into a mutation-free style. It tries
very hard to change the array in place, and the result is the code
ends up imperative if one is not very careful. I wasn't.

The conclusion?

We shape our tools and thereafter our tools shape us. [2]


[1] Round-robin tournament
[2] Understanding Media: The Extensions of Man

sexta-feira, 15 de outubro de 2010

Serendipity, languages, YACC and robots!




While I was playing around with a particular problem this week, a
small discovery led me to a major design fix for the solution I had
developed. Here I will tell you this story because it is not only
about coding, but about inspiration, and its many sources.

The problem was the following:


You will have to trace the steps of a robot to determine its final
commands in the following language:


L - turn 90 degrees left
R - turn 90 degrees right
M - move forward
T - transport to a given location

The commands will be given as such:



10 10 # board size
2 5 N # initial location and the direction the robot is facing
LLRRMMMRLRMMM # series of moves
T 1 3 # transport to position x=1 y=3
LLRRMMRMMRM # another series of moves


Summing up, it is a small textual logo.


My approach to the problem was basically to draft the structures I
would need, in a semi object oriented approach (old-habits). Much like
the following(the first version is in portuguese):


;; tabuleiro é uma estrutura contendo um par de inteiros
(define-struct tabuleiro (x y) #:transparent)

(define-struct robo (x y direção) #:transparent)

;; constrói-tabuleiro : string -> tabuleiro
(define (constrói-tabuleiro dados)
  (let ([dados-do-tabuleiro (string-tokenize dados)])
    (make-tabuleiro (string->number (first dados-do-tabuleiro))
                    (string->number (second dados-do-tabuleiro)))))

;; constrói-tabuleiro : string -> tabuleiro
(define (constrói-robo dados)
  (let ([dados-do-robo (string-tokenize dados)])
    (make-robo (string->number (first dados-do-robo))
               (string->number (second dados-do-robo))
               (string-ref (third dados-do-robo) 0))))



All was going pretty smooth. I had defined some structures, later
the functions that mapped to the commands in the mini logo:


(define DIREÇÕES-POSSIVEIS
  (list '(#\N (#\W #\E))
        '(#\W (#\S #\N))
        '(#\S (#\E #\W))
        '(#\E (#\N #\S))))

(define RESULTADO-DO-PASSO-A-FRENTE
  (list (list #\N (list (λ (n) n) add1))
        (list #\W (list sub1 (λ (n) n)))
        (list #\S (list (λ (n) n) sub1))
        (list #\E (list add1 (λ (n) n)))))

;; muda-direção : robo char -> robo
(define (muda-direção o-robo virar-para)
  (let ([possíveis-direções
         (second (findf (λ (uma-possibilidade)
                          (equal? (first uma-possibilidade)
                                  (robo-direção o-robo)))
                        DIREÇÕES-POSSIVEIS))])
    (struct-copy robo
                 o-robo
                 (direção (if (equal? virar-para #\L)
                              (first possíveis-direções)
                              (second possíveis-direções))))))


;; muda-posição : robo number number -> robo
(define (muda-posição o-robo x y)
  (struct-copy robo
               o-robo
               (x x)
               (y y)))

;; passo-a-frente : robo -> robo
(define (passo-a-frente o-robo)
  (let ([possíveis-funções
         (second (findf (λ (um-resultado-de-uma-posição)
                          (equal? (first um-resultado-de-uma-posição)
                                  (robo-direção o-robo)))
                        RESULTADO-DO-PASSO-A-FRENTE))])
    (muda-posição o-robo
                  ((first possíveis-funções) (robo-x o-robo))
                  ((second possíveis-funções) (robo-y
  o-robo)))))

That also went ok. But the problem was parsing the language. I did
my own ad-hoc parser, but as I was building it, the felling of
suspicion was growing and my faith in my approach diminishing. Take
a look at the final product:


  
;; ler-movimentos-do-robo : input-port robo tabuleiro -> robo
;; le e modifica a posição do robo a partir de uma lista de movimentos
(define (ler-movimentos-do-robo arquivo
                                (o-robo #f)
                                (o-tabuleiro #f))
  (let* ([linha-de-comandos (read-line arquivo 'any)])
    (if (eof-object? linha-de-comandos)
        o-robo
        (let ([elementos-da-linha (string-tokenize linha-de-comandos)])
          (case (length elementos-da-linha)
            [(3)
             (if (equal? (first elementos-da-linha) "T")
                 (ler-movimentos-do-robo arquivo
                                         (muda-posição
                                          o-robo
                                          (string->number (second
                                                           elementos-da-linha))
                                          (string->number (third
                                                           elementos-da-linha)))
                                         o-tabuleiro)
                 (ler-movimentos-do-robo arquivo
                                         (constrói-robo linha-de-comandos)
                                         o-tabuleiro))]
            [(2) (ler-movimentos-do-robo arquivo
                                         o-robo
                                         (constrói-tabuleiro linha-de-comandos))]
            [else
             (ler-movimentos-do-robo arquivo
                                     ; cria um novo robo pra cada comando da linha
                                     (string-fold
                                      (lambda (comando velho-robo)
                                        (if (equal? comando #\M)
                                            (passo-a-frente velho-robo)
                                            (muda-direção velho-robo comando)))
                                      o-robo
                                      linha-de-comandos)
                                     o-tabuleiro)])))))

Big, butt-ugly, hard to read and maintain. Something was wrong
and I wasn't really sure what. Then serendipity struck me in the
form of
this message. Lex
and YACC, of course! It took me a couple of hours to learn Racket's
syntax for it, but I ended up with a lexer and a parser for the
mini logo, in a version that was much more friendly and elegant.



(define-tokens value-tokens (NUMBER
                             DIRECTION
                             FUNCTION
                             COMMANDS))

(define-empty-tokens op-tokens (EOF NEWLINE))

(define-lex-abbrevs
  (teleport     #\T)
  (turn-left    #\L)
  (turn-right   #\R)
  (move-forward #\M)
  (directions (:or #\N
                   #\S
                   #\E
                   #\W))
  (digit        (:/ #\0 #\9)))

(define mech-lexer
  (lexer
   [(eof) 'EOF]
   [#\newline (token-NEWLINE)]
   ;; recursively call the lexer on the remaining input after a tab or space.    
   ;; Returning the result of that operation.  
   ;; This effectively skips all whitespace.
   [#\space (mech-lexer input-port)]
   [directions (token-DIRECTION (string-ref lexeme 0))]
   [(:+ (:or turn-right turn-left move-forward))
    (token-COMMANDS
     (map (λ (command)
             (get-consequences COMMAND-LOOKUP-TABLE command))
          (string->list lexeme)))]
   [teleport (token-FUNCTION (string-ref lexeme 0))]
   [(:+ digit) (token-NUMBER (string->number lexeme))]))

;; mech-parser : (X -> token) board mech -> mech
(define (mech-parser gen
                     (board #f)
                     (mech #f))
  ((parser
    (start start)
    (end EOF NEWLINE)
    (tokens value-tokens op-tokens)
    (error (λ (tok-ok? tok-name tok-value)
              (error 'lexer
                     (format
                      (if (false? tok-ok?)
                          "the token ~a with value ~a was invalid."
                          "unknow error with token ~a with value ~a")
                      tok-name
                      tok-value))))
    
    (grammar
     (start [() mech] ;; end our parsing, return the mech structure
            [(exp) $1])
     
     (exp [(NUMBER NUMBER)
           (mech-parser gen
                        (make-board $1 $2)
                        mech)]
          
          [(NUMBER NUMBER DIRECTION)
           (mech-parser gen
                        board
                        (make-mech $1 $2 $3))]
          
          [(FUNCTION NUMBER NUMBER)
           (with-handlers ((string? (λ (message)
                                       (display message)
                                       (mech-parser gen
                                                    board
                                                    mech))))
                          (mech-parser gen
                                       board
                                       (jump board mech $2 $3)))]
          
          [(COMMANDS)
           (mech-parser gen
                        board
                        (foldl
                         (λ (command old-mech)
                            (with-handlers ((string? (λ (message)
                                                        (display message)
                                                        old-mech)))
                                           (command board old-mech)))
                         mech $1))])))
   gen))

(define (process-mech ip)
  (mech-parser (λ () (mech-lexer ip))))


If you want to compare the full versions, take a look at the
github repository. The
version with the cleaner Lexer/Parser are called 'mech' instead of
'robo'.
Until next time!