5.

Aqueles Que Fazem as Regras e Aqueles Que Vivem o Sonho

[o]

Pelo espaço e tempo... na sua jarra de sino... numa missão para se encontrar...

Francamente, estou cansado de ouvir que o Dr. Cham é louco. Sim, ele tentou se enterrar vivo. Sim, ele eletrocutou sua sobrinha. Sim, é fato, ele explodiu um asilo. Mas tudo isso foi por uma boa causa e, em cada caso, eu acredito que ele tenha tomado a decisão certa.

Tenho certeza que você gostaria de ficar do lado da opinião popular, mas você está prestes a sentir um pequeno comichão de admiração por ele, uma vez que ele te ensine tudo sobre as definições de classe do Ruby. E ainda mais quando você aprender sobre mixins. E talvez, no final do capítulo, nós todos comecemos a olhar além do passado obscuro do Doutor e não mais o chamaremos de louco.

Então, se você quer chamá-lo de louco, eu começaria indo na estação de trem quebrar umas lâmpadas fluorescentes grandes. Tire-o do seu sistema agora, antes de irmos mais além.

1. Esta é para os Desprivilegiados

Algumas pessoas ainda não conseguem acreditar no que fizemos.

Se você me der um número, seja ele qualquer ano da vida do Dr. Cham, darei-lhe uma sinopse do período. E farei isso com um método Ruby. Portanto será uma peça independente, um pedaço de código isolado que pode ser ligado à voz de um vulcão robótico, quando este tipo de coisa for o ápice das vozes competentes e talentosas.

Ok, preciso que você preste atenção nos comandos def , case e when (quando). Você já viu Ranges (Períodos), os acordeões fechados 1895..1913, no capítulo 3. Eles contêm as pontas e todos os números entre. E as barras no final de cada linha simplesmente ignoram o Enter, assegurando ao Ruby que há mais linhas por vir.

Então, por favor: def, case e when.

 def biografia_do_dr_cham( ano )
   case ano
   when 1894
     "Nasceu."
   when 1895..1913
     "Infância em Lousville, Winston Co., Mississippi."
   when 1914..1919
     "Trabalhou em uma creche de nozes-pecãs; socou um quacre de uma seita protestante."
   when 1920..1928
     "Navegou na companhia do Rio Wisdomming, que se juntou \
      ao Rio Mississippi e se engajou em reflexão e auto-aprimoramento, \
      onde ele concluiu 140 horas de crédito para sua Remoniversidade"
   when 1929
     "Voltou à Louisville para escrever um romance sobre camponeses caçadores que viajam no tempo."
   when 1930..1933
     "Ergueu uma respeitável carreira garantindo as creches das nozes-pecãs.  Financeiramente estável, \
      ele passou algum tempo no Brasil e Novo México, comprando raras árvores de noz-pecã de casca \
      fina. Assim que sua notoriedade chegou a um alto patamar: caramba, ele tentou se enterrar vivo."
   when 1934
     "Voltou a escrever seu romance.  Mudou de caçadores para magnatas de seguradoras e \
      de camponeses para protestantes."
   when 1935..1940
     "Recebeu Arthur Cone, o chefe da Irmandade do Rio Wisdomming, em sua residência \
      como hóspede. Juntos por cinco anos, planejaram e inventaram."
   when 1941
     "Aqui as coisas começam a ficar interessantes."
   end
 end

O comando def. Aqui esta nossa primeira definição de método. Um método simples, que pode ser usado em qualquer lugar no Ruby. E como rodamos ele?

 puts biografia_do_dr_cham( 1941 )

Que por sua vez responde “Aqui as coisas começam a ficar interessantes.” É sempre a mesma história: use suas respostas. Eu fiz as coisas ali de tal modo que o case sempre responderá com uma String. E já que o case é o último (e único) comando no método, então o método responderá aquela String. Gotejando água que é derramada de uma saliência para outra.
Permita-me ser mais claro sobre a condição case. Na verdade, eu deveria chamá-la de case..when, já que elas não podem ser usadas separadamente. O comando case é seguido de um valor, que é comparado contra cada valor que segue o comando when. O primeiro valor a coincidir é usado pelo case, o resto é ignorado. Você pode fazer a mesma coisa com um monte de if..elsif, mas isso é muito verborrágico.

 case ano
 when 1894
   "Nasceu."
 when 1895..1913
   "Infância em Lousville, Winston Co., Mississippi."
 else
   "Sem informações sobre este ano."
 end

É a mesma coisa que:

 if 1894 === ano
   "Nasceu."
 elsif 1895..1913 === ano
   "Infância em Lousville, Winston Co., Mississippi."
 else
   "Sem informações para este ano."
 end

Os três iguais (===) são o comprimento da corda de veludo, checando valores de forma similar aos dois iguais (==). Resumindo: os três iguais são uma corda maior e ela desce um pouco no meio. Não é tão tensionada, é um pouco mais maleável.

Veja os períodos assim: (1895..1913) não é nem um pouco igual a 1905. Não, o período (1895..1913) só é realmente igual a qualquer outro período (1895..1913). Os três iguais, no caso de um período, dão uma folga e deixam o número inteiro 1905 entrar, pois mesmo ele não sendo igual ao período, ele está incluído na lista de número inteiros representados pelo período. O que é suficiente em alguns casos, como o da biografia que eu fiz anteriormente.

A qual realmente se parece com uma biografia, não? Quero dizer, claro, o método biografia_do_dr_cham é código, mas ele se parece com uma biografia, clara e afável.

O que a pesquisa revelou.

Mas Estava Ele Doente??

Você sabe, o momento dele era tão ruim. Era um desastre como romancista, mas suas empreitadas na alquimia eram muito promissoras. Ele tinha um elixir de leite de cabra e sal marinho que melhorava dores nas pernas. Um cara até regenerou um pedaço do dedo que havia perdido. Tinha um fumo medicinal orgânico que cheirava chulé mas lhe dava visão noturna. Ele trabalhava em algo chamado Escada Líquida, mas nunca vi ou li nada a respeito. Não pode ser para subir. Quem sabe.

Um jornal local uma vez visitou o Dr. Cham. A crítica literária deles lhe deu quatro estrelas. Sério. Ela fez um artigo sobre ele. Deu-lhe uma avaliação.

Mas saiba que o Dr. N. Harold Cham se sentia muito mal em relação à sua sobrinha. Ele acreditou que o tratamento de choque funcionaria. A pólio a teria matado de qualquer jeito, mas ele tentou.

Em 9 de Setembro de 1941, depois de sedá-la como uma dose de fenacetina na sua sala de operações, ele colocou os clipes condutores no nariz, língua, dedos e ombros de Hannah. Com a ajuda de seu aprendiz, um estudante perspicaz chamado Marvin Holyoake, eles polvilharam a garota com flocos de uma substância que o doutor chamou de opus magnum. Um pó de ouro branco que levaria a corrente e evidentemente energizaria a menina, forçando seu sangue a aflorar e lutar e vencer.

Mas aquilo não deu muito certo, quando a alavanca foi puxada, ela se debateu e chutou — e KABLAM! — e BLOY-OY-OY-KKPOY! Anéis de cabelo e uma parede de luz, e o sino da morte tocou. A experiência sucumbiu em uma estreita pluma de fumaça e a inocência dela (durante semanas, todo mundo só falava: “Ela nunca vai ter a chance de…”) foi um rombo no chão e nos pulmões deles.

Para Hannah, eu programo.

 opus_magnum = true
 def salve_hannah
   sucesso = opus_magnum
 end

Um método em sua própria ilha. E o que vai dentro não é afetado por simples variáveis externas. O Dr. Cham não podia penetrar na doença da sua sobrinha assim como uma variável opus_magnum não pode penetrar no exterior de aço do método.

Se rodarmos o método salve_hannah, o Ruby vai chiar conosco, alegando que não sabe de opus_magnum nenhuma.

Estou falando de foco, escopo. Microscópios restringem e magnificam sua visão. Telescópios estendem seu campo de visão. No Ruby, escopo referencia o campo de visão dentro de métodos e blocos.

A declaração def do método abre sua visão. Nomes de variáveis introduzidos ali serão vistos pelo método e continuarão valendo até que o end feche seus olhos. Você pode passar dados para um método usando argumentos e dados podem ser resgatados do método, mas os nomes usados dentro do método só valem no escopo dele.

Algumas variáveis tem um escopo mais amplo. Variáveis globais, como $LOAD_PATH, que começam com um cifrão estão disponíveis sob qualquer escopo. Variáveis de instância como @nomes, que começam com uma arroba estão disponíveis em todo lugar dentro do escopo da classe. A mesma coisa serve para variáveis de classe como @@@ingressos@. Variáveis de classe e de instância serão exploradas em breve.

Blocos têm escopo, mas ele é um pouco difuso. Mais flexível.

 verbo = 'salvou'
 ['sedou', 'polvilhou', 'eletrocutou'].
 each do |verbo|
   puts "O Dr. Cham " + verbo + " sua sobrinha Hannah."
 end
 puts "Sim, o Dr. Cham " + verbo + " sua sobrinha Hannah."

O bloco itera (circunda, revolve) por cada uma das ações do Doutor. A variável verbo muda a cada passo. Em um passo, ele a está sedando. No próximo, ele está polvilhando-a. E então, eletrocutando.

Então, a questão é: após o término do bloco, terá ele salvado Hannah?

 O Dr. Cham sedou sua sobrinha Hannah.
 O Dr. Cham polvilhou sua sobrinha Hannah.
 O Dr. Cham eletrocutou sua sobrinha Hannah.
 Sim, o Dr. Cham eletrocutou sua sobrinha Hannah.

Os blocos podem ver variáveis da vizinhança. O bloco viu que a variável verbo existia, ele reescreveu o que ela continha e continuou. Quando o bloco acabou e sua pequena vida se esvaiu, a variável verbo saiu de lá uma outra criatura.

Se o bloco usar uma variável que ainda não tenha sido usada previamente, essa variável desaparece após o término do bloco. O escopo do bloco se fecha e a variável vai junto. Aqui um exemplo em que verbo não foi usado antes do bloco:

 ['sedou', 'polvilhou', 'eletrocutou'].
 each do |verbo|
   puts "O Dr. Cham " + verbo + " sua sobrinha Hannah."
 end
 puts "Sim, O Dr. Cham " + verbo + " sua sobrinha Hannah."

Dá um erro: undefined local variable or method 'verbo'. Poof. (Método ou variável local ‘verbo’ não definido.)

Deve ser difícil, mesmo para um grande cientista, sumir com o corpo de uma garotinha cujo vestido ainda está passado e bordado, mas cuja boca está roxa nas extremidades. No jornal do Dr. Cham, ele relata que fora atormentado pelo fantasma dela, que reluzia ouro e cuja renda flamejava. Suas desilusões aumentaram e ele fugiu do Cérberus e de massivas, vingativas mãos angelicais.

Somente semanas mais tarde, ele foi embora, impulsionado por esses arrependimentos, sumindo na explosão que o levaria para fora do planeta.

Ainda enquanto você lê isto aqui, em algum momento, a jarra em formato de sino do nosso solitário Dr. Cham pousou num distante planeta depois de viajar sessenta anos. Assim que o novo mundo apareceu, assim que a curvatura do planeta se mostrou, assim que a jarra em formato de sino varreu os céus tempestuosos, rasgando folhas de aurora e vento solar, os olhos do Dr. Cham se abriram chocados.

Pouso seguro.  Espanto.

O que você esta testemunhando é o pouso do Dr. Cham no planeta Endertromb. Do que eu pude perceber, ele pousou no meio de uma estação desolada, época em que não tem muita coisa acontecendo no planeta. A maioria dos habitantes têm suas mentes presas a um zumbido desanimador que faz com que eles se desintegrem em fantasmas fúteis uma-parte-conhecimento e três-partes-vapor por um tempo.

Meu modesto conhecimento sobre a história e clima de Endertromb foi adquirido convivendo com o professor de piano da minha filha, quem cresceu no planeta.

Maridos mortos poderia destruir o Doutor.

Eu freqüentemente treino o professor de piano da minha filha para assegurar que ele mantenha seus compromissos. Que ele atenda chamadas em horas estranhas e responda chamadas de emergência prontamente. Quando ele finalmente me contou que era um alienígena cujo dia consistia em quinhentas e quarenta horas acordado, eu estava incrivelmente favorável a um relacionamento contratual com ele que durará até 2060.

Por três dias (de acordo com seu relógio de bolso), o Dr. Cham viajou nas escuras passagens de ar, respirando o vento empoeirado daquele planeta árido. Mas no terceiro dia, ele encontrou o término da Estação Desolada e acordou para uma vista magnífica, decorada com recém-floridas árvores de maçã e fileiras de frescos castelos.

2. Um Castelo Tem Seus Computadores

Os vales panorâmicos de Sedna em Endertromb.

Nosso intrépido Doutor partiu para o castelo alienígena, lançando-se sobre as flores. O chão passou por seus calcanhares. O castelo aparecia gradativamente no horizonte. Ele desejava ter um cavalo garanhão, mas nenhum cavalo apareceu. E foi assim que ele descobriu que o planeta não leria sua mente e não responderia seus pedidos.

Porém, como o instrutor de órgão da minha filha havia me explicado, o planeta podia ler mentes e podia realizar desejos. Só que não os dois ao mesmo tempo.

Um dia questionando o maestro de órgão, ele rascunhou o seguinte código Ruby numa folha de papel cor-de-queijo. (E cheiros estranhos de queijo estavam vindo de algum lugar, eu não posso dizer onde.)

 require 'endertromb'
 class FazedorPedidos
   def initialize
     @energia = rand( 6 )
   end
   def realize( pedido )
     if pedido.length > 10 or pedido.include? ' '
       raise ArgumentError, "Pedido ruim."
     end
     if @energia.zero?
       raise Exception, "Sem energia."
     end
     @energia -= 1
     Endertromb::realize( pedido )
   end
 end

Este é o fazedor de pedidos.

Na verdade, não, esta é a definição de um fazedor de pedidos. Para o Ruby, é uma definição de classe. O código descreve como um certo objeto vai funcionar.

Toda manhã, o fazedor de pedidos inicia com até cinco pedidos disponíveis para serem concedidos. Um novo FazedorPedidos é criado quando o sol levanta.

 pedidos_do_dia = FazedorPedidos.new

O método new é um método de classe que cria um novo, objeto em branco. Ele também chama o método initialize (inicializar) do objeto automaticamente. Na definição do FazedorPedidos , você vai ver o método initialize, que contém uma única linha de código: @energia = rand( 6 ).

O rand( 6 ) sorteia um número entre 0 e 5. Este número vai representar quantos pedidos ainda restam no dia. Então, ocasionalmente não haverá pedidos disponíveis do fazedor de pedidos.

O número aleatório é dado à uma variável de instância de nome @energia. Esta variável de instância estará disponível a qualquer momento por toda a classe. A variável não pode ser usada fora do escopo da classe.

No capítulo três, demos uma breve olhada em variáveis de instância e decidimos respeitá-las como atributos. (O símbolo arroba poderia significar atributo.) Variáveis de instância podem ser usadas para guardar qualquer tipo de informação, mas elas são mais usadas para se guardar pedaços de informação sobre o objeto representado pela classe.

No caso acima, cada fazedor de pedidos para o dia tem seu próprio nível de energia. Se o fazedor de pedidos fosse uma máquina, você talvez veria um medidor nele que marca a energia restante. A variável de instância @energia agirá como esse medidor.

 pedidos_do_dia = FazedorPedidos.new
 pedidos_do_dia.realize( "chifres" )

