Personal tools
You are here: Home



 
Showing blog entries tagged as: comunidade

A prova do GDD, em Lisp

Outro dia assisti a uma palestra sobre Hadoop e MapReduce. Todos os exemplos foram dados em um pseudocódigo que misturava Ruby com JavaScript enquanto, na minha cabeça, eu os re-escrevia de um jeito que funcionassem de verdade em Python (eu trabalho com isso). Como no meu último post eu já resolvi a provinha do Google Developer Day usando Python (e usei uma função anônima e um filter, vejam só), eu fiquei com a coceira enorme de refazer essas perguntas com Lisp (já que ela expressa maps e reduces como ninguém mais).

No meu laptop eu tenho uns 4 dialetos de Lisp diferentes (não existe uma "implementação canônica" como no caso de Python ou Ruby). Para brincar aqui, eu escolhi Clojure. Clojure é um dialeto de Lisp que roda sobre a máquina virtual do Java (Java é o COBOL do século XXI e provavelmente do XXII, mas a VM e toda a infra-estrutura dela são muito legais). Outro motivo é que o meu Emacs (o IDE to rule them all) está ligado ao Clojure pelo Slime. Eu instalei ambos (Clojure e Slime) com o ELPA, o gerenciador de add-ons do Emacs e, com uma gambiarra e dois symlinks, estou usando o Clojure 1.2 em vez do 1.1 (que é a versão que o ELPA oferece por hora). Eu podia ter tentado usar o Emacs Lisp (o Emacs é quase todo escrito em Emacs Lisp e um REPL dele está sempre disponível), mas ele não é nem um Lisp moderno, nem particularmente gostoso de usar. Podia ter usado Scheme (e provavelmente o resultado seria mais elegante), mas achei que, por rodar na JVM, Clojure é mais "sexy". Qualquer coisa que evite que alguém tenha que escrever código em Java é uma Coisa Boa que merece ser incentivada.

Aqui cabe uma observação: várias linguagens - Scala, Jython, JRuby - permitem que seus programas rodem dentro de máquinas virtuais Java. Todas elas permitem, também, que você use classes que fazem parte tanto do Java propriamente dito como de outros programas nos quais você talvez precise adicionar alguma funcionalidade. A produtividade individual de um desenvolvedor experiente usando uma linguagem como Python e Ruby (dos quais Jython e JRuby são dialetos) já foi observada como sendo superior à de um desenvolvedor igualmente experiente usando Java. Em outras palavras: se você está usando Java você devia dar uma olhada em linguagens mais produtivas.

E isso vale para C#/.NET. Ninguém deveria usar essas tranqueiras.

A propósito, se você quiser ver a resolução da provinha em Jython, vá à outra versão do artigo. É absolutamente a mesma coisa.

Voltando à prova, resolvê-la deu um pouco de trabalho, provavelmente porque eu ainda estou começando a aprender Clojure (o Clojure Programming/Examples/Cookbook e o livro Programming Clojure, de Stuart Halloway tem ambos sido companhia constante aqui - e são bons mesmo como uma introdução ao Lisp - e o The Joy of Clojure é o próximo no wish-list, para assim que estiver pronto) e porque lembro muito pouco de outros dialetos de Lisp (e o pouco que eu lembro, parece, mais atrapalha do que ajuda).

Aviso muito importante: Eu disse isso acima, mas preciso repetir: estou aprendendo Clojure. Posso ter feito alguma barbaridade sem saber. Mais: não fiz qualquer tentativa de otimizar o código exceto para concisão e legibilidade. Também não fiz TDD. E, por favor, não considere meu estilo pessoal como algo que seja bem-vindo (ou mesmo socialmente aceito) entre programadores Lisp ou Clojure. Aceite meus conselhos por sua conta e risco e não me culpe de nada.

Agora que você foi adequadamente avisado, vamos à provinha:

1) O que esse programa faz?

x = 7
y = 4
if y > 2, then
   y = y * 2
else
   x = x * 2
print (x + y)

No REPL do Clojure, eu fiz assim:

user> (def x 7)
#'user/x
user> (def y 4) 
#'user/y
user> (if (> y 2) (def y (* 2 y)) (def x (* 2 x)))
#'user/y
user> (+ x y)
15

O programa do exercício imprime "15".

2) Quantas vezes esse programa imprime "hello"?

Na linguagem do exercício os loops incluem as extremidades.

for i = 1 to 5
   if i != 2, then
      for j = 1 to 9
         print 'hello'

Vou fingir que, de olhar o pseudocódigo, não dá pra sacar que o programa roda 4 vezes o loop interno e imprime "hello" 36 vezes.

Em Clojure, não temos loops como em Python (ou C, ou quase qualquer outra linguagem desse time). Vamos usar uma list comprehension com o efeito colateral de imprimir coisas na tela.

(for [
        i (range 1 6) 
        j (range 1 10)
     ] 
     (if (not= i 2) 
         (println "hello")
     )
)

Ou, de um jeito um pouco mais Clojure, usando a cláusula ":when" no binding dos ranges no lugar do "jeito C de fazer" com o if dentro do bloco:

(for [
      i (range 1 6) 
      j (range 1 10)
      :when (not= i 2) 
      ] 
  (println "hello")
  )

Executando isso no REPL, ele vai imprimir os "hello"s (como o exemplo em Python fez) entrecortados pelo retorno da list comprehension (que o Python não fez) e isso é chato de contar (ainda mais chato do que o exemplo do Python). Do mesmo jeito que eu fiz com Python, eu vou usar um contador. Como o Clojure abraça a idéia de programação sem efeitos-colaterais e memória transacional, você precisa envolver a coisa cujo estado você pretende alterar em um pouco de burocracia. Famos criar um contador mutável que pode ter seu valor alterado durante a execução do programa.

(def contador (ref 0))

E, com isso, nosso código fica assim:

user> (def contador (ref 0))
(for [
      i (range 1 6)
      j (range 1 10)
      :when (not= i 2)
      ]
  (println (dosync (alter contador inc)) "hello")
  )

A função "dosync" cuida da transação (eu poderia alterar várias variáveis de uma vez) e "alter" faz a alteração propriamente dita do dado que está na referência "contador". "dosync" nos devolve o resultado da última coisa que ele fez, que foi incrementar o contador. Agora, na janela do REPL, vemos algo como:

32 hello
33 hello
34 hello
35 hello
36 hello
nil nil nil nil nil nil nil nil nil nil)
user>

Que é exatamente o que nós queríamos. Agora sabemos que o programa imprime "hello" 36 vezes. Se tivéssemos compilado o programa e o executado a partir de um shell, não veríamos os "nil"s (que só são mostrados pelo REPL porque são o retorno de da função println agrupados pelo for - que retorna uma lista com os resultados).

Poderíamos ter sido mais espertos e simplesmente contado o comprimento da lista que o for nos deu (o monte de "nil"s que atrapalha a leitura da nossa saída), mas isso é para o próximo exercício.

3) Quais números, entre 5 e 2675 são pares e divisíveis por 3?

O exercício diz que eu posso escrever um programa para isso. Eu não fiz isso com Python e ainda não preciso fazer isso com Lisp. Tenho uma pontinha de dó de quem precisa.

user> (count (for [n (range 5 2676) :when (and (= (mod n 3) 0) (even? n))] n))
445

Que foi porco da primeira vez e continua porco agora. Quem leu o primeiro post (ou estava acordado no ginásio) sabe que se um número é par e divisível por 3, ele é divisível por 6. Assim, podemos usar o mesmo truque que usamos com Python na nossa solução:

user> (count (for [n (range 5 2676) :when (= (mod n 6) 0)] n))
445

Eu só sinto saudade da função "even?" da primeira implementação. É legal.

4) Números bonitos

A pergunta nos apresenta Barbara e seus critérios para que números sejam ou não bonitos. Para ela, números são bonitos se contiverem um dígito 4 e não contiverem um dígito 9. Ao final, nos pergunta quais números entre 14063 and 24779, inclusive, são bonitos.