Ok, dê um passo atrás e tenha certeza de entender este exemplo aqui. A classe FazedorPedidos é a base que elaboramos de como toda a mágica dos pedidos funciona. Não é o realmente o gênio na lâmpada, é a papelada por trás das cenas. São as regras e obrigações em que o gênio vive.

É o pedidos_do_dia que é o gênio da lâmpada. E aqui estamos dando um pedido a ser realizado. Nos dê uma galhada, gênio. (Se você realmente arranjar uma galhada neste exemplo, eu nem quero saber. Vá saltitar em campinas verdes com seus amigos.)

No capítulo anterior, o treinamento era: Ruby tem duas metades.

  1. Definindo coisas.
  2. Colocando estas coisas em ação.

O que são as ações no Ruby? Métodos. E agora, você está provando a linguagem de definição interna do Ruby. Definições de métodos usando def. Definições de classe usando class.

Neste ponto da sua instrução, é mais fácil entender que tudo no Ruby é um objeto.

 numero = 5
 print numero.next                 # imprime '6'

 frase = 'desejando por chifres'
 print frase.length                # imprime '19'

 pedidos_do_dia = FazedorPedidos.new
 pedidos_do_dia.realize( "chifres" )

E, consequentemente, cada objeto tem uma classe nos bastidores.

 print 5.class                         # imprime 'Integer'
 print 'desejando por chifres'.class   # imprime 'String'
 print FazedorPedidos.new.class        # imprime 'FazedorPedidos'

Dr. Cham nunca viu o fazedor de pedidos enquanto desbravava a paisagem. Ele ficava bem além das terras dele, no vale de Sedna. Penhascos cheios de porções de bosques, onde você podia jogar seus pedidos (escritos num tirinha 1″ × 6″), dentro do sumidouro. Com sorte ele pousará nas costas de um lagarto, espetando em seu chifrinho pontiagudo dele.

E digamos que seu pedido chegue lá. Bem, então, descendo pela floresta contorcida vai a magra salamandra, correndo através das igrejas descendentes que foram empurradas para a íngreme base do desfiladeiro de uma vez por todas. E o desfalecido padre dentro, que também resistiu a queda, matará o pequeno anfíbio — estrangulando-o até a morte com uma corrente abençoada de ouro — e guardá-lo para as comemorações do Conhecendo Seu café da manhã. Ele pisará no seu pequeno e precioso pedido e, quando os ladrões vierem, aquele papel ainda estará lá, preso na sola do sapato dele. Claro, o meio preferido de tortura dos ladrões é cortar um padre em finíssimas fatias da cabeça aos pés. Quem pode catar evidências disto? E quando eles fatiam a última fatia da sola do sapato, eles terão aquele escalpo de borracha nas mãos para boa sorte e bons tempos. Mas eles canoam com muita força, estes ladrões. Eles batem seus remos rapidamente na corrente para manter o grande vapor do motor externo . Mas a sola de sapato está em uma cadeia fraca, presa ao cinto de um dos homens. E uma velha carpa cabeluda salta, agarra esta fração de minuto de calçado. E os ladrões podem tentar, mas eles não vêem embaixo d’água. Se eles pudessem, eles veriam aquele cabo poderoso, empacotado com milhões de necessariamente fibras ópticas. , esse peixe é um periférico conectado direto ao núcleo de trabalho do planeta Endertromb. Tudo que ele pega é um gole daquele peixe e seu desejo está liberto!

E é assim que os pedidos das crianças se realizam neste lugar.

Uma vez que o instrutor de órgão da minha filha tenha desenhado a classe para o fazedor de pedidos, ele continuou com uma classe para o leitor de mentes do planeta.

 require 'endertromb'
 class LeitorMental
   def initialize
     @mentes = Endertromb::procurar_por_consciencia
   end
   def read
     @mentes.collect do |mente|
        mente.read
     end
   end
 end

Como você já viu antes, o initalize acontece quando um novo (new) objeto LeitorMental é criado. Este initialize rastreia o planeta em busca das mentes. Parece que as mentes estão guardadas em um array, já que há uma iteração nelas no final usando o método collect.

Tanto o fazedor de pedidos e quanto o leitor mental referem-se a uma classe chamada Endertromb. Esta classe está guardada em um arquivo endertromb.rb, que é carregado com o código: require 'endertromb'. Você vai, muitas vezes, usar outras classes para realizar parte da sua tarefa. Boa parte da metade restante deste livro explorará a grande variedade de classes úteis que podem ser carregadas no Ruby.

Dr. Cham Arrisca Entrar

Mas assim que o Dr. Cham se aproximou do castelo, mesmo o planeta sabendo de seus pensamentos, sentindo sua surpresa e antecipação, tudo que Dr. Cham sentiu era a morte. Ele subiu os degraus de seu portão frontal, passou através da entrada de mais bela arquitetura e estava quase certo de que ele estava deserto.

Por um tempo ele bateu na porta. O que foi recompensante.

Baleia parruda saudando.

Ele assistiu ao bebê baleia subir como um balão determinado. Ele se maravilhou com sua primeira introdução alienígena e sentiu alguma preocupação de que ela tenha passado tão rapidamente. Bem, ele iria esperar lá dentro.

Assim que ele entrou pela porta do castelo, sentiu-se com sorte pela porta não ter sido atendida por uma águia gigante com garras afiadas, ávida por brincar. Ou uma cabeça de rato gigante. Ou até mesmo um furacão ou mesmo um furacão do tamanho de um homem. Somente uma pequena baleia choo-choo rechonchuda.

“Nenhum lugar para se sentar neste castelo,” disse ele.

À primeira vista, ele pensou ter entrado em um saguão escuro, mas assim que seus olhos se ajustaram, ele viu que a entrada se estendia em um túnel. A porta do castelo se abriu em uma passagem feita de pedaços longos e planos de rocha. Algumas partes eram harmônicas e lembravam um corredor. Outras partes eram estreitas e até inclinadas, o fim sumia de vista.

A passagem era iluminada por pequenas geladeiras sem portas, grandes o suficiente para guardar uma braçada de repolho, até os seus pés. Ele olhou para dentro de um deles, que estava oco, iluminando por todos os lados, e criando cacos de gelo metodicamente.

Ele tocou nos pedaços de gelo, que grudaram secamente em seus dedos. E ele então esfregou suas mãos no gelo. O que deixou algumas linhas enlameadas em suas mãos, mas satisfez um pouco sua saudade por um banho. Quanto tempo já fazia? Dez anos? Trinta?

Pela passagem, longos tubos de tecido lotavam algumas seções. Mais tarde, matéria de pontos brilhantes em conchas de porcelana e baldes.

Ele caiu em uma sala que havia sido escavada ao lado do túnel e nela haviam alguns cascos de tartaruga vazios no chão e uma grande parede iluminada. Ele examinou a sala, perplexo. O que seria isso? Por um instante, pensou em sentar em um casco. Isto poderia ser a entrada finalmente, algum tipo de sala de recepção. Por outro lado, aranhas poderiam sair dos buracos dos cascos quando ele sentasse. Ele seguiu viagem.

Refeição no Bolso de um Castelo

A medida que continuava sua jornada por entre as passagens (pelo túnel central ramificavam e se juntavam grandes vazias cavernas), ele escolheu temas em algumas localizações. Grupos de salas infestadas com maquinaria de bombeamento. Tecidos e barris de cola dominavam outra área. Ele seguiu vozes que vinham de uma cavidade veludosa e macia como travesseiro, o que o levou para um lugar sem saída: uma parede curvada com uma pequena sala entalhada no nível dos olhos.

Ele se aproximou da parede e, dentro do buraco quadrado, estavam dois porcos-da-terra comendo à mesa.

Eles o encaram serenamente, ambos degustando um pouco de besouros escavados, que davam dois deles, abertos ao meio e parados com as costas na mesa.

“Olá, bonequinhos,” ele disse, e eles terminaram suas mordidas e ficaram olhando com seus garfos segurados à distância.

“Eu queria que minha sobrinha Hannah estivesse aqui para conhecê-los,” disse ele aos atenciosos porcos-da-terra. “Ela pensaria que vocês são um intricado show de ventriloquismo.” Ele olhou para a área da refeição, empilhada como conjuntos de pratos, toalhas de mão. Metade de um pequeno coelho projetava-se do topo da máquina, grãos vermelho cremosos estavam caindo para baixo dele. Uma porta no fundo da sala estava entreaberta. Dr. Cham podia ver uma sala cintilante com cadeiras e motores zunindo através da porta.

“Toda criança gostaria desta casa de bonecas,” ele disse. “Hannah, minha sobrinha, como mencionei, ela tem uma boneca que senta em um fuso e começa a soltar fio. É uma ilusão, é claro. A boneca não produz fio algum.”

Um dos porcos-da-terra abriu um alçapão no chão e pressionou um botão ali, que se iluminou. Então, um pequeno projetor de filme veio lentamente sob trilhos. O outro porco-da-terra sentou e olhou o Dr. Cham.

“Mas Hannah ainda alcança lá no fundo da casa de boneca e pega todos os fios imaginários formando um maço. Que ela leva para sua mãe, minha irmã, que é muito boa em deixar Hannah de bom humor. Ela costura um vestido no tamanho da boneca, o qual Hannah leva até a boneca.”

“E ela diz à boneca, ‘Aqui, olhe, seu trabalho duro e perseverança resultaram neste lindo vestido. Agora você pode aceitar o convite e acompanhar, hoje à noite, o Chefe de Polícia na Mansão do Governador.’ E ela tem uma boneca vestida de policial que faz o papel do Chefe. Ele é muito raquítico para ser o Chefe de verdade, isso precisaria de um bom pedaço de plástico.”

O porco-da-terra responsável pelo projetor o carregou com um rolo e o mirou na parede do fundo. O filme começou e os porcos-da-terra se sentaram. Um quadrado verde apareceu na parede. O atencioso porco-da-terra encarou o Dr. Cham parado.

“Seus filmes são coloridos,” disse o Dr. Cham. “Que vida pequena e amável.”

O filme exibido foi: um quadrado azul. Aí, um círculo vermelho. Aí, um quadrado laranja. Os atenciosos porcos-da-terra se viraram, assistiram a tela virar um triângulo rosa, e ambos porcos-da-terra voltaram a comer.

Uma estrela roxa. Um quadrado vermelho. Com o assentamento do silêncio, Dr. Cham podia escutar notas zumbindo do projetor. Como uma lenta, lerda caixa de som tentando girar suas engrenagens ao longo da linha de trem.

“Sim, aproveitem o jantar,” disse o Dr. Cham e educadamente se virou, marchando de volta no caminho que ele tomara.

Outra Rua Sem Saída Onde as Coisas Começam

Ele se encontrou perdido nos túneis do castelo. Nada parecia familiar. Todavia, ele não estava muito preocupado. Ele estava noutro planeta. Ele estava perdido de qualquer maneira.

Ele se contorceu pelos túneis, tentando lembrar o caminho, mas muito mais interessado em explorar para lembrar seus passos. Ele seguiu um único túnel profundamente, descendo, descendo, ficou tão inclinado que ele tinha que pular entre as beiradas e cuidadosamente achar apoio para os pés. A gravidade aqui não parecia ser diferente da Terra. Ele escorregava com a mesma facilidade.

Mesmo sem ter absolutamente nenhuma maneira de saber onde ele estava, ele tinha certeza de ter saído dos limites do castelo. Esta profundidade, este tanto de caminhada. Já fazia uma hora desde que ele adentrara a porta. E, a medida que voltava no túnel, ele tinha certeza que emergiria em um uma nova habitação, talvez até mesmo um buraco em que ele pudesse espiar para fora e ver o castelo. Talvez ele não devesse ter ido tão longe nessa rota. Ele espera que nada esteja hibernando aqui embaixo.

O túnel chegou ao fim. Um escuro, fim sem saída.

No fim dos túneis: um computador e um livro.

Ele tinha tempo. Então leu o livro. Ele leu sobre os raposos e sua perseguição ao porco-espinho que roubou a caminhonete deles. Ele leu sobre o elfo e o presunto. Ele viu os pictógrafos dele mesmo e descobriu que ele poderia realmente se relacionar com seu próprio esforço. Ele até mesmo aprendeu Ruby. Ele viu como isso tudo termina.

Eu não teria estômago para isso, no lugar dele. Mas ele teve. E jurou em seu âmago que veria as coisas apenas do jeito que elas aconteciam.

No monitor do computador, o Dr. Cham viu o prompt do irb piscando. Assim como o Dr. Cham, você deve reconhecer o prompt do irb do O Colete Do Tigre (o primeiro pacote de expansão deste livro, que inclui uma introdução básica ao IRB – Interactive Ruby.)

Assim como ele acabou de explorar os túneis a pé, agora ele explora as configurações da máquina com o prompt. Ele colocou o livro onde o encontrou. Ele não precisava mais dele. Isto tudo iria acontecer mesmo se ele o usasse ou não.

Ele começou com:

 irb> Object::constants
   => ["Marshal", "String", "Dir", "LoadError", "Float", ... e por aí vai ]

Este comando lista as constantes de nível mais alto. Classes são listadas como constantes também, então esta lista é ótima para ver o que está carregado no Ruby a qualquer momento.

Ele examinou a lista procurando algo não familiar. Qualquer classe que não vem com o Ruby. Marshal, String, Dir, LoadError, Float. Cada uma dessas vêm com o Ruby.

Mas um pouco para baixo na lista:

 ... "Struct", "Values", "Time", "Elevador", "Range" ...

Elevador? Exatamente o tipo de classe a se bisbilhotar. Ele tinha onde ir.

 irb> Elevador::methods
   => ["method", "freeze", "allocate", ... outra lista grande ... ]
 irb> Elevador::class_variables
   => ['@@relatorio_diagnostico', '@@circuito_eletrico_ativo', '@@senha_manutencao']
 irb> Elevador::constants
   => []

Parece que a classe Elevador tem um monte de métodos. A maioria deles parecem ser os mesmos métodos que todo objeto tem no Ruby. Por exemplo, method, freeze e allocate vêm com toda classe no Ruby. (Elevador::freeze não deixaria que a classe Elevador seja alterada. Elevador::allocate criaria um novo objeto Elevador sem chamar o método initialize.)

As class_variables foram interessantes para Dr. Cham. Este elevador parece genuíno. Mas sem constantes disponíveis. Isso nos diz que não há classes aninhadas dentro da classe Elevador.

Ele tentou criar um objeto Elevador.

 irb> e = Elevador::new
 ArgumentError: wrong number of arguments (0 for 1), requires a password
         from (irb):2:in `initialize'
         from (irb):2:in `new'
         from (irb):2
         from :0

Ele tentou algumas senhas.

 irb> e = Elevador::new( "para cima" )
 AccessDeniedError: bad password
 irb> e = Elevador::new( "subindo" )
 AccessDeniedError: bad password
 irb> e = Elevador::new( "escadas_sao_terriveis" )
 AccessDeniedError: bad password
 irb> e = Elevador::new( "EscadasSaoTerriveis" )
 AccessDeniedError: bad password