Agora eu vou usar um pedaço do Clojure que não vem carregado, mas que é muito útil: uma biblioteca de manipulação de strings. Para usá-la, vamos fazer:

user> (use 'clojure.contrib.string)
WARNING: repeat already refers to: #'clojure.core/repeat in namespace: user,
 being replaced by: #'clojure.contrib.string/repeat
WARNING: butlast already refers to: #'clojure.core/butlast in namespace: user, 
being replaced by: #'clojure.contrib.string/butlast
WARNING: reverse already refers to: #'clojure.core/reverse in namespace: user, 
being replaced by: #'clojure.contrib.string/reverse
WARNING: get already refers to: #'clojure.core/get in namespace: user, 
being replaced by: #'clojure.contrib.string/get
WARNING: partition already refers to: #'clojure.core/partition in namespace: user, 
being replaced by: #'clojure.contrib.string/partition
WARNING: drop already refers to: #'clojure.core/drop in namespace: user, 
being replaced by: #'clojure.contrib.string/drop
WARNING: take already refers to: #'clojure.core/take in namespace: user, 
being replaced by: #'clojure.contrib.string/take
nil

Os warnings dizem que ela mudou o comportamento de algumas coisas que já estavam disponíveis. Não se preocupe com isso: só queremos a função "substring?". Agora, para saber quantos são bonitos, vamos começar com uma função que decide se um número é bonito ou não:

user> user> (defn bonito? [x]
        (and
         (substring? "4" (str x))
         (not(substring? "9" (str x)))
         ))
#'user/bonito?

Por favor, ignore que eu converti x duas vezes para uma string. Eu otimizo para legibilidade. Outra coisa: eu poderia ter usado .indexOf diretamente ou usá-lo para fazer meu próprio "substring?", mas como clojure.contrib é parte do Clojure, eu acho melhor não duplicar o que é parte do pacote.

Agora temos um "bonito" no nosso namespace. Vamos testá-la, para ver se  fizemos tudo direito:

user> (bonito? 4)
true
user> (bonito? 9)
false
user> (bonito? 49)
false
user> (bonito? 1941)
false

Daí, basta aplicá-la usando a mesma técnica que usamos no problema anterior:

user> (count (for [
           n (range 14063 24780) 
           :when (bonito? n)]
           n))
3047

Se você preferir, pode dispensar a função:

user> (count (for [
           n (range 14063 24780) 
           :when (and (substring? "4" (str n)) 
                      (not(substring? "9" (str n)))) ]
           n))

E tem um jeito ainda mais curto, usando a função "filter".

user> (count (filter bonito? (range 14063 24780)))
3047

E, se eu quiser tornar a coisa um pouco mais obscura usando uma função anônima:

user> (count (filter (fn [n] (and (substring? "4" (str n))
                             (not(substring? "9" (str n))))) 
                     (range 14063 24780)))
3047

Apesar das aparências, funções anônimas não existem para atrapalhar a legibilidade do seu código mas para que você possa construí-las somente quando necessário e passá-las como parâmetro para outras funções que vão fazer coisas com elas.

5) Os telefones

A última pergunta nos apresenta um país em que os números de telefone têm 6 dígitos. Números não podem ter dois dígitos consecutivos idênticos, porque isso é caído. A soma dos dígitos tem de ser par, porque isso é legal e o último dígito não pode ser igual ao primeiro, porque isso dá azar.

Vamos começar com os caídos. Ao contrário do nosso exemplo em Python, eu preciso me preocupar com os limites dos índices. (nth "abcdef" -1) não é aceitável em Clojure.

user> (defn caido? [n] 
        (some true? (for 
                     [i (range (- (count (str n)) 1))]
                     (= (nth (str n) i) (nth (str n) (+ 1 i)))
                     )))
#'user/caido?

Camos fazer alguns testes para ver se estamos encontrando números caídos:

user> (caido? 123456)
nil
user> (caido? 122345)
true
user> (caido? 123451)
nil