Isso foi inútil. Oh, espere! A senha de manutenção. Listada nas class_variables.

 irb> Elevador::senha_manutencao
 NoMethodError: undefined method `senha_manutencao' for Elevador:Class
         from (irb):1
         from :0

Hmm. Variáveis de instância só estão disponíveis dentro de um objeto. E variáveis de classe só estão disponíveis dentro de uma classe. Como conseguir aquela senha?

 irb> class Elevador
 irb>   def Elevador.senha_manutencao
 irb>     @@senha_manutencao
 irb>   end
 irb> end
   => nil
 irb> Elevador::senha_manutencao
   => "escadas_sao_passado!"

Agora sim! Conseguimos a senha. Você viu aquilo?

Ele adicionou um método de classe à classe Elevador. Não é ótimo como você pode começar a definir uma nova classe Elevador e o Ruby simplesmente adiciona suas modificações na definição de classe já existente?

Métodos de classe são geralmente chamadas com os dois pontos duplos. Mas, um ponto também serve. Já que Elevador é uma classe por si só, Ruby vai entender que se você chama Elevador.senha_manutencao, você está chamando um método de classe. Os dois pontos duplos simplesmente ajudam a tornar métodos de classe óbvios para o leitor.

E justamente. Métodos de classe são um pouco incomuns. Normalmente você não quer guardar informação diretamente dentro de uma classe. Contudo, se você tem um pedaço de informação que você precisa compartilhar com todos os objetos de uma classe, então você tem um bom motivo para usar a classe como armazenamento. É compreensível que a @@@senha_manutencao@ tenha sido armazenada na classe, ao invés de em cada objeto separado. Deste modo, o objeto pode simplesmente alcançar a classe e ver a senha compartilhada.

Provavelmente é assim que a proteção por senha funciona.

 class Elevador
   def initialize( senha )
     raise AccessDeniedError, "senha incorreta" \
       unless senha.equals? @@senha_manutencao
   end
 end

Proteger uma classe assim não faz sentido, já que tudo no Ruby pode ser alterado e reescrito e remoldado. O Dr. Cham tinha a senha e agora o elevador era dele.

 irb> e = Elevador.new( "escadas_sao_passado!" )
 #<Elevador:0x81f12f4 @level=4>
 irb> e.andar = 1

Dr. Cham estava parado lá quando as portas do elevador, atrás do terminal do computador, abriram-se para ele. Com um exasperado senso de realização e uma grande quantidade de entusiasmo por todos os eventos que se passaram, ele entrou no elevador e apertou o 4.

3. A Continuação da História do Instrutor de Órgão da Minha Filha

Eu sei que você pode estar surpreso em saber que eu tenho uma filha. Você pensa que meu estilo de escrever indica uma mente imatura ou infantil. Bem, por favor relaxe. Eu não tenho uma filha. Mas isso não me impede de pensar no treinamento musical dela.

Enquanto essas histórias do planeta Endertromb me eram relatadas, eu me vi vagando por corredores, passando as pontas dos meus dedos por sofás fortemente atados e me envolvendo nos gritos saturados dos tubos, enquanto o instrutor de órgão da minha filha tocava. Suas notas ressoavam tão ocas e profundas nas paredes de sua mansão que eu comecei a confundi-las com um silêncio nefasto, e achava ainda mais fácil me recolher ao espaço infinito dos meus pensamentos. Para pensar no planeta ancestral e suas filosofias obscuras: seus templos carnais, corados com os resíduos dérmicos dos seus mártires; seus cartéis de baleias, engolindo seus inimigos e prendendo-os por décadas, arrastando-os para cima e para baixo em suas escadarias de costelas; suas brumas venenosas e seus portais dolorosos; e, as cruéis dinastias dos Originais, a espécie que clama paternidade de toda vida inteligente no universo.

Mas, eventualmente, eu ouvia aqueles tubos de oitavas mais altas cantar e acabava voltando para a mesma tarde jovial de onde havia saído.

É interessante como até a brisa do nosso planeta é uma coisa um tanto estranha para forasteiros. Ele também me contou sobre viajantes de Rath-d, que se aventuraram na Terra cinco séculos atrás, mas se dissiparam rapidamente nas nossas correntes de ar já que eles, seus equipamentos e suas armaduras eram todos feitos de carvão.

Eu tinha me sentado ao órgão, ouvindo as histórias sobre sua colônia, enquanto ele acentuava suas sinfonias e as histórias desapareciam por um tempo, até que a melodia terminasse. Ele falava sobre si e seus irmãos sendo abraçados pela cauda de sua mãe e rasgando o tecido macio da parede interna. Um sabão suculento, esponjoso e melado que limpou suas bocas e esôfagos enquanto descia. Eles mastigaram e roeram fortemente aquilo e espuma se formava. Depois de comer, eles sopraram bolhas uns sobre os outros, cada bolha cheia de uma espuma densa, sobre a qual dormiram. E de manhã bem cedo, quando a mãe os soltava do abraço, ela observava serenamente enquanto seus bebês dormiam em um ensopado de almôndegas escuras e um molho doce e grudento.

Ele soletrou todos os gostos de Endertromb. Dos seus órgãos cor de salmão engomados, que se tornavam uma pasta quando cozidos, e seus olhos que derretiam e viravam um rico creme. Das suas manteigocias com tentáculos. E ele estava apenas começando a apreciar essas delícias, ainda criança, para ser elevado de um jardim de infância por um par de elefantes pigmeus que desceram um enorme guindaste dos céus, e o ergueram pela gola.

Eles o transplantaram para a Terra, o guiaram em seu ofício, trombeteando suas trombas alto para a cidade de Grand Rapids ouvir, então se foram, chorando e abraçando uns aos outros.

“Mas, estranhamente (em-pithy-dah), Eu aprendi, toquei (pon-shoo) nos órgãos no meu planeta (oth-rea) natal,” ele disse.

O instrutor de órgão da minha filha fala essas palavras extras que você vê em parênteses. Quem é que sabe se é sua língua nativa ou seu soluço sonoro. Ele mantém outro traço de Endertromb: ele tem doze nomes.

“Não, (wen-is-wen),” ele disse. “Eu tenho um nome (im-apalla) que é dito (iff) de muitas-muitas maneiras diferentes.”

Eu o chamo de Paij-ree nas manhãs e Paij-plo de tarde. Já que estou escrevendo de dia, o chamarei de Paij-ree aqui.

Protetores Auriculares Livres de Murmúrio

Alienígena nas teclas.

Então eu disse a Paij-ree, “Paij-ree, eu estou escrevendo um livro. Para ensinar ao mundo Ruby.”

“Oh, (pill-nog-pill-yacht) bacana,” ele disse. Ele conhece Ruby há mais tempo que eu, mas mesmo assim: Eu serei o instrutor de Ruby da minha filha.

E eu disse, “Paij-ree, você está no livro. E as estórias do seu planeta.” Eu falo com ele como se ele fosse o E.T. Eu não sei por quê. Como o que eu disse em seguida: “E daí talvez algum dia você possa ir para casa para o seu pai e para sua mãe!”

Ele replicou, “(pon-shoo) (pon-shoo) (em-pithy-dah).” Que é o jeito dele de expressar em voz alta seu silêncio e receio.

Ele queria ver o que eu havia escrito, então eu mostrei a ele este pequeno método que escrevi para você.

 def limpar_murmurios_de( frase )
   while frase.include? '('
     abre = frase.index( '(' )
     fecha = frase.index( ')', abre )
     frase[abre..fecha] = '' if fecha
   end
 end

“Viu o que isto faz, Paij-ree? Qualquer índio velho pode usar este método para remover toda essa poluição incoerente das suas falas,” eu disse.

E eu alimentei o método com algo que ele havia dito mais cedo.

 o_que_ele_disse = "Mas, estranhamente (em-pithy-dah), 
 Eu aprendi, toquei (pon-shoo) em órgãos no meu planeta
 (oth-rea) natal."
 limpar_murmurios_de( o_que_ele_disse )
 print o_que_ele_disse

E saiu de certa forma uma frase mais clara.

 Mas, estranhamente,  Eu aprendi, toquei em órgãos no meu planeta natal. 

“Você não deveria usar este (wary-to) loop while,” ele disse. “Existem jeitos mais amáveis, (thopt-er), e gentis.”

No método limpar_murmurios_de, estou basicamente procurando por abre parênteses. Quando eu encontro um, eu procuro um fecha parênteses na seqüência. Uma vez que tenha encontrado ambos, eu os troco e seu conteúdo por uma string vazia. O loop while continua até que todos os parênteses se acabem. Os murmúrios são removidos e o método termina.

“Agora olhando este método,” eu disse. “Eu vejo que há alguns aspectos confusos e outras coisas que eu poderia ter feito melhor.” Por favor não me olhe estranho por seu professor ter escrito este código. Eu acho certo lhe mostrar algumas técnicas desleixadas para lhe ajudar a trabalhá-las comigo. Vamos lá.

Ok, Aspecto confuso No. 1: Este método limpa uma string. Mas e se nós acidentalmente dermos a ele um File? Ou um número? O que acontece? E se rodarmos limpar_murmurios_de( 1 )?

Se nós dermos ao limpar_murmurios_de o número 1, o Ruby irá imprimir o seguinte e depois sair.

 NoMethodError: undefined method `include?' for 1:Fixnum
         from (irb):2:in `limpar_murmurios_de'
         from (irb):8

O que você vê aqui é um amiguinho especialmente tortuoso e verboso (mas às vezes muito útil) chamado depurador. Ele é um policial nervoso, ao menor sinal de problema, imediatamente apreende todo e qualquer suspeito, os põe contra a parede e lê os direitos deles tão rapidamente que ninguém consegue ouvir tudo. Mas está claro que há um problema. E, é claro, tudo não passou de um mal entendido, certo?

Quando o Ruby ler para você esses direitos de Miranda, preste atenção no começo. A primeira linha é quase sempre tudo que você precisa. Nessa primeira linha está contida a mensagem essencial. E ali em cima, a primeira linha está nos dizendo que não há método include? para o número 1. Lembra, quando estávamos conversando sobre o método reverse no capítulo anterior? Naquela hora, eu disse, “vários métodos só estão disponíveis com certos tipos de valores.” Ambos reverse e include? são métodos que funcionam com strings mas não têm sentido e são indisponíveis para números.

Sendo mais claro: o método tenta usar o número. O método vai iniciar com frase valendo 1. Então, ele chega na segunda linha: while frase.include? '('. Números não têm método include?. Maravilha, o depurador nos mostrou onde o problema está. Eu não esperava que alguém fosse passar um número, então estou usando métodos que não funcionam com números.

Viu, é só isso. Nosso método é sua própria ferramenta de bolso , certo? Ele age como seu próprio widget independente de todo o resto. Para todos por aí usando o método limpar_murmurios_de, caso a eles seja passado um número, será atirado para eles esta mensagem de pânico que não lhes faz sentido. Eles serão convidados a bisbilhotar dentro do método, o que realmente não é o trabalho deles. Eles não sabem como se virar lá dentro.

Felizmente, nós podemos acionar nossos próprios erros, nossas próprias exceções, o que pode fazer mais sentido a algum desavisado que dê um objeto errado para ser limpo.

 def limpar_murmurios_de( frase )
   unless frase.respond_to? :include?
     raise ArgumentError, 
      "não posso limpar os murmúrios de um(a) #{ frase.class }"
   end
   while frase.include? '('
     abre = frase.index( '(' )
     fecha = frase.index( ')', abre )
     frase[abre..fecha] = '' if fecha
   end
 end

Desta vez, se passarmos um número (de novo, o número 1), teremos algo mais sensato.

 ArgumentError: não posso limpar os murmúrios de um(a) Fixnum
         from (irb):3:in `limpar_murmurios_de'
         from (irb):12

O método respond_to? é realmente bacana e eu imploro que você nunca se esqueça dele. O respond_to? checa qualquer objeto para garantir que ele contém um determinado método. Ele então retorna com true o false. No caso acima, é checado se o objeto frase recebido contém algum método include?. Se nenhum método include? for encontrado, então disparamos o erro.

Você deve estar pensando por que eu usei um símbolo com o respond_to?. Eu usei um símbolo :include? invés da string 'include?'. Na verdade, ambos funcionarão com o respond_to?.

Geralmente símbolos são usados quando você está passando o nome de um método ou qualquer outro construtor. É mais eficiente, chama mais atenção. O respond_to? pergunta ao Ruby para olhar a si mesmo e ver se um método está disponível. Estamos conversando com o Ruby, então o símbolo ajuda a denotar isto. Não é grande coisa, Ruby só reconhece símbolos mais rapidamente que strings.

Agora, Aspecto Confuso No. 2: Você notou como nosso método modifica a frase?

 algo_dito = "Uma espaçonave (gith)."
 limpar_murmurios_de( algo_dito )
 print algo_dito

Você percebeu isso? Na primeira linha do código acima, a variável algo_dito contém a string "Uma espaçonave (gith).". Mas, depois de invocar o método, na terceira linha, nós imprimimos a variável algo_dito e nesse momento ela contém a string limpa string "Uma espaçonave.".

Como isso funciona? Como o método modifica a string? Ele não deveria fazer uma cópia da string antes de modificá-la?

Sim, absolutamente, ele deveria! É falta de educação modificar strings daquele jeito. Nós usamos gsub e gsub! no capítulo passado. Você se lembra qual destes dois métodos é um método destrutivo, que modifica strings diretamente?

Ou nós chamamos este método de limpar_murmurios_de! (como cortesia a todos os colegas bacanas por aí que podem vir a usar este método) ou modificar o método para trabalhar em uma cópia da string ao invés da coisa real. O que é uma modificação muito fácil! Nós só precisamos dar um dup na string.

 def limpar_murmurios_de( frase )
   unless frase.respond_to? :include?
     raise ArgumentError, 
      "não posso limpar os murmúrios de um(a) #{ frase.class }"
   end
   frase = frase.dup
   while frase.include? '('
     abre = frase.index( '(' )
     fecha = frase.index( ')', abre )
     frase[abre..fecha] = '' if fecha
   end
   frase
 end

O método dup faz uma cópia de qualquer objeto. Veja a linha que adicionamos separada:

 frase = frase.dup

Que linha de código peculiar. Como frase vira uma cópia de frase? Ela se apaga? O que acontece com a frase original? Ela desaparece?

Lembre que variáveis são como apelidos. Quando você vê frase = "Uma espaçonave (gith).", você vê o Ruby criando uma string e então dando um apelido a essa string.

Do mesmo modo, quando você vê frase = frase.dup, você vê o Ruby criando uma nova string e então dando um apelido a essa string. Isso é útil dentro do seu método porque agora frase é um apelido para uma nova cópia da string que você pode usar seguramente sem modificar a string que foi passada ao método.

Você verá muitos exemplos de nomes de variáveis sendo reusados.

 x = 5
 x = x + 1
 # x agora é igual a 6

 y = "Endertromb"
 y = y.length
 # y agora é igual a 10

 z = :include?
 z = "a string".respond_to? z
 # z agora é igual a true

E, sim, algumas vezes objetos desaparecem. Se você não consegue chegar em um objeto por uma variável, então o Ruby vai entender que você já terminou com ele e vai se livrar dele. Periodicamente, o Ruby envia seu coletor de lixo (garbage collector) para libertar estes objetos. Todo objeto é mantido na memória do seu computador até que o coletor de lixo se livre dele.

Oh, e mais uma coisa sobre o dup. Algumas coisas não podem ser “dupadas”. Números, por exemplo. Símbolos (que se parecem com :morte) são idênticos quando grafados iguais. Assim como números.

Além disso, algumas variáveis especiais: nil, true, false. Estas são coisas que o Ruby não vai te deixar alterar, então não faz sentido copiar mesmo. Quero dizer, imagine se você pudesse mudar o false para que seja true. A coisa toda vira uma grande mentira.

Talvez o Aspecto Confuso No. 3 seja simples. Estou usando aquelas chaves na string. Estou a tratando como se ela fosse um Array ou Hash. Eu posso fazer isso. Porque strings têm um método [].

Quando usadas em uma string, as chaves vão extrair parte daquela string. Mais uma vez, espaço para as pás da empilhadeira. A string é como uma longa prateleira e a empilhadeira tira os pedaços da string.

Dentro das chaves, nós passamos o index (índice). É a etiqueta que colocamos entre as pás, onde o trabalhador pode vê-las. Quando o assunto são strings, podemos usar vários objetos como índices.

 str = "Uma string é uma longa prateleira de letras e espaços."
 puts str[0]       # imprime 85 (o código do caractere 'U')
 puts str[0..-1]   # imprime 'Uma string é uma longa prateleira de letras e espaços.'
 puts str[1..-2]   # imprime 'ma string é uma longa prateleira de letras e espaços'
 puts str[1, 3]    # imprime 'ma '
 puts str['prateleira'] # imprime 'shelf'

Tudo bem, o último Aspecto Confuso No. 4: este método pode ser enviado a um loop interminável. Você pode dar uma string para este método, o que fará com que ele trave e nunca mais volte. Dê uma olhada no método. Você consegue jogar um graveto que trave o loop?

 def limpar_murmurios_de( frase )
   unless frase.respond_to? :include?
     raise ArgumentError, 
      "não posso limpar os murmúrios de um(a) #{ frase.class }"
   end
   frase = frase.dup
   while frase.include? '('
     abre = frase.index( '(' )
     fecha = frase.index( ')', abre )
     frase[abre..fecha] = '' if fecha
   end
   frase
 end

Aqui, entorte o graveto antes de jogá-lo.

 graveto = "Aqui está um ( graveto entortado."
 limpar_murmurios_de( graveto )

Por que o método trava? Bem, o loop while espera até que todos os parênteses abertos se acabem antes de parar de rodar. E ele só modifica um parêntese aberto que tenha um par parêntese fechado. Então, se nenhum parêntese fechado é encontrado, o parêntese aberto não será modificado e o while nunca ficará satisfeito.

Como você reescreveria este método? Eu sei como me virar no Ruby, então eu usaria uma expressão regular.

 def limpar_murmurios_de( frase )
   unless frase.respond_to? :gsub
     raise ArgumentError, 
       "não posso limpar os múrmurios de um(a) #{ frase.class }"
   end
   frase.gsub( /\([-\w]+\)/, '' )
 end

Dê o melhor de si quando pensar nos seus loops. É muito fácil, especialmente para os loops while e until saírem do controle. Melhor usar um iterador. E nós chegaremos em expressões regulares na hora certa.

Resumidamente, aqui está o que aprendemos sobre escrever métodos:

  1. Não se surpreenda se as pessoas passarem objetos inesperados aos seus métodos. Se você não pode usar de jeito nenhum o que lhe deram, raise (cause) um erro.
  2. É falta de educação mudar objetos que são dados aos seus métodos. Use dup para fazer uma cópia. Ou encontre um método como gsub que automaticamente faz a cópia enquanto faz o seu serviço.
  3. As chaves podem ser usadas para procurar partes dentro de qualquer objeto Array, Hash ou String, já que estes objetos provêm um método []. E também, já que estes objetos provêm um método []=, as chaves podem ser usadas para atribuição (do lado esquerdo do sinal de igual) para mudar partes destes objetos.
  4. Cuidado com loops fujões. Evite while e until se você puder.

Os Mecanismos do Estereótipo

Vendedor de gatos do espaço.

Imediatamente ouve-se um sussurro nas árvores atrás da casa do Paij-ree e acabou que era o homem que caíra do céu. Seu nome era Doug e ele vendia gatos.

Então, assim que ele aparecer, quando sua sombra (e as sombras dos gatos amarrados aos seus pés) entrou na frente do pássaro no gramado que nós estávamos tentando acertar com uma raquete, enquanto ele retirava o hélio do grande balão, nós gritamos, “Olá, Doug!”

E ele diz, “Olá, Gonk-ree! Olá, Why!”

Paij-ree checa os bolsos para ter certeza que tem o real-e-vinte-sete que vai precisar para comprar os três gatos que precisa para manter a fornalha abastecida e a parabólica virando. Estes gatos geram montes de eletricidade estática quando Paij-ree os joga no gerador, onde eles estarão em inferioridade numérica a gigantes bastões de vidro, que os acariciam continuamente— Mas, espere! Você reparou como o corretor de gatos chamou ele de Gonk-ree?

E ele o chama de Gonk-ree de dia e Gonk-plo de noite.

Então o sufixo é definitivamente relacionado à luz do sol. Até onde sei, o prefixo indica a relação de quem chama o Paij-ree.

 class String

   # As partes do nome do professor
   # de órgão da minha filha.
   @@silabas = [
     { 'Paij' => 'Pessoal',
       'Gonk' => 'Negócios',
       'Blon' => 'Escravo',
       'Stro' => 'Mestre',
       'Wert' => 'Pai',
       'Onnn' => 'Mãe' },
     { 'ree'  => 'AM',
       'plo'  => 'PM' }
   ]

   # Um método para determinar o 
   # signficado de certos nomes dele.
   def significado_do_nome
     partes = self.split( '-' )
     silabas = @@silabas.dup
     significado = partes.collect do |p|
       silabas.shift[p]
     end
     significado.join( ' ' )
   end

 end

Agora eu fui bem mais além do que lhe mostrar apenas código banal. Houve aqui uma grave libertinagem e um crime contra a natureza. Um crime que a maioria das linguagens não permitiriam que você cometesse. Nós estamos mudando a String, uma das classes do núcleo do Ruby!

“Eu sei que isto é um pouco perigoso,” Eu disse, quando passei isso por baixo do nariz do Paij-ree. “Eu espero que ninguém se machuque.”

“Todo cara pálida deve experimentar o que esse (kep-yo-iko) perigo faz,” ele disse. “Cachorros e lenhas e areia movediça (kul-ip), todos devem ser experimentados.” E ele deu uma gole no seu drink de pântano Beagle Berry.

Então o que é que eu estou adicionando à classe String? Duas coisas: uma variável de classe e um método. Um método de instância normal.

Eu gosto de ver a arroba como um caractere que significa atributo. A arroba dupla atributo coletivo. Uma variável de classe. Todas as instâncias da classe podem olhar para esta variável e ela é a mesma para todas. A variável @@@silabas@ é um Array que agora pode ser usado dentro da classe String.

O novo método é significado_do_nome e esse novo método pode ser usado com qualquer string.

print "Paij-ree".significado_do_nome imprime Pessoal AM.

Como você pode ver, Paij-ree é um nome pessoal. Um nome que os amigos usam nas manhãs.

Tenha certeza de ter visto a linha de código que usa self. Esta é uma variável especial, uma variável que representa o objeto cujo método você está chamando. Para simplificar as coisas um pouco, vamos tentar fazer um método que separe uma string pelos hífens.

 class String
   def separar_hifen
     self.split( '-' )
   end
 end

De novo, aqui está um método que pode ser usando com qualquer string.

"Gonk-plo".separar_hifen retorna o Array ['Gonk', 'plo'].

Usar self marca o a entrada em um novo estágio com idéias mais avançadas no Ruby. Esta é uma linguagem de definição. Você está definindo um método, desenhando ele antes dele ser usado. Você está preparando para a existência de um objeto que use aquele método. Você está dizendo, “Quando separar_hifen for usado, haverá uma string a qual estaremos separando-hífens. E self é uma variável especial que faz referência àquela string.”

Ruby é uma linguagem de definição imbatível. Uma discussão suculenta e de rachar a cuca estará no seu caminho nas profundezas deste livro.

Na maioria das vezes você não precisa usar self explicitamente, já que você pode chamar métodos diretamente dentro de outra definição de método.

 class String
   def separar_hifen; split( '-' ); end
 end

No método significado_do_nome, encontre o loop. Aprender sobre Array#collect é essencial. Vamos olhar de perto.

 significado = partes.collect do |p|
   silabas.shift[p]
 end

O Array partes contém o nome separado. ['Paij', 'plo'], por exemplo. Estamos iterando por cada item naquele Array com collect. Mas collect vai um passo a frente em relação ao que o each faz. Assim como each, collect joga cada item pela calha como uma variável de bloco. E aí, ao término do bloco, collect mantém a resposta que o bloco dá e a adiciona em um novo Array. O método collect é o jeito perfeito de se fazer um novo Array que é baseado em itens de um Array existente.

O Doug tem três gatos à venda. Um custa doze centavos, um sessenta e três centavos, um nove centavos. Vamos ver quanto cada gato custaria se nós adicionássemos uma gorjeta de 20%.

 gatosegorjetas = [0.12, 0.63, 0.09].collect { |custogato| custogato + ( custogato * 0.20 ) }

Costumo dizer que a propriedade do Paij-ree é um charmoso pedaço de floresta quando não está chovendo gatos e Doug. Por vários dias, Paij-ree e eu acampamos em tendas perto do rio atrás da casa dele, subsistindo de fumaça de turdus e retalhando indiozinhos adormecidos ao pôr do sol. Em uma ocasião ele perdeu no carteado e eu sabia que sua mente estava distraída, pensando em Endertromb. Tudo isso deve estar remoendo nele por algum tempo já. Eu fui o primeiro confidente que ele tivera.

“Acabei de vir de Ambrose,” Eu disse. “É tipo minha segunda casa adotiva, um lugar onde elfos aspiram a ser animais perfeitos.”

Ele resmungou e balançou a cabeça. “Você não pode ser (poth-in-oin) parte (in) em coisas assim.”

“Você acha que nós falharemos?”

“Eu (preep) já vi isso antes,” ele disse. E daí, ele falou sobre a Loteria.

4. A Cabra Quer Assistir Um Filme Inteiro

Blinky, winky, uma cabra... desperta...

O elevador se abriu em uma sala verde tomada por estantes e arquivos. Rolos de filme e latas de filme e fitas de vídeo por toda parte. O Dr. Cham não fazia idéia do que eram a maioria destas coisas. Tudo que ele viu foi uma grande, bagunça futurística.

Ele bradou novamente, esbarrando em estreitos becos entre estantes, “Al-ô-ô?? Estou procurando vida inteligente, sou um viajante do espaço!” Ele tropeçou quando seu pé enroscou num videocassete. “Algum outro ser com quem eu possa me comunicar?”

Com as mãos em volta da boca, ele gritou, “Al-ô-ô?”

“Crying out loud(*).” A cabra sonolenta veio trotando pelo corredor. (* Livro do poeta norte-americano
Cid Corman, tradução: Gritando bem alto).

A cabra já conhece o Dr. Cham.

“Eu odeio aquele livro,” disse a cabra. “Eu acho que o autor é insincero.”

“Mesmo?” perguntou o Dr. Cham.

“Tenho certeza que tudo é verdade. Mas é muito enfeitado. Eu fico tipo: Chega. Já entendi. Pára com isso.”

“Não tenho muita certeza do que fazer com isso,” disse o Doutor. “Parece um esforço honesto. Na verdade, eu escrevi algo em Ruby lá atrás.”

“Isto não dá às cabras uma boa reputação,” disse a cabra.

“Mas você é a única cabra no livro,” disse o Doutor.

“E totalmente mal interpretada.”

A mecânica por trás de devorar o Dr. Cham.

A cabra fechou sua boca e Dr. Cham acalmou-se.

“Na verdade sou bastante letrada,” disse a cabra. “Embora, recentemente, eu estou vendo mais filmes. Eu amo filmes estrangeiros. Um de meus parentes acabou de trazer Ishtar do seu planeta. Uau, aquilo foi excelente.”

“Eu não visito o meu planeta há muito tempo. Seria difícil considerá-lo minha casa a esta altura do campeonato.”

“Bem, Warren Beatty é maravilhoso. Seu personagem é basicamente socialmente aleijado. Ele até tenta se matar, mas Dustin Hoffman senta no peitoril da janela e começa a chorar e cantar uma música totalmente hilária. É de partir o coração. Eu tenho ele aqui, você deveria assisti-lo.”

“Posso pegar algo para comer?” perguntou o Doutor. E ainda se sentia sujo.

“Que tal assistirmos um filme e você pode comer mantegocias com tentáculos?” disse a cabra.

Então, rumaram de volta ao projetor da cabra. De volta para ao compartimento do congelador, eles se sentaram em um tapete gigante e quebraram alguns apêndices de mantegocias congeladas. A casca era dura, mas depois de quebrada, havia um rico creme de frutas em abundância. Doce ao paladar e de um aroma muito agradável.

“Primeiro filme, você tem que ver,” disse a cabra. “Filmado e produzido localmente. Eu sou íntimo da moça que dirigiu o elenco. Saí com ela por um tempo. Sabia de todos que iriam protagonizar diferentes papéis muito antes que fosse anunciado.”

A cabra ajeitou o projetor perto do Dr. Cham. “A música está em surround sound. Você pode ajustar no botão.”

Os Originais e Seu Planeta Deprimente.

A mente do Dr. Cham vagou nesse ponto da apresentação, bem a medida que a guerra aumentava entre as duas multidões de animais colonizadores. Os detalhes de suas guerras e campanhas continuavam a consumir o carretel de filme transparente que Dr. Cham alimentava através do projetor.

Guerra após guerra após guerra. O Cerco do Elmer Lake. A Última Estada de Newton P. Giraffe e Filhos. A Invasão Canil da Pequena Nuvem Abandonada. Nenhum animal morreu nessas guerras. Geralmente um ataque consistia em dar um tapinha na cabeça de outro animal. E eles davam petelecos nos narizes uns dos outros. Mas, acredite em mim, aquilo era humilhante.

Porca miséria. As coisas podiam ter dado certo.

O Nascimento de um Objeto

“Não se aflija,” disse a cabra, ansiosa para dissuadir a atenção do Dr. Cham de volta ao filme. “As coisas dão certo.”

No Ruby, o Objeto é o centro exato de todas as coisas. Ele é O Original.

 class UrsoTostado < Object; end

O menor que indica herança. Isto significa que a nova classe UrsoTostado é baseada na classe Objeto. Todo método que Objeto tem estará disponível na UrsoTostado. Constantes disponíveis em Objeto estarão disponíveis em UrsoTostado.

Mas todo objeto herda de Object. O código…

 class UrsoTostado; end

É idêntico a…

 class UrsoTostado < Object; end

Herança é uma comodidade. Você pode criar espécies de objetos que se relacionam entre si. Frequentemente, quando está dissecando um problema, você se deparará com vários objetos que compartilham atributos. Você pode ter menos trabalho herdando de classes que já solucionam parte desse problema.

Você pode ter uma classe BrasilEndereco que guarda o endereço, cidade, estado, e CEP de alguém que more no Brasil. Quando você começar a guardar endereços da Inglaterra, você pode adicionar uma classe ReinoUnidoEnderecos. Se você então garantir que os dois endereços herdam de uma classe mãe Endereco, você pode planejar seu software de correspondência de modo que aceite todo tipo de endereço.

 def envia_lhes_um_kit( endereco )
   unless endereco.is_a? Endereco
     raise ArgumentError, "Objeto Endereco não encontrado."
   end
   print endereco.formatted
 end

Além disso, herança é ótimo se você quer sobrescrever certos comportamentos numa classe. Por exemplo, talvez você queira fazer a sua própria variação da classe Array. Você quer melhorar o método join. Mas se você mudar Array#join diretamente, afetará outras classes no Ruby que usam Arrays.