Observe que, ao contrário da solução em Python (que tem um bug, aliás) a função que identifica números caídos não identifica números que não são caídos mas que dão azar como se fossem caídos.

Vamos precisar, então, escrever uma função para os que dão azar. Essa é fácil:

user> (defn da-azar? [n]
        (= (first (str n)) (last (str n))))
#'user/da-azar?

Só para ter certeza do que fizemos:

user> (da-azar? 123456)
false
user> (da-azar? 623456)
true
E, finalmente, uma para os números legais:
user> (defn legal? [n] 
        (even? 
         (reduce + 
                  (map (fn [s] (Integer/parseInt s)) 
                       (for [c (str n)] (str c))))))
#'user/legal?

Aqui eu preciso dizer uma coisa: tem que existir um jeito melhor de invocar o método estático parseInt de Integer. Essa cicatriz entre o lado Lisp e o lado Java está muito feia.

Voltando ao exercício, vamos testar nossa função para termos certeza de que não fizemos nada errado:

user> (legal? 12)
false
user> (legal? 55)
true
Com as três na mão, basta usarmos duas no nosso critério:
user> (count (for [n (range 100000 1000000)
           :when (and (legal? n)
                      (not (da-azar? n))
                      (not (caido? n)))]
           n))
238500

Mas o exercício não perguntou quantos caídos entre 100000 e 999999. Eles nos deu uma lista. Com um pouco de mágica de clipboard, colocamos os números em uma string, que quebramos e fazemos uma lista:

user> (def tudo "214966
215739
220686
225051
225123
(...)
720202
720568
720576
")
#'user/tudo
user> tudo
"214966\n215739\n220686\n225051\n225123\n...720202\n720568\n720576\n"
user> (def numeros (split-lines tudo))
#'user/numeros
user> numeros
("214966" "220686" "225051" "225123"..."720202" "720568" "720576")
user> (count numeros)
200

Então, usamos a lista e chegamos no resultado:

user> (count (for [n numeros
           :when (and (legal? n)
                      (not (da-azar? n))
                      (not (caido? n)))]
           n))
61

61 de 200 é o resultado que tivemos antes. Se erramos, erramos duas vezes do mesmo jeito.

Não doeu tanto assim, doeu?

Muitos programadores morrem de medo de Lisp. Morrem de medo, vêm um monte de parênteses, acham confuso e desistem. Lisp é uma linguagem muito interessante - a mais antiga ainda em uso - e impõe uma certa disciplina que é útil para qualquer programador. Robert "Uncle Bob" Martin recomenda que todo programador profissional aprenda uma linguagem "diferente" das que conhece por ano. A analogia que ele faz é interessante: um carpinteiro que só sabe fazer banquinhos de pinho não é um bom carpinteiro. Ele precisa aprender a trabalhar com outros tipos de madeira e a fazer outros tipos de móvel.

Se tudo o que você sabe fazer são sites em PHP ou módulos de ERP em C#, talvez seja hora de pensar em aprender algo novo.

Read More…

A "provinha" do Google Developer Day

Algumas pessoas acharam estranho o processo de inscrição para o Google Developer Day. Nas edições anteriores, você preenchia um formulário, contava o que você fazia e onde trabalhava e ficava nisso. Os primeiros a se inscreverem iriam ao evento e pronto. Os menos atentos ganhavam a lista de espera. Agora, além do formulário, você tem que mandar um currículo e resolver alguns problemas que exigem familiaridade com alguma ferramenta de programação.

Não sei se foi essa a intenção da Google, mas, com esse processo de inscrição, eles têm seus dados de contato, seu currículo e sua avaliação em uma prova.

Mas não se anime. Essa prova não deve ser a que o RH do Google usa. Eu, pessoalmente, acredito que ela apenas existe para separar quem vai entender alguma coisa do GDD de quem não vai entender nada e evitar, com isso, que gente que poderia melhor aproveitar o evento fique de fora.

Agora que as inscrições foram fechadas e o prazo para a entrega das provas terminou, eu me sinto à vontade para publicar esse post.

A prova

A prova tem 5 questões, um pouco diferentes para cada candidato. Eu não sei se foi honesto, mas eu resolvi as minhas com uma janela e um interpretador Python do lado. E eu vou fazer o mesmo aqui.

O que esse programa faz?

x = 7
y = 4
if y > 2, then
   y = y * 2
else
   x = x * 2
print (x + y)

Esse é facil. Na janela do ipython:

In [1]: x = 7

In [2]: y = 4

In [3]: if y > 2:
   ...:     y = y * 2
   ...: else:
   ...:     x = x * 2
   ...:     
   ...:     

In [4]: x + y
Out[4]: 15

Quantas vezes esse programa imprime "hello"?

Uma observação: os loops incluem as extremidades.

for i = 1 to 5
   if i != 2, then
      for j = 1 to 9
         print 'hello'

De novo, com o mesmo truque (só que em Python, o range não inclui a extremidade maior):

In [1]: for i in range(1, 6):
   ...:     if i != 2:
   ...:         for j in range(1, 10):
   ...:             print 'hello'
   ...:             
   ...:             
hello
hello
hello
hello
...

Erm... Chato assim. Vamos tentar de outro jeito

In [1]: linha = 1

In [2]: for i in range(1, 6):
   ...:     if i != 2:
   ...:         for j in range(1, 10):
   ...:             print linha, 'hello'
   ...:             linha += 1
   ...:             
   ...:             
1 hello
2 hello
3 hello
4 hello
(...)
36 hello

Agora sim. Mesmo sem o computador, de olhar dá pra sacar que o primeiro loop roda 5 vezes e o segundo, 9. Como a condição que pula o segundo loop pula uma iteração (nem todos os testes fazem isso), o programa imprime 4 x 9 hello's.

Quais números, entre 5 e 2675 são pares e divisíveis por 3?

O exercício diz que eu posso escrever um programa para isso. Deve ser pra acomodar o pessoal que não vive sem um compilador.

In [1]: len([ n for n in range(5, 2676) if n % 2 == 0 and n % 3 == 0 ])
Out[1]: 445

Mas isso foi porco. Quem estava acordado no ginásio vai lembrar que se um número é par (divisível por 2 - essa é do primário) e divisível por 3, ele é divisível por 6. Assim, podemos simplificar nossa solução:

In [2]: len([ n for n in range(5, 2676) if n % 6 == 0 ])
Out[2]: 445

Podemos respirar aliviados agora que vimos que o resultado continua o mesmo.

Números bonitos

A pergunta nos apresenta Barbara e seus critérios para que números sejam ou não bonitos. Para ela, números são bonitos se contiverem um dígito 4 e não contiverem um dígito 9. Ao final, nos pergunta quais números entre 14063 and 24779, inclusive, são bonitos.

Para saber quantos são bonitos, podemos começar com uma função:

In [1]: def bonito(x):
   ...:     return '4' in str(x) and '9' not in str(x)
   ...:

E podemos testá-la, para ver se  fizemos tudo direito:

In [2]: bonito(4)
Out[2]: True

In [3]: bonito(9)
Out[3]: False

In [4]: bonito(49)
Out[4]: False

In [5]: bonito(1491)
Out[5]: False

Daí, basta aplicá-la usando a mesma técnica que usamos no problema anterior:

In [6]: len([ n for n in range(14063, 24780) if bonito(n) ])
Out[6]: 3047

Se você preferir, pode fazer tudo em uma linha:

In [7]: len([ n for n in range(14063, 24780) if '4' in str(n) and '9' not in str(n) ])
Out[7]: 3047

Ou, ainda:

In [8]: len(filter( lambda x: '4' in str(x) and '9' not in str(x), range(14063, 24780)))
Out[8]: 3047

Os telefones

A última pergunta nos apresenta um país em que os números de telefone têm 6 dígitos. Números não podem ter dois dígitos consecutivos idênticos, porque isso é caído. A soma dos dígitos tem que ser par, porque isso é legal e o último dígito não pode ser igual ao primeiro, porque isso dá azar.

Vamos começar com os caídos

In [1]: def caido(x):
   ...:     for i in range(0, len(str(x))):
   ...:         if str(x)[i] == str(x)[i - 1]:
   ...:             return True
   ...:     return False
   ...:

Agora vamos para os legais

In [2]: def legal(x):
   ...:     return sum([ int(n) for n in str(x) ]) % 2 == 0
   ...:

E, se olharmos a função "caido", vamos ver que ela considera caídos os números que dão azar.

In [3]: caido(123451)
Out[3]: True

Assim, basta usarmos duas no nosso critério:

In [4]: len([ n for n in range(100000, 1000000) if not caido(n) and legal(n) ])
Out[4]: 238500

Mas o exercício não perguntou quantos caídos entre 100000 e 999999. Eles nos deu uma lista. Com um pouco de mágica de clipboard, colocamos os números em uma string, que quebramos e fazemos uma lista:

In [5]: tudo = '''214966
   ...: 215739
   ...: 220686
   ...: 225051
   ...: 225123
   ...: 226810
   ...: 228256
(...)
   ...: 720576
   ...: '''

In [6]: tudo
Out[6]: '214966\n215739\n220686\n225051\n225123\n...720202\n720568\n720576\n'

Opa! Tem um '\n' no final do qual precisamos nos livrar

In [7]: numeros = tudo.split('\n')[:-1]

In [8]: len(numeros)
Out[8]: 200

Então, usamos a lista e chegamos no resultado:

In [9]: len([ n for n in numeros if not caido(n) and legal(n) ])
Out[9]: 61

61 de 200 parece razoável.

Motivo para pânico?

Não desanime se seus números forem muito diferentes dos meus. Os enunciados variam de teste para teste. Além disso, até agora eu não recebi confirmação da minha inscrição. Isso pode indicar que eu errei tudo.

Boa sorte!

Read More…

Por que você não deve deixar de ir à LinuxCon só por causa do keynote do Sandy Gupta

Os amigos

Muitos amigos meus estão dizendo que não vão à LinuxCon Brazil por conta de um keynote por um representante da Microsoft. Isso me preocupa muito e me preocupou a ponto de eu me decidir a escrever este post

O mentiroso

A Microsoft é uma entidade engraçada. É extremamente consistente e previsível. Joga baixo, sempre que pode. Seus funcionários acreditam, de coração, que está tudo bem e que é normal fazer essas coisas. Se me convidarem pra jogar bola, eu não vou. Devem dar caneladas, cotoveladas e tudo o mais que puderem, desde que acreditem que vão ficar impunes.

Sandeep Gupta veio da SCO. Foi ele o cara (eu pensei em usar "mané", mas ele sabia muito bem o que estava fazendo) que anunciou (PDF) que havia código do Unix no Linux. Eu escrevi sobre isso há muito tempo - desde então se provou que o Linux não tem código Unix nele e que a SCO não tinha nenhum direito sobre o código que ela dizia ser dela que ela dizia que foi parar (e não foi) dentro do Linux. Lá ele chegou a ser presidente da SCO Operations, seja lá o que fosse que ela operasse.

Muita gente suspeita que a SCO foi apenas um laranja para a Microsoft. A Microsoft tem uma série de coincidências interessantes de executivos que destruíram competidores e que, depois disso, acabaram trabalhando em cargos prestigiosos da empresa. Um que eu me lembro fácil é Rick Beluzzo, que fez com que a HP praticamente abandonasse o desenvolvimento do HP-UX e priorizar servidores Windows, porque, nas palavras dele "NT é o futuro" (em tempo - a divisão de servidores da HP que mais dava lucro era a dos HP-UX, na última vez que eu olhei). Depois da HP ele foi a Silicon Graphics (mais ou menos na época em que a Microsoft comprou a Softimage e estabeleceu o NT como alternativa viável para animação) e que acabou licenciando a preço de banana a tecnologia de aceleração de 3D deles para a Nvidia (que permitiu PCs com performance de 3D similar às SGIs e que enterrou de vez o negócio deles). Depois disso ele foi parar na MSN e deve ter ganho seus vários milhões com isso tudo. A história de Gupta é um paralelo notável e demonstra que, se não a SCO, pelo menos ele esteve a serviço da Microsoft desde o início.

Você contrataria um executivo como ele?

Nem eu.

Mas esse não é o ponto. O homem é um pulha e a Microsoft não é uma empresa ética. Isso não é segredo e nem é a primeira vez que eu digo isso.

O evangelista

James Plamondon era um evangelista da Microsoft. Em uma apresentação, ele explicou como se faz para esvaziar um evento de um competidor - a Microsoft simplesmente aparece no evento. Plamondon, nessa entrevista, se vangloria de ter acabado com duas conferências de desenvolvedores de Mac tornando-as multi-plataforma e impondo tracks com palestras que não interessam a ninguém. Desenvolvedores de software para Mac não querem ir a uma conferência para assistir palestras sobre como escrever software para Windows. Ao impor sua presença, ele espanta conferencistas e, a longo prazo, estrangula a conferência, que morre, aparentemente, de causas naturais. A primeira foi a Mac App Developers Conference, onde ele era membro do board da associação por trás. A segunda foi a Technology and Issues Conference. As duas tiveram uma vida longa antes da Microsoft decidir acabar com elas.

Está tudo aqui. Essa parte que eu mencionei está na página 27, mas o PDF tem 66 páginas de pura maldade (o método que ele usou para entrar na grade de uma conferência é particularmente maligno). Esse pessoal não é só ultra-competitivo. Eles não tem caráter nenhum.

O vilão

Não tenha dúvida de que a Microsoft pagou, direta e indiretamente, para estar na LinuxCon. Mas nós ganhamos com isso. O evento fica melhor no geral, tem mais dinheiro, as entradas podem ser mais baratas e o lanche pode ser melhor. O espaço pode ser mais bem-cuidado, as palestras podem ter mais pessoas. E o preço disso é que temos a oportunidade de ir lá e detonar com o cara no keynote dele. Gente! É o cara da SCO! Melhor que isso só se fosse Bill Gates! Ele vai ser um alvo fácil falando por uma hora. Você pode estar no auditório e, quando ele subir ao palco, sair como forma de protesto (cuidado - ele vai usar a carta da "intolerância" e do "fanatismo" para nos demonizar). Melhor é ficar e crivá-lo com as perguntas mais pontudas e cortantes que puderem imaginar. Se você tiver uma credencial de imprensa, use-a para fazer perguntas na entrevista coletiva. O cara é mau e merece. Simboliza e protagoniza tudo o que existe de mais errado em nosso mercado. Eu lamento profundamente não poder ir pessoalmente dessa vez, mas minha oportunidade de trollá-lo vai chegar.

O que não podemos fazer

Essa parte é muito importante.

Evidentemente, não podemos usar de violência. Eu imagino que também não seja permitido entrar com tortas no auditório. Mais importante do que tudo isso é não deixarmos que a Microsoft esvazie o evento. Se você não aprova e não tem estômago pra ficar ouvindo, vá para o corredor durante o keynote fazer alguma coisa. É uma LinuxCon, afinal. Vá escrever algum código que ajude os outros. Encontre alguém e vá resolver algum problema seu. Deixe que ele fale sozinho sobre a interoperabilidade que a empresa dele não quer. Distribua folhetos, imprima a página 27, traduza, publique em seu blog. Faça algo. Eles vivem da nossa inação.

Mas, mais do que tudo isso, não deixe de ir. O evento e a comunidade a que ele serve não precisam de Guptas e Plamondons.

Precisam de você.

Read More…

They had it all

They had it all

I like to remind my younger peers that technology does not show a steady progression pattern. In the past we can see long forgotten examples of ideas were not only ahead of their time, but that are still ahead of our own. PLATO was such a thing.

In the 70's they had social media, collaborative editing, wide-area multi-user games, hypertext, instant-messaging and e-mail. And they had it in graphic terminals that showed pictures we would not be able to see on a desktop computer until the mid-80s.

They had it all.

Enjoy.

Read More…