Então você começa sua própria classe chamada MeuArray, que é baseada na classe Array original.

 class MeuArray < Array
   # Contruir uma string neste array, formatando cada entrada
   # e depois as unindo.
   def join( sep = $,, format = "%s" )
     collect do |item|
       sprintf( format, item )
     end.join( sep )
   end
 end

MeuArray é agora uma classe Array customizada com o seu próprio método join. Array é a superclasse (classe-superior, classe-mãe) do MeuArray. Cada objeto tem um método superclass onde você pode verificar esta relação.

 irb> MinhaArray.superclass
   => Array

Perfeito. Nós administramos um hotel e nós temos uma Array dos tamanhos dos nossos quartos: [3, 4, 6]. Vamos imprimir isso de um jeito bacana para encadernarmos.

 quartos = MinhaArray[3, 4, 6]
 print "Nós temos quartos de " + quartos.join( ", ", "%d camas" ) + " disponíveis."

Que imprime, “Nós temos quartos de 3 camas, 4 camas, 6 camas disponíveis.”

Dr. Cham estava procurando por um banheiro, mas só tinham videotapes arquivados para todo lado. Ele acabou encontrando um lugar, que poderia ser um banheiro. Tinha um recipiente metálico. Mais importante que isso, era escuro e escondido.

Enquanto ele está lá, deixe-me acrescentar que enquanto Os Originais massacraram Os Invasores para provar seus direitos como Criaturas de Primeiro Escalão, com o Objeto Ruby, não existe tal disputa. Ele é o rei Objeto absoluto, o Primeiro.

Observe.

 irb> Class.superclass
   => Module
 irb> Kernel.class
   => Module
 irb> Module.superclass
   => Object
 irb> Object.superclass
   => nil

Até Classe é um Objeto! Veja, mesmo as classes sendo linguagem de definição para objetos, nós ainda podemos chamar métodos de classe nelas e tratá-las como objetos ocasionalmente. Pode parecer um círculo estonteante, mas é verdadeiramente uma descendência bastante clara. E garante que quando você altera o Object, você altera tudo no Ruby. O que é impossivelmente assustador e todo-poderoso e cataclísmico e incrível! Ruby não lhe restringe, minha irmã, meu irmão!

Entre Class e Object, você vê Module? Se Object é o rei, o pai de todas as outras partes do Ruby, então Module é uma pobre e frágil freira, abrigando e protegendo todos as suas criancinhas Ruby da cidade. (Para completar a analogia: Class é a professora da escola da vila e Kernel é o auto-proclamado importante coronel.)

O motivo da existência do Module é dar comida e abrigo ao código. Métodos podem ficar abrigados embaixo da manta do Module. Module pode conter classes, constantes e variáveis de qualquer tipo.

“Mas o que um Module faz?” você pergunta. “Como ele é lucrativamente utilizado??”

“Isso é tudo que ele faz!!” Eu replico, mostrando as palmas da mão na maior expressão de futilidade conhecida pelo homem. “Agora me escute — pois nunca mais repetirei isso — essa Mãe Módulo Superior deu a estes pobres objetos um lugar para morar!!”

 # Veja, aqui está o module -- onde mais seu código poderia estar?
 module AtenciosaSantaInes

   # Uma CONSTANTE repousa perto da porta.  Ótimo.
   HOMEM_DESDENTADO_COM_GARFO = ['homem', 'garfo', 'chicletes expostos']

   # Uma Class está comendo, vivendo bem na cozinha.
   class CriancaGordaDeCera; end

   # Um Método está se escondendo lá atrás no armário banana, Deus sabe por quê.
   def timida_garota_com_cara_de_raposa; {'por favor' => 'eu quero uma noz de carvalho por favor'}; end

 end

Agora você tem que ir pela Santa Inês para achá-los.

 >> AtenciosaSantaInes::HOMEM_DESDENTADO_COM_GARFO
 => ["homem", "garfo", "chicletes expostos"]
 >> AtenciosaSantaInes::CriancaGordaDeCera.new
 => #<AtenciosaSantaInes::CriancaGordaDeCera:0xb7d2ad78>
 >> AtenciosaSantaInes::instance_methods
 => ["timida_garota_com_cara_de_raposa"]

Lembre-se sempre que um Module é somente um hotel. Um teto sobre suas cabeças. Ele não é uma auto-consciente Classe e, portanto, não pode ser trazido à vida com new.

 >> AtenciosaSantaInes.new
 NoMethodError: undefined method `new' for AtenciosaSantaInes:Module
         from (irb):2

Santa Inês deu a própria vida para cuidar desses pedaços de código desesperados. Por favor. Não tire isso dela.

Se, todavia, você quer roubar da Santa Inês, eu posso lhe ajudar. Você pode arrumar um grande mosteiro para confinar o ministério da AtenciosaSantaInes e então o quê sobrará para ela?

Para isso você pode usar extend, que puxará todos os métodos do módulo para dentro de uma classe ou um objeto.

 >> class FundacaoDeAmorEAmparoTimeWarnerAolCitibank; end
 >> FundacaoDeAmorEAmparoTimeWarnerAolCitibank.extend AtenciosaSantaInes
 >> FundacaoDeAmorEAmparoTimeWarnerAolCitibank::instance_methods
 => ["timida_garota_com_cara_de_raposa"]

Na verdade, ninguém roubou da AtenciosaSantaInes, somente pegaram emprestado. A timida_garota_com_cara_de_raposa agora tem dois endereços.

Você deve admitir. O velho mosteiro pode ser comprado um zilhão de vezes e a pequena garota-com-cara-de-raposa ainda estará nos fundos no armário banana esperando uma noz de carvalho! Que pena que não podemos alimentá-la. Ela é um método sem argumentos.

Quando Dr. Cham retornou renovado, a tira de filme estava um pouco atrasada. Mas a cabra não notou, então o Doutor avançou alguns quadros até fazer algum sentido.

A cabra que disse ao planeta que ele era feio.

Então os invasores deixaram o planeta.

“Este planeta é decrépito,” disse o Dr. Cham. “O castelo é bacana. Mas por dentro é um desastre.”

“O castelo parece uma projeção,” disse a cabra. “Todas as flores e brotos de maçã e até mesmo o céu. É uma projeção de baixa resolução.”

“Sim? Ele é encantador.”

“Eu acho.”

O cilindro termina.

“Está tudo errado!” disse a cabra. “Não é assim que o filme termina! Não teve sangue! O que aconteceu? O que aconteceu? Você apertou o botão errado, idiota?”

“Bem, eu não sei,” disse o Dr. Cham. Ele girou o botão para frente e para trás. Deu um tapa na lente.

“Cheque o filme! Cheque o filme!”

Dr. Cham tirou um pedaço do filme do alimentador do projetor, derretido e pingando nas extremidades.

“Maldição! Estes projetores são de qualidade! Nunca vi isso acontecer. Não pode ser.”

Caçando Uma Voz

“Eu não acho que tenha sido o projetor,” disse o Dr. Cham. “Alguma coisa voou pela tela e proferiu um gemido furioso.”

“Eu não tenho nenhuma cópia deste filme,” disse melancolicamente a cabra. “E aquela garota. A diretora de elenco. Eu nunca mais a verei novamente.”

Dr. Cham levantou-se e olhou para os largos corredores de carnificina magnética, procurando.

“Oh, ei, você deveria chamar aquela garota,” a cabra continuou. “Você poderia conversar com ela, chegar a um consenso. Diga a ela sobre mim. Não aja como se fosse meu amigo, só, você sabe, ‘Oh, aquele cara? Eh, mas que bobalhão.’”

Dr. Cham mirou a porta e saiu.

Os corredores eram todos um outro mundo de bagunça. Nos arquivos da cabra, as estantes estavam desarrumadas. No corredor, as estantes estavam completamente tortas. Pias caíam pelo teto. O Doutor se aventurou por baixo dos escombros, chutando compensados de madeira quando necessário.

“Você não deveria estar aqui fora,” disse a cabra. “Você está na propriedade de outra pessoa aqui. Um casal de elefantes pigmeus são donos disso tudo. Eles são sujeitos maus. Vão te dar uma surra com suas trombas. Elas as enrolam e simplesmente dão porrada.”

Dr. Cham tirou um arquivo do seu caminho, que caiu por uma frágil parede, e então pelo chão do cômodo ao lado. E eles o ouviram caindo por vários andares depois.

“Eu estou tentando lembrar como isso acontece no livro,” disse o Dr. Cham, enquanto andava ligeiramente pelo hall. “Aquela neblina leitosa que varreu a projeção. Nós encontramos aquela coisa.” Ele sacudiu uma maçaneta, quebrou-a. Vagarosamente, passou pela porta e lá desapareceu.

“Você tem o dom de destruir as coisas com um chute, não tem?” disse a cabra. “Paredes, portas.” A cabra chifrou a parede ao estilo Zidane. A parede estremeceu e então permaneceu em silêncio.

Então, tudo ficou calado. E sombrio.

A cabra ficou firme no gélido corredor, esperando Dr. Cham revirar algumas mesas e emergir, pronto para continuar a partir do cômodo que ele estava. Mas o Dr. Cham não voltou, e a cabra optou por compartilhar um momento com os destroços negligenciados deixados por seus vizinhos. Não que ela pudesse velos de verdade. Ela podia apenas escutar os sussurros ocasionais das pilhas de faturas, cópias mestre de papel carbono e envelopes manilha quando deslocava suas pernas.

O chão parecia entortar-se bem perto da cabra, como se as pilhas de tralhas ao seu redor estivessem começando a deslizar em direção a seu peso. Ele estaria no centro deste redemoinho de documentação elefantística. Morreria ele primeiro pelos cortes causados pelo papel? Ou ele ficaria sufocado sob o sólido funeral de suprimentos de escritório?

Uma luz suave, no entanto, pairou sobre ele. Uma luz prateada, flutuante. Não, era uma — eram tesouras? As tesouras cresceram em um cintilante agrupamento de pão inteligente, cada fatia sufocada de glitter. Mas, não, eram mãos. E um chapéu de Páscoa.

A cabra sozinha no corredor, conhece uma aparição.

Em outro cômodo, Dr. Cham parou silenciosamente sobre o vidro claro. O teto abruptamente ficou transparente, então a luz das estrelas cobriu suas calças e jaqueta. Ele andou adiante até o centro do cômodo em cores escuras, iluminado tão suavemente quanto um manuscrito antigo em sua própria caixa em um museu. Mais estrelas, mais grupos de algodão em chamas, apareciam a medida que ele vinha pelo chão. E ele apareceu na visão logo em seguida, ele esperava que fosse maior, mas não era.

Terra. Como um ovo colorido, ainda fresco. Ele sentiu longas cordas de violoncelo cantando como que na sua espinha. Como podiam chamá-la de Pessoasenlameadas? Aqui estava uma lâmpada vibrante e gramada. Aquela grande bola em que tinha algo acontecendo para ele.

Ele pensou nas Chacretes. Realmente, ele sentia saudade das Chacretes. Que boas dançarinas elas eram. Ele chegou a gritar algo para as Chacretes quando as viu. Algo muito submisso e bajulador.

Oh, sim, enquanto As Chacretes giravam, braço com braço, ele gritara, “Círculos concêntricos!” Ninguém prestou atenção.

E esse pensamento foi o bastante para alimentar o complexo de superioridade do Dr. Cham. Ele fez um sorriso de pateta e deu alguns passos para trás. Ele sentiu verdadeiramente a sua genialidade em tal frase. Ela estava no fato dele perceber a simplicidade de um círculo. Ele refletiu sobre isso por todo o caminho de volta ao corredor.

O que eu acho ótimo. Adore-se quando você tiver um segundo.

O Doutor conhece esse fantasma.

“Oh, certo,” disse a cabra. “Sua sobrinha. A sobrinha que você matou. Eu estou com você agora.”

Por alguns momentos, eles ficaram se entreolhando. Tempo bastante para que ambos o Dr. Cham e a cabra pensassem: Oh, sim. Hannah nos causa muitos aborrecimentos. Ela já está falando sobre rosquinhas de bordo.

“Ela sempre começa falando sobre rosquinhas de bordo assim na lata?” perguntou a cabra.

“Sim, ela faz isso,” disse o Doutor. “Ela traz isso para você, depois ela traz para mim. Ela vê uma rosquinha de bordo em algum lugar — Eu não me lembro muito bem onde.”

“Eu estou vendo uma rosquinha de bordo de verdade?” Hannah disse. “Eu preciso de uma de verdade.”

“Ok, ok,” disse a cabra. “Sim, eu lembro: agora é a parte que ela diz que se ela conseguir uma rosquinha de bordo de verdade, ela será uma pessoa real novamente. Porque o real destino dela era ter uma padaria e você arruinou isso e agora ela está condenada a ser um fantasma.”

“Hey, isso é verdade!” Hannah uivou.

“É terrível que tenhamos que fazer essa cena inteira de novo,” disse o Doutor. “As rosquinhas não são materiais. Elas devem ser todas deixadas de fora.”

“Cara, estou tendo problemas para lembrar tudo desse capítulo,” disse a cabra. “Eu nem me lembro como sair desse corredor. Eu devo ter lido aquele livro tipo trinta vezes. Nós entramos destruindo uma parede? Nós gritamos até que alguém nos ache?”

“Nós fizemos a Hannah flutuar pelas paredes e ela encontra algum tipo de máquina,” disse o Dr. Cham. “Eu tenho que escrever um programa — e tudo dá certo de algum modo.”

“Mas, você sabe o que eu estou dizendo?” disse a cabra. “Eu esqueço todos os detalhes. Especialmente dos capítulos anteriores. Quer dizer, eu lembro do final perfeitamente. É complicado ficar sentando vendo tudo isso. O final é tão melhor.”

Dr. Cham flexionou seus braços balançou seu calcanhar. “O porco-espinho.” Sorriu ambiciosamente para a cabra.

“Oh, com certeza. O porco-espinho é definitivamente quem eu quero conhecer,” disse a cabra. “Eu me pergunto o quê ele fará com todo aquele dinheiro depois que o livro terminar.”

Dr. Cham acenou respeitosamente. “Estou doido para ver ele de chinelos.”

“Aqueles chinelos infernais!” disse a cabra e gaguejou grosseiramente, um banho de saliva jorrando de suas mandíbulas.

A mente de Hannah estava chacoalhando, perturbada, esperando que essas tolices cessassem por um momento. Ela inclinou sua cabeça de lado e o chocalho deslizou junto da curva de seu crânio. De qualquer modo, o barulhinho sumiu, a medida que a parte de trás de sua cabeça desaparecia (vazava é como ela chamava isso). Então a sua cabeça estava novamente com seu pequenino chocalho e ela se encontrou fazendo mais uma vez aquele indiscreto gemido. HRRRRRR-RRR-OH-RRRR-RRRR.

“Eu não estou nessa de bacon pedaçudo” disse a cabra. “Não vejo o quê é tão legal nisso.”

Podia ela falar gemendo? BON-BON. Com um sotaque francês. BOHN-BOHN. BOHN-APPE-TEET-OHHHH-RRRR.

“Eu sei que ela é inofensiva, mas esse som me dá calafrios. Meu cabelo está completamente em pé.”

“Hannah?” disse o Dr. Cham. “Onde você está, criança? Venha e volte para nós, minha sobrinha.”

Ela estava bem perto deles, dentro e fora. E eles podiam ouvi-la limpando a voz, clara, falando como um anjo esparramando poeira estelar. Sim, toda a estória da rosquinha de bordo veio de novo, e mais sobre a padaria que ela seria dona, os muffins, pãezinhos e baguetes.

5. O Roubo do Capitão Loteria

Os tubos e misturas das loterias.

E agora, as histórias das Loterias Paij-ree.

Em Endertromb, o pai do organista inventou a loteria. A idéia surgiu quando ele estava rezando para o Escavador Dosh.

Escavador Dosh é uma espécie de Deus para eles. Mas dez vezes mais assustador. Esse cara cavou um túnel infinitamente profundo através do planeta e saiu morto. Mas ele não está realmente morto. Ele está realmente um segundo atrás deles. E ele come tempo.

É meio complicado, porque o Escavador Dosh mata totalmente as pessoas. Mas acho que se você faz o que ele diz, não é tão ruim. Talvez eu fale sobre isso mais tarde. É tão doloroso falar sobre isso por ser algo tão assustador. Além disso, um dos meus amigos realmente acredita em toda a coisa. Eu fico meio que chocado — não como se estivesse chorando, mais como se estivesse engasgado.

De qualquer forma, enquanto rezava, três números vieram para o pai do Paij-ree.

Ele então se perguntou. “O que são esses números?”

E sua mente passou um pequeno vídeo clipe dele vendendo todos os tipos de números. E, por anos e anos, viajando e vendendo números.

E indagou ao seu cérebro, “Pessoas comprarão números?”

E seu cérebro disse, “Se comprarem os três números corretos, dê a eles um prêmio.”

Foi quando ele se imaginou saltando de uma rampa de ski e jogando presentes para as pessoas. Sem dúvidas: ele seria um ícone.

Então ele foi e fez o que seu cérebro disse e vendeu números. A simples loteria do pai consistia em três únicos números, retirados de um conjunto de 25 números.

 class BilheteLoteria

   INTERVALO_NUMERICO = 1..25

   attr_reader :numeros_escolhidos, :data_compra

   def initialize( *numeros_escolhidos )
     if numeros_escolhidos.length != 3
       raise ArgumentError, "três números devem ser escolhidos"
     elsif numeros_escolhidos.uniq.length != 3
       raise ArgumentError, "os três escolhidos devem ser diferentes"
     elsif numeros_escolhidos.detect { |p| not INTERVALO_NUMERICO === p }
       raise ArgumentError, "os três escolhidos devem ser números entre 1 e 25."
     end
     @numeros_escolhidos = numeros_escolhidos
     @data_compra = Time.now
   end

 end

Sim, a classe BilheteLoteria contém os três números (@numeros_escolhidos) e o momento em que o bilhete foi adquirido (@data_compra). O intervalo de números permitidos (de um a vinte e cinco) é mantido na constante INTERVALO_NUMERICO.

O método initialize pode ter qualquer número de argumentos passados. O asterisco no argumento numeros_escolhidos significa que quaisquer argumentos serão passados como um Array. Ter os argumentos em um Array significa que métodos como uniq e detect podem ser usados juntos aos argumentos.

Esta classe contém duas definições: o método de definição (def) e um de definição de atributos (attr_reader). Ambos são, realmente, apenas métodos de definição.

O attr_reader é um atalho idêntico à escrever o este código Ruby:

 class BilheteLoteria
   def numeros_escolhidos; @numeros_escolhidos; end
   def data_compra; @data_compra; end
 end

Atributos são métodos empacotadores (wrappers) para variáveis de instância (assim como @numeros_escolhidos) que podem ser usados fora da própria classe. O pai do Paij-ree queria codificar uma máquina que pudesse ler números e a data da compra do bilhete. Para fazer isso, estas variáveis de instância devem ser expostas.

Vamos criar um bilhete aleatório e ler os números de volta:

 bilhete = BilheteLoteria.new( rand( 25 ) + 1,
             rand( 25 ) + 1, rand( 25 ) + 1 )
 p bilhete.numeros_escolhidos

Executando o código acima, eu apenas pego: [23, 14, 20]. Você receberá um erro se acontecer dos dois números aleatórios serem idênticos.

Entretanto, eu não posso mudar os números escolhidos no bilhete de loteria de fora da classe.

 bilhete.numeros_escolhidos = [2, 6, 19]

Eu receberei um erro: undefined method `numeros_escolhidos=` Isto porque attr_reader somente adiciona um método de leitura, não um método de escrita. Entretanto, isso é bom. Nós não queremos que os números ou a data mudem.

Então, os bilhetes são objetos_. Instâncias da classe BilheteLoteria. Faça um bilhete com BilheteLoteria.new. Cada bilhete tem as suas variáveis de instância @numeros_escolhidos e @@datacompra@.

O capitão loteria teria necessidade de gerar três números aleatórios no encerramento do sorteio, por isso vamos acrescentar um método de classe conveniente para geração aleatória de bilhetes.

 class BilheteLoteria
   def self.novo_aleatorio
     new( rand( 25 ) + 1, rand( 25 ) + 1, rand( 25 ) + 1 )
   end
 end

Oh, não. Mas nós temos um estúpido erro que aparece quando dois dos números aleatórios são idênticos. Se dois números são iguais, o initialize lança um ArgumentError.

O truque é voltar e reiniciar o método se um erro acontecer. Nós podemos usar o rescue (resgate_) do Ruby para apanhar o erro e redo (_refazer) o método do início.

 class BilheteLoteria
   def self.novo_aleatorio
     new( rand( 25 ) + 1, rand( 25 ) + 1, rand( 25 ) + 1 )
   rescue ArgumentError
     redo
   end
 end

Melhor. Pode demorar algumas vezes para que os números caiam juntos corretamente, mas cairão. A espera fará o suspense, não?

O capitão loteria mantinha um registro de todos que compraram bilhetes, junto com os números de loteria deles.

 class SorteioLoteria
   @@bilhetes = {}
   def SorteioLoteria.compra( cliente, *bilhetes )
     unless @@bilhetes.has_key?( cliente )
       @@bilhetes[cliente] = []
     end
     @@bilhetes[cliente] += bilhetes
   end
 end

Yal-dal-rip-sip foi o primeiro cliente.

 SorteioLoteria.compra 'Yal-dal-rip-sip',
     BilheteLoteria.new( 12, 6, 19 ),
     BilheteLoteria.new( 5, 1, 3 ),
     BilheteLoteria.new( 24, 6, 8 )

Quando chega a hora do sorteio da loteria, o pai do Paij-ree (o capitão loteria) adiciona um bit de código para selecionar aleatoriamente os números.

 class BilheteLoteria
   def pontuacao( final )
     contador = 0
     final.numeros_escolhidos.each do |nota|
       contador += 1 if numeros_escolhidos.include? nota
     end
     contador
   end
 end

O método pontuacao compara um BilheteLoteria com um bilhete aleatório, o qual representa a combinação vencedora. O bilhete aleatório é passado através da variável final. O bilhete recupera um ponto para todo número vencedor. A pontuação final é retornada pelo método pontuacao.

 irb> bilhete  = BilheteLoteria.new( 2, 5, 19 )
 irb> vencedor = BilheteLoteria.new( 4, 5, 19 )
 irb> bilhete.pontuacao( vencedor )
   => 2

Com o tempo você verá o quão brilhante é Paij-ree. Seu pai o encarregou de conduzir a loteria por ele, à medida que a demanda por bilhetes consumia todas as horas do dia do capitão da loteria. Você consegue imaginar o jovem Paij-ree – em seu terno pomposo – brincando com elásticos com seus dedos jovens, em meio à reunião da empresa na qual propôs a peça final do sistema? Com certeza, quando se levantou, seu pai falou tudo para ele, mas foi ele quem ligou o projetor e fez todos os gestos com as mãos.

 class << SorteioLoteria
   def jogo
     final = BilheteLoteria.novo_aleatorio
     vencedores = {}
     @@bilhetes.each do |comprador, lista_bilhetes|
       lista_bilhetes.each do |bilhete|
         pontuacao = bilhete.pontuacao( final )
         next if pontuacao.zero?
         vencedores[comprador] ||= []
         vencedores[comprador] << [ bilhete, pontuacao ]
       end
     end
     @@bilhetes.clear
     vencedores
   end
 end

Os sócios de seu pai ficaram atordoados. O que era aquilo? (Paij-ree sabia que era apenas a definição de um método de classe — eles se sentiram completamente desmoralizados quando ele disse isso). Eles não conseguiam entender as duas setas para esquerda. Sim, era um concatenador, mas o que estaria ele fazendo em meio à definição da classe?

Bebês, pensava Paij-ree, embora mantivesse bem alta a auto-estima de cada um destes homens. Ele era apenas uma criança e crianças são duras como uma parede de tijolos.

O operador << permite a você alterar a definição de um objeto. Paij-ree simplesmente havia usado a classe SorteioLoteria, e o método dele, jogo, seria um método de instância normal. Mas, uma vez que usou o operador <<, o método jogo será adicionado diretamente à classe, como um método de classe.

Quando você viu class << obj, acredite em seu coração, eu estou adicionando diretamente para a definição de obj.

O embrião do instrutor de órgão também lançou um truque na sintaxe digno de ser examinado. Na nona linha, um vencedor foi encontrado.

 vencedores[comprador] ||= []
 vencedores[comprador] << [ bilhete, pontuacao ]

A sintaxe ||= é um atalho.

 vencedores[comprador] = vencedores[comprador] || []

O pipe duplo é um ou lógico. Faça vencedores[comprador] igual a vencedores[comprador] ou, se vencedores[comprador] é nulo, faça-o igual a []. Este atalho é um pouco estranho, mas se você puder abrir sua mente, ele é um bom método para economizar tempo. Você está se certificando que uma variável está inicializada antes de usá-la.

 irb> SorteioLoteria.jogo.each do |vencedor, bilhetes|
 irb>   puts vencedor + " ganhou com " + bilhetes.length + " bilhete(s)!"
 irb>   bilhetes.each do |bilhete, pontuacao|
 irb>     puts "\t" + bilhete.numeros_escolhidos.join( ', ' ) + ": " + pontuacao
 irb>   end
 irb> end

 Gram-yol ganhou com 2 bilhetes(s)!
     25, 14, 33: 1
     12, 11, 29: 1
 Tarker-azain ganhou com 1 bilhetes(s)!
     13, 15, 29: 2
 Bramlor-exxon ganhou com 1 bilhetes(s)!
     2, 6, 14: 1

Mas estes dias de inocência não continuaram para Paij-ree e seu pai. Seu pai, frequentemente, se esquecia de lavar seu uniforme e acabou contraindo uma micose em seus ombros. A doença afetou gradualmente seu equilíbrio e seu senso de direção.

Seu pai ainda tentou futilmente manter os negócios funcionando. Ele rodou a cidade, algumas vezes andando, de forma deplorável, passo-a-passo sobre os paralelepípedos, muitas vezes tateando as paredes, contando os tijolos até o salão dos matemáticos e a estação dos cocheiros, onde ele teria empurrado bilhetes de loteria aos transeuntes, que o cercaram e o esbofetearam com grandes beterrabas molhadas. Mais tarde, Paij-ree iria encontrá-lo em uma esquina, seu sangue escorrendo nos esgotos da cidade junto aos sucos das escuras, respingantes beterrabas, cujo suco preencheu o caminho até suas veias e coagulou firmemente como um amontoado exército de brake lights lutando por um lugar nos pedágios.

Uma Palavra Sobre Accessors (Porque Eu Te Amo e Espero Por Seu Sucesso e Meus Cabelos Estão Raleando Com Isto e Os Sonhos Realmente Se Tornem Realidade)

Anteriormente, eu mencionei que attr_reader adiciona um método reader, mas não um método writer.

 irb> bilhete = BilheteLoteria.new
 irb> bilhete.numeros_escolhidos = 3
 NoMethodError: undefined method `numeros_escolhidos=' for #<BilheteLoteria:0xb7d49110>

Que está correto neste caso, visto que o pai do Paij-ree não queria que os números fossem alterados depois que o bilhete fosse vendido. Se estivéssemos interessados em ter variáveis de instâncias que teriam ambos os métodos reader e writer, deveríamos usar attr_accessor.

 class BilheteLoteria
   attr_accessor :numeros_escolhidos, :data_compra
 end

Que faz exatamente o mesmo que este código comprido:

 class BilheteLoteria
   def numeros_escolhidos;       @numeros_escolhidos;       end
   def numeros_escolhidos=(var); @numeros_escolhidos = var; end
   def data_compra;              @data_compra;              end
   def data_compra=(var);        @data_compra = var;        end
 end

Santos gatos! Olhe para estes métodos escritores por um momento. Ele são chamados métodos picks= e purchased=. Estes métodos interceptam atribuições externas à variáveis de instância. Constantemente você irá deixar attr_reader ou attr_accessor (ou mesmo talvez attr_writer) fazer o trabalho por você. Outras vezes, você mesmo irá querer tomar conta da portaria, checando as variáveis mais detalhadamente.

 class CompeticaoSkate
   def o_vencedor; @o_vencedor; end
   def o_vencedor=( nome )
     unless nome.respond_to? :to_str
       raise ArgumentError, "O nome do vencedor deve ser uma String,
         não um problema matemático ou uma lista de nomes ou qualquer outra
         coisa parecida."
     end
     @o_vencedor = nome
   end
 end

Na maior parte das vezes você não vai querer usar isto. Mas, assim que formos caminhando através das lições, você irá perceber que Ruby possui muitas escotilhas e vielas nas quais você pode se enfiar e hackear código. Também estou lhe preparando para metaprogramação, que, se puder farejar o dragão, está ameaçadoramente próxima.

Paij-ree era um jovem e audaz Endertromaltoek. Ele martelava ossos de animais em longos, deslumbrantes trompetes com orifícios profundos que eram conectados por cortiças que os músicos uniam a seus dedos. Obviamente ele vendeu apenas três destas unidades, mas ele estava amplamente injuriado pois um acadêmico autônomo, um tipo demônico, para ele era de uma classe mais pobre e os pobres só conseguiam seu brilhantismo através de práticas satânicas. Claro, estavam certos, de fato, ele tinha um acordo com os magos negros, com quem ele mantinha encontros anuais, sofrendo atormentadoras primaveras ardentes, banhando-se enquanto eles lançavam feitiços.

Ele adorava seu pai, mesmo sabendo que seu pai deteriorara em nada mais que um giroscópio. Ele idolatrava o trabalho do homem e gastava seus pequenos ganhos jogando na loteria. Ele adorava assistir os numerais, cada um pintado sobre bolas de argila ocas, levantadas do robloch (que é qualquer tipo de fluido, reservatório ou entorno que vem resiste a presença de fantasmas), os grandes banqueiros amarrando-as num cordão de prata, lendo-as em ordem.

Mesmo hoje. Paij-ree pinta as cenas com pinceladas cruas de tinta preta em folhas de papel alumínio. É bastante tocante ver o que ele recuperou na preciosidade de sua memória, mas não sei dizer exatamente porque ele o faz em folhas de papel alumínio. Seus desenhos rasgam com bastante facilidade. O próprio Paij-ree fica confuso e lhe servirá bolo de pão usando esta arte, mesmo após ela ter sido corretamente emoldurada. Então, são tantas coisas sobre ele que são problemáticas e absurdas e absolutamente miseráveis.

A doença espalhou-se sobre a forma de seu pai e ervas pantanosas cobriam as mãos e a face de seu pai. O musgo empurrava sua espinha para uma rígida verticalidade. Tão espesso era o turmo sobre sua cabeça que ele aparentava vestir um arbusto num chapéu de lançador. Ele também chamava a si mesmo por um novo nome — Quos — e ele curava as pessoas em que tocava, deixando uma pilha de vilas cheias de vida no seu caminho a medida que viajava pelas cidades. Muitos o chamavam de Musgossias e choravam sob seus pés, o que molhava os brotos e o levava a germinar no solo. Isto o deixava momentaneamente irritado, ele duramente chacoalhava suas pernas para libertar-se e selvagemente levava suas mãos ao céu, trazendo um trovão de fragmentos de luz sobre estes patéticos

Paij-ree estava distante das odisséias espirituais de seu pai (de fato, pensou o homem morto), então ele apenas viu a decadência da loteria sem a presença de seu capitão. É neste ponto em que Paij-ree foi ao trabalho, revivendo a falecida loteria de sua família.

Jogando com Poucos Dedos

A cidade estava repleta de pessoas que perderam o interessa na loteria. O tempo tinha realmente exaurido a todos. Aquela terrível chuva alagando seus porões. Toda a cidade foi forçada a mover uma estória adiante. Você colocaria a tampa de volta em sua caneta e então arruinaria a caneta, visto que a tampa já estava repleta de lama. Todos estavam esgotados, muitas pessoas afogadas.

Paij-ree gastava seus dias numa quadriliche, o único móvel que permanecia acima do nível dor mar. Ele dormia na cama de cima. A terceira cama também estava seca, então ele deixava uma gaivota desabrigada de sua cratera fazer seu ninho sobre a cama. A gaivota não precisava de toda a cama, então Paij-ree também mantinha seus lápis e calculadores nela.

De início, estes foram tempos muito sombrios para ambos, e eles persistiram em continuar com má aparência o tempo todo. Paij-ree tornou-se obcecado por suas unhas, mantendo-as longas e intocadas, enquanto o resto dele deteriorava sob uma vasta cabeleira. Na companhia de Paij-ree, a gaivota da cratera aprendeu sua própria excentricidade e arrancava todas suas penas do lado direito de seu corpo. Ela se parecia com um diagrama em corte.

Eles aprenderam a ter épocas felizes. Paij-ree entalhou uma flauta a partir da parede usando suas unhas e a tocava frequentemente. Na maioria das vezes ele tocava suas canções relaxantes durante o dia. À tarde, eles batiam na parede e chacoalhavam a estrutura da cama em ritmo com sua música. A gaivota ficou doida quando ele tocou quatro notas determinadas repetidamente. Ele assistia a gaivota em êxtase voando em círculos. Paij-ree mal podia manter sua compostura dado o efeito que tinha aquela pequena melodia. Ele não se agüentava, babando de tanto rir.

Paij-ree chamava a gaivota de Eb-F-F-A (Mi-bemol-Fá-Fá-Lá), depois desta música favorita.

A amizade pode ser um excelente catalisador para o progresso. Um amigo pode encontrar em você características que nenhuma outra pessoa consegue ver. É como se ele procurasse sua pessoa e de algum jeito encontrasse cinco jogos completos de talheres de prata que você nunca soube que estiveram lá. E mesmo que este amigo não entenda porque você tem estes talheres escondidos, é, ainda assim, um grande feito, digno de respeito.

Enquanto Eb-F-F-A não encontrava a prataria, ele havia encontrado uma outra coisa. Uma pilha de uma outra coisa. Visto que Paij-ree estava abandonado sobre a cama quádrupla, a gaivota faria uma exploração em busca de alimento. Um dia ela voou até um barril, flutuando sobre onde ficava o galpão de ferramentas. Eb-F-F-A andou sobre o barril, rolando-o até a casa de Paij-ree e então o quebrou, revelando a coleção perdida de bicos de pato.
Sim, bicos de pato de verdade. (Eb-F-F-A estava esofagizando seus grasnos. mantendo-se calmo, sugando as gotas de suor de volta para sua testa — patos não eram da mesma pena que ele, mas mesmo assim da mesma família.) Paij-ree aplaudiu com alegria, absolutamente, ele pretendia cobrir sua casa com estes bicos, eles poderiam ter contido um pouco da torrente. Provavelmente não muita coisa, nenhum motivo para reclamações.

E a cola do teto estava ao pé do barril e eles eram dois companheiros de beliche empreendedores com tempo livre, então eles fizeram uma balsa com os anteriormente quacáveis lábios. E para fora foram eles, para o interior! Movendo-se através de uma total mistura de cidade e sopa. Quão estranho era atingir uma praia e então descobrir que era apenas a velha e suja estrada que passava pelo trevo de Toffletown.

No interior, eles vendiam. Era sempre uma longa caminhada até a próxima plantação, mas existiam alguns poucos compradores na mansão (“Bem-vindo a Mansão Erguida com Besouros”, diziam eles ou, “A Mansão Erguida com Substitutos do Celofane — você não sabe quão perigoso pode ser o celofane verdadeiro?”) E uma das famílias embrulhavam sobras de gelatina e presunto em algum celofane para os dois viajantes. E eles quase morreram no dia seguinte por causa delas.

Então, quando veio o calor e, como a primeira loteria do interior era à noite, um fazendeiro chamou por eles do seu terreno, enquanto ele estava próximo de uma vaca sua que pastava. Paij-ree e Eb-F-F-A foram até ele, murmurando um ao outro se deveriam oferecê-lo o Bilhete Especial Gasto pelo Vento ou se ele preferiria optar em ganhar o Arriscado Medalhão Original Caseiro Interiorano do Roco.

Mas o fazendeiro lhes acenou a medida que se aproximavam, “Não, deixem suas calculadoras e rodas de probabilidades. É para a minha papa-capim.” Ele quis dizer sua vaca. A versão de Emdertromb: o dobro de carne, duas vezes mais carnuda, não produz leite, produz chapas de papel. Ainda assim, ela pasta.

“Sua papa-capim (poh-kon-ic) quer um bilhete da sorte?” indagou Paij-ree.

“Ela viu vocês e ficou realmente empolgada,” disse o fazendeiro. “Ela não sabe números,
mas ela entende um pouco sobre sorte. Quase foi acertada por um avião senil um dia e,
quando a encontrei, ela apenas levantou os ombros, como se dissesse, ‘Bem, acho que não
foi nada’”

“Toda (shas-op) loteria é numér-(iga-iga)-ica,” afirmou Paij-ree. “Ela sabe (elsh) notas musicais? Minha águia sabe (losh) notas musicais.,” disse Paij-ree. "Paij-ree assobiou para a gaivota da cratera e ela respondeu com um D (Dó) contínuo.

O fazendeiro não podia falar com a consciência musical de sua papa-capim, então Paij-ree enviou a gaivota para descobrir (D-D-D-A-D (Ré-Ré-Ré-Lá-Ré), vá-ensinar-a-vaca) enquanto ele hackeava algumas melodias em sua calculadora.

 class BilheteLoteriaAnimal

   # Uma lista de notas válidas.
   NOTAS = [:Ab, :A, :Bb, :B, :C, :Db, :D, :Eb, :E, :F, :Gb, :G]

   # Armazenas as três notas escolhidas e as datas de compra.
   attr_reader :escolhidas, :comprado

   # Cria um novo bilhete a partir das três notas.  As três notas
   # devem ser únicas.
   def initialize( nota1, nota2, nota3 )
     if [nota1, nota2, nota3].uniq!
       raise ArgumentError, "as três escolhidas devem ser diferentes entre si"
     elsif escolhidas.detect { |p| not NOTAS.include? p }
       raise ArgumentError, "as três escolhidas devem ser notas da escala cromática."
     end
     @escolhidas = escolhidas
     @comprado = Time.now
   end

   # Faz a contagem do resultado (escore) do bilhete contra o resultado do sorteio.
   def escore( final )
     contador = 0
     final.escolhidas.each do |nota|
       contador +=1 if escolhidas.include? nota
     end
     contador
   end

   # Construtor para criar um BilheteLoteriaAnimal aleatoriamente
   def self.novo_aleatorio
     new( NOTAS[ rand( NOTAS.length ) ], NOTAS[ rand( NOTAS.length ) ],
          NOTAS[ rand( NOTAS.length ) ] )
   rescue ArgumentError
     redo
   end

 end

Não há necessidade de os bilhetes para animais se comportarem drasticamente diferente dos bilhetes tradicionais. A classe BilheteLoteriaAnimal é internamente diferente, mas expõe os mesmos métodos vistos na classe BilheteLoteria. O método escore é até mesmo idêntico ao método @score da antiga classe BilheteLoteria.

Ao invés de usar uma variável de classe para armazenar a lista de notas musicais, elas são armazenadas numa constante chamada BilheteLoteriaAnimal::NOTAS. Variáveis mudam e a lista de notas não deveria. Constantes foram projetadas para se manterem. Mesmo assim você pode alterar a constante, mas terá que trapacear ou o Ruby irá chiar.

 irb> BilheteLoteriaAnimal::NOTAS = [:ASSOBIO, :GORJEIO, :BALIDO]
 (irb):3: warning: already initialized constant NOTAS
   => [:ASSOBIO, :GORJEIO, :BALIDO]

A gaivota voltou com a papa-capim, o nome dela era Merphy, ela estava empolgada em tentar a sorte, ela inflou seu rosto sonhador, assobiou cinco ou seis notas em série, todas elas seguraram seu colar, puxaram-na para perto da calculadora e a deixaram respirar três notas, então eles estrangularam o último ar até que seu bilhete estivesse impresso e tudo estava catalogado certinho dentro de @@@bilhetes[‘merphy’]@. Obrigado, vejo você no sorteio!

Então a febre da loteria tornou-se uma epidemia entre as simples mentes dos animais. Paij-ree poupou algum custo, usou a mesma classe SorteioLoteria que ele usaria no ambiente comum da loteria de sua infância. E logo os animais estavam fazendo sua própria música, seus próprios mapas e filmes.

“E Os Originais?” Perguntei a Paij-ree. “Eles devem ter odiado seus animais!”

Ele porém recuou com mau humor e franziu sua testa. “Eu sou um Original. Assim como você. Nós odiamos (ae-o) algum deles?”

Não muito tempo após o término da loteria, Paij-ree sentiu a gaivota da cratera Eb-F-F-A descendo em seu ombro, ela então assobiou um urgente e triste C-Eb-D-C-A-Eb (Dó-Mi Bemol-Ré-Lá-Mi Bemol). Estas notas desesperadas enviaram uma onda de calafrios através do corpo de Paij-ree. Tinha o Deus Rei de Bêbado Solo. Nosso Amado Topiário, o Musgossias Quos, Pai Literal Daquele Homem Quem Era O Instrutor de Órgão da Minha Filha — tinha ele realmente chegado ao seu fim? Como isto poderia acontecer? Poderiam as grandes árvores não mais nutri-lo e guiar os ventos úmidos em sua direção? Ou seu próprio esguio líquen cobriram seu caminho e cresceram obstruindo sua respiração?

Você não liga dizia a canção da gaivota. Ele deteriorou-se e enfraqueceu e caiu na porta iluminada de seu casebre. Seus rebentos torcendo e chorando para que o dia não acabasse. Para que o sol permanecesse fixo e longe e atencioso.

Plor-ian, o criado da casa, deixou que os jarros viessem e Quos manteve-se bem hidratado até que Paij-ree chegou para avaliar os caídos botões de plantas macias e o emergente rosto de seu pai, o capitão da loteria. Sua pele profundamente marcada como um travesseiro cheio de bordados; Grandes galhos saltavam-lhe dos braços agora retraídos com grande sede.

Paij-ree penteou as longas raízes que rodeavam os olhos de seu pai e aquelas que vinham do canto de sua boca. Enquanto eu gostaria de lhe dizer que as lágrimas de Paij-ree rolavam até os braços e poros de seu pai, rejuvenescendo e recuperando o gramado cavalheiro: Não posso dizer isto.

Na verdade, as lágrimas de Paij-ree rolavam até seus braços e caiam no chão de tábuas rangentes, alimentando as desprezíveis ervas daninhas, energizando a matéria negra das plantas, que literalmente saltavam através do chão à noite e sufocavam Nosso Quos. Puxão, rasgo, crack. E este era seu esqueleto.

Depois disso Paij-ree nunca mais poderia ser chamado de Wert-ree ou Wer-plo.

6. Eles que Fazem as Regras

Hannah saltou de volta a parede e apoiou-se em seus dedos.

“Está é a parede,” disse Dr. Cham. “Os Originais estão aí dentro. Minha filha, você pode levar-nos ao convés de observação?”
“Você espera que a gente vá contra estes caras? indagou a cabra. “Eles são doidos como coalas. Mas estes coalas tem lasers!”

“De qualquer forma, nós vencemos. disse Dr. Cham. “Você e eu sabemos disso.”

“Ok, bem, estou confuso em relação a isso”, disse a cabra. “Nós realmente vencemos? Ou podemos estarmos pensando sobre o Kramer contra Kramer? Quem venceu foi o Dustin Hofmman ou fomos nós?”
“Na na ni na não.” Hannah flutuou e nervosamente arrastou suas pernas junto da parede. “Tem um homem com uma cara enorme lá!”

“O Sr. Cara,” disse o Doutor. “Ele é o rosto original.”

“Ele não me viu,” disse Hannah e lamentou-se. HOMA-HOMA-ALLO-ALLO.
Ela fez aquele furo gotejante através dos gastos buracos de rato e das portas de congeladores, fluindo para dentro e para fora, levando os pontos de controles do vídeo a assobiar e os painéis da parede a se atarem a si mesmos e desabarem no silêncio. Os três passaram através dos dois desgastados níveis de segurança e emergiram no convés de observação tendo uma vista panorâmica do compartimento de cargas.

Klon Ooper. Corwood. Sr. Face. Vonblisser.  Os Originais.

“Os últimos vivos entre Os Originais,” disse Dr. Cham. “Você está certa disso, Hannah?” O que, de qualquer modo, ela não escutou, a medida que seus olhos repousavam fixamente nas lendárias criaturas.

“Olhe para eles”, falou a cabra. “Estes caras escreveram o livro das regras, Doutor. Nós devemos tudo a estes caras.”

“E Deus?” disse Dr. Cham.

“Eu realmente não sei,” disse a cabra. “Hannah provavelmente sabe melhor sobre isto do que qualquer um de nós.”

Hannah nada disse. Ela apenas conhecia um outro fantasma e este era seu Mediador Pós-Falecimento, Jamie Huft. Quem parecia não ter qualquer resposta para ela e exigia que as questões fossem enviadas em escrito com um selo auto-endereçável incluso no envelope. Hannah não tinha ainda visto a bola rolar naquela caixa postal.

“Devemos estar no alto das montanhas”, afirmou a cabra. “Vejam só essa escuridão.”

“Eu vi um outro convés como este lá embaixo onde encontramos Hannah,” disse Dr. Cham. “Lá embaixo, perto da sua área de moradia. Você deveria gastar algum tempo para procurá-lo. Lá é bastante pacífico. Você pode ver a Terra e os sete mares.”

“Os sete mares?” A cabra imaginou se isso era próximo ao grupo as Rockettes. Ela leria sua parte no material sobre dança de precisão e veria aquela linha de pernas, caminhado a paços miúdos sobre o palco como um grande, e brilhoso preparador de solo.

Hannah movimentou-se com vida.

Hannah entra em pânico. As rosquinhas estão ao alcance.

Eles não podiam escutá-los, mas viram seus slides.

E nenhum dos três falou quando Os Originais desligaram o projetor de slides e embarcaram num foguete bastante fino que passou fulminante com clareza através de uma rachadura no teto do compartimento de cargas.

“Minha nossa,” disse a cabra.

“O quê?” perguntou Hannah.

“Você vai morrer,” falou a cabra.

Dr. Cham olhou para os controles a frente deles, um longo painel de alavancas acolchoadas e telas verdes.

“Eu já estou morta. Sou um fantasma.”

A cabra encarou o Doutor, que estava explorando o painel de controle. “Ok, bem, se o seu tio não tiver uma conversinha com você, eu vou deixar as coisas bastante claras. Existe uma grande chance de que estes caras vão construir uma bomba. E você vê como estou inquieto? Você vê como meus joelhos estão tremendo?”

“Ahan.”

“Ahan, é o quão real é isto aqui, garota. Eu não me lembro de nada do livro maldito exceto que estes caras estão construindo uma bomba que pode explodir o mundo fantasma. E, uma vez que o mundo fantasma se for, então o Escavador Dosh terá seu segundo retorno. É um negócio que eles calcularam. Inferno, é algo doentio, isto é tudo que você precisa saber.”

“Mas estou morta.”

“Ok, bem, nós estamos conversando, não estamos? Você pode falar, então você está morta?” A cabra chacoalhou a cabeça. “Eu gostaria de me lembrar se nós vencemos ou se foi mesmo o Dustin Hoffman.”

Hannah berrou. "Por que eu tenho que morrer de novo? Ela choramingou, suas pernas estremeceram em descontrole e ela caiu no chão. MOH-MOHHH-MAO-MAOOO.

Dr. Cham tinha puxado com muita força uma alavanca felpuda, o que destravou e fez deslizar, como um porta pão, a tampa de um compartimento. Ele colocou suas mãos lá dentro e encontrou um teclado firmemente preso.

" É isso," disse ele e colocou irb, que apareceu numa tela a esquerda de seu oculto teclado. Ele checou a versão do Ruby.

 irb> RUBY_VERSION
   => "1.8.6"

O Ruby estava atualizado. O que mais ele podia fazer? Escanear constantes e class_variables era inútil. A única razão de ter funcionado com a classe Elevador era porque alguém tinha deixado o irb rodando com suas classes ainda carregadas.

Ele tinha acabado de carregar este irb e nenhuma classe especial estava disponível. Ele tinha que encontrar algumas classes. Ele começou carregando o arquivo `rbconfig` para ter uma idéia de quais eram as configurações do Ruby.

 irb> require 'rbconfig'
   => true
 irb> Config::CONFIG
   => {"abs_srcdir"=>"$(ac_abs_srcdir)", "sitedir"=>"bay://Ruby/lib/site_ruby", ... }

Lá havia muita informação para se analisar. A constante Config::CONFIG é um Hash que contém cada configuração do ambiente usada para ajustar o Ruby. Você pode encontrar o nome do sistema operacional em Config::CONFIG['host_os']. O diretório onde as bibliotecas principais do Ruby são armazenadas pode ser encontrado em Config::CONFIG['rubylibdir']. Os programas Ruby podem armazenar arquivos auxiliares em Config::CONFIG['datadir'].

De qualquer maneira, O que Dr. Cham realmente precisava era uma lista de todas as bibliotecas que não eram bibliotecas principais do Ruby. Bibliotecas que foram instaladas pelos Originais ou quem quer que tenha manejado este console. Ele checou algumas variáveis globais por esta informação.

 irb> $"
   => ["irb.rb", "e2mmap.rb", "irb/init.rb", ... "rbconfig.rb"]
 irb> $:
   => ["bay://Ruby/lib/site_ruby/1.9", "bay://Ruby/lib/site_ruby/1.9/i686-unknown",
       "bay://Ruby/lib/site_ruby", "compartimento://Ruby/lib/1.9", 
       "bay://Ruby/lib/1.9/i686-unknown", "."]

Aha, ótimo. Dr. Cham coçou sua barba e olhou para sua sessão o irb. A variável global $" contém um Array de cada biblioteca que foi carregada com require. A maioria destas bibliotecas foram carregadas pelo irb. Embora ele havia carregado 'rbconfig.rb' a pouco.

A variável global $:, que pode também ser acessada como $LOAD_PATH, contém uma lista com todos os diretórios em que Ruby irá checar quando você tentar carregar um arquivo com require. Quando Dr. Cham rodou require 'rbconfig', Ruby verificou nesta ordem cada um dos diretórios.

 bay://Ruby/lib/site_ruby/1.9/rbconfig.rb
 bay://Ruby/lib/site_ruby/1.9/i686-unknown/rbconfig.rb (*)
 bay://Ruby/lib/site_ruby/rbconfig.rb
 bay://Ruby/lib/1.9/rbconfig.rb
 bay://Ruby/lib/1.9/i686-unknown/rbconfig.rb
 ./rbconfig.rb

O segundo caminho era onde o Ruby acabaria por encontrar o arquivo rbconfig.rb. Dr. Cham supôs que os primeiros cinco caminhos eram caminhos absolutos. Estes eram caminhos para diretórios num disco chamado compartimento. Caminhos absolutos podem variar em seu sistema. No Windows, caminhos absolutos começam com a letra do disco. No Linux, caminhos absolutos começam com uma barra.

O diretório "." indicava um caminho absoluto; O ponto solitário representa o diretório de trabalho atual. O diretório onde Dr. Cham inicializou o irb. Então, depois de Ruby ter procurado em todos locais padrão, ele checou o diretório atual.

A cabra deu uma espiada com sua cabeça ao redor de Dr. Cham e assistia todas estas instruções exalarem, a medida que ele lambia seus lábios para manter suas salivações longe dos monitores e dos brilhosos botões. Ele havia soltado alguns regozijos (nas linhas de: Não, isso não ou Sim, sim, isso mesmo ou Ok, bem, você escolhe), mas agora ele estava completamente envolto, recomendando código, “Tente require 'setup' ou, não, tente 3 * 5. Tenha certeza que a matemática básica funciona.”

“Claro que a matemática funciona,” disse Dr. Cham. “Deixe comigo, eu preciso encontrar algumas classes úteis.”

“É um simples teste de sanidade,” disse a cabra. “Apenas tente. Faça 3 * 5 e veja o que aparece.”

Dr. Cham cedeu.

 irb> 3 * 5
   => 15

“Ok, muito bom! Estamos dentro!” a cabra chacoalhou alegremente sua cara peluda.

Dr. Cham deu um tapinha na cabeça, “Ótimo. Agora podemos continuar.”

 irb> Dir.chdir( "bay://Ruby/lib/site_ruby/1.9/" )
   => 0
 irb> Dir["./*.{rb}"]
   => ['endertromb.rb', 'leitormental.rb', 'fazedorpedidos.rb']

Dr. Cham tinha usado chdir para mudar o diretório atual de trabalho para o primeiro caminho listado no LOAD_PATH. Este primeiro caminho em site_ruby é um lugar comum para armazenar classes personalizadas.

Aqui estavam as três classes lendárias que o instrutor de órgão da minha filha havia anotado para mim anteriormente neste capítulo. E, Dr. Cham, tendo lido o dito capítulo, reconheceu estas três peças do sistema imediatamente.

A classe Endertromb. que continha os mistérios dos poderes deste planeta. A classe LeitorMental que, escaneando as mentes de seus habitantes, lia o conteúdo de cada mente. E, finalmente, a classe crucial FazedorPedidos que permitia a realização de desejos de dez letras, caso o desejo alguma vez encontrasse um caminho para o núcleo de Endertromb.

“O que você acha de 4 * 56 + 9?” perguntou a cabra. “Não sabemos se isso pode fazer expressões compostas.”

“Eu tenho o LeitorMental bem aqui,” disse Dr. Cham. “E eu tenho o FazedorPedidos bem aqui do lado dele. Este planeta pode ler mentes. E este planeta pode fazer pedidos. Agora, vamos ver se ele pode fazer ambos ao mesmo tempo.”

7. Eles Que Viveram o Sonho

Apesar da arte dos Originais ter desaparecido há muito, Dr. Cham trabalhou freneticamente no computador acoplado ao painel de controle sobre o convés de observação. Hannah havia desaparecido dentro do chão (ou talvez aquelas pequenas faíscas ao longo do caminho eram ainda rastros de sua presença paranormal!) e a cabra amigavelmente assistiu Dr. Cham hackear um módulo Ruby.

 require 'endertromb'
 module EscanerPedidos
   def escanear_por_um_pedido
     desejo = self.read.detect do |pensamento|
       pensamento.index( 'pedido: ' ) == 0
     end
     desejo.gsub( 'pedido: ', '' )
   end
 end

“Qual seu plano?” perguntou a cabra. “Parece que eu poderia resolver este problema em umas três linhas.”

“Este Módulo é a nova tecnologia de EscanerPedidos,” disse ele. “O escâner só pega um desejo se ele começa com a palavra pedido, um dois pontos e um espaço. Deste modo o planeta não será preenchido com cada palavra com menos-de-dez-letras que aparecem na cabeça das pessoas.”

“`Por que você simplesmente não usa uma classe?” indagou a cabra.

“Porque um Módulo é mais simples que uma classe. É apenas um aparato de armazenamento para métodos. Ele mantém um grupo de módulos juntos. Você não pode criar novos objetos a partir de um método.”

“Mas você não vai querer um objeto EscanerPedidos, para que você possa realmente usá-lo?” disse a cabra, chocada.

“Eu vou mesclá-lo com o LeitorMental,” disse Dr. Cham. E assim o fez.

 require 'leitormental'
 class LeitorMental
   include EscanerPedidos
 end

“Agora, o módulo EscanerPedidos está mesclado ao LeitorMental,” disse Dr. Cham. “Posso chamar o método escanear_por_um_pedido em qualquer objeto LeitorMental.”

“Então, é um mixin,” disse a cabra. “O mixin LeitorMental.”

“Sim, qualquer módulo que é incluso numa classe com um include é um mixin para esta classe. Se você voltar e olhar para o método escanear_por_um_pedido, verá que ele chama um método self.read. Eu apenas tenho que ter certeza de que, qualquer que seja a classe com que estou mesclando o LeitorMental, ela tenha um método read. Caso contrário, ocorrerá um erro.”

“Isto parece bastante estranho, o fato do mixin precisar de certos métodos que ele já não tem. Parece que ele deveria funcionar por ele mesmo.”

Dr. Cham moveu seus olhos do teclado para a cabra. “Bem, é como sua coleção de vídeos. Nenhuma das suas fitas de vídeo funciona ao menos que você as ponha numa máquina que use fitas de vídeo. Eles dependem um do outro. Um mixin tem alguns requisitos básicos, mas uma vez que uma classe atinge estes requisitos, você pode adicionar toda esta funcionalidade extra a ela.”

“Hey, isso é legal,” disse a cabra.

“Você leu o livro trinta vezes e não pegou isso?” perguntou Dr. Cham.

“Você é bem melhor professor pessoalmente,” disse a cabra. “Eu não pensei que fosse gostar tanto assim de você.”

“Eu compreendo completamente,” disse o Doutor. “Isto é muito mais real do que as tirinhas fazem sê-lo.”

 require 'fazedorpedidos'
 leitor = LeitorMental.new
 pedidor = FazedorPedidos.new
 loop do
   pedido = leitor.escanear_por_um_pedido
   if pedido
     pedidor.realize(pedido)
   end
 end

Irb sentou e rodou o laço na tela. Ele fará isso até que você pressione Control-C. Mas Dr. Cham o deixou rodando. Rodando o laço indefinidamente, escaneando as ondas mentais por um pedido adequado.

E Dr. Cham terminou seu pedido. No começo, ele pensou imediatamente em um garanhão. Para cavalgar em pêlo sobre os vales de Sedna. Mas ele recuou com o pensamento, seu pedido não havia sido formado corretamente. Um garanhão era inútil para perseguir Os Originais, então ele fechou seus olhos novamente, mordeu seu lábio e pensou com si mesmo: pedido: baleia.

Última Baleia para Pessoasenlameadas

A atarracada e mal humorada baleia apareceu na entrada do castelo, onde Hannah estava chacoalhando um botão de rosas com sua mão. Ela golpeou a Baleia com a mão, mas esta apenas permaneceu perfeita, confortável e firme contra o céu sólido e azul de Endertromb.

“Estou entediada,” disse ela a baleia. BOHR-BOHR-OHRRRRRR.

“Ok,” disse a baleia, profundamente e suavemente. Enquanto a palavra deslizava junto de sua pesada língua, suas bordas dividiam-se e a palavra saia polida e vestida numa bolha pelo canto de sua boca.

“Eu sempre tenho que morrer,” disse a jovem fantasma. “As pessoas sempre me matam.”

A baleia sacudiu suas curtas nadadeiras, que se encontravam a uma distância inútil do solo. Então, ela se moveu com esforço em direção a menina com sua cauda. Lançando-se sobre os pedaços de grama.

“As pessoas matam, então, quem elas matam?” disse a menina. “Eu. Elas me matam todas as vezes.”

A baleia conseguiu chegar a três metros da garota onde se erguia como um grande monumento de guerra que representava um número suficiente de soldados mortos a ponto de trazer um ruidoso passo até você. E agora a baleia descansava sua cauda e, exausta pela escalada até então, deixou suas pálpebras se cerrarem tornando-se uma levemente inchada montanha de barro. Sua farta sombra dobrou-se em volta da quase imperceptível Hannah.

Mas outra sombra apareceu, estreita e determinada. Bem atrás dela, a mão veio sobre seu ombro, e o fantasma quente dentro da mão tocou sua manga.

“Como você chegou aqui embaixo?” disse a garota.

Dr. Cham sentou bem do lado dela e o bode deu a volta e sentou em frente.

“Escute aqui,” disse Dr. Cham. “Nós temos que seguir este grupo malvado de vândalos até o fim, Hannah. E para apanhá-los, nós precisamos de sua fiel ajuda!”

“Estou com medo,” chorou Hannah.

“Você não está com medo,” disse o bode. “Vamos. Você é uma criança fantasma intimidante.”

“Bem,” ela disse. “Estou um pouco entediada.”

Dr. Cham se ajoelhou, trazendo sua presença cabeluda para o chão, seu rosto a apenas alguns centímetros do dela. “Se você vier conosco, se você pode acreditar no que sabemos, então poderemos pegar esta trupe revoltante. Agora, você diz que seu destino é ser uma confeiteira. Não vou entrar no mérito. Você tem todo o direito do mundo — e de Endertromb, no caso — de se tornar uma confeiteira. Digamos que, se você não se tornar uma confeiteira, será uma grande tragédia. Quem é que vai cuidar de todos aqueles donuts se não for você?”

Ela deu de ombros. “É isso que eu venho dizendo.”

“Você está certa,” disse o Doutor. “Você vem dizendo isso desde o começo.” Ele olhou para o céu, onde o vento assobiava pacificamente apesar da furada forçada do foguete dos Originais. “Se o seu destino é ser uma confeiteira, então o meu é acabar com tudo isso, acabar com a confusão que está começando a se formar. E escute-me, menina — ouça o quão certa e sólida a minha voz fica quando eu digo isto — eu acabei com sua vida, eu tenho total responsabilidade por sua vida como uma aparição, mas eu a trarei de volta. Vai levar mais tempo que um donut, mas você vai ter uma infância real. Eu prometo.”

Na baleia pedida... indo...

Claro, levou um minuto para o bode cortar seu pedido para dez letras, mas ele logo estava a caminho, seguindo os mesmos rastros no céu, até o Dr. Cham e sua sobrinha fantasma Hannah. Até o grupo de animais vilanescos chamado de Os Originais. Até as Rockettes.

E o Escavador Dosh batia e festejava a cada segundo que eles deixavam para trás.

Virar a página.