<p>why’s (ergreifende) Einführung in Ruby</p>

tenderly written and illustrated by

why the lucky stiff

AttributionShare Alike
Licensed under the Attribution-ShareAlike license.
See http://creativecommons.org/licenses/by-sa/2.0/ for details.


1.

Über das Buch

[o]

Was für eine fantastische Reise!

  1. ein elf mit seinem haustier-schinken!
  2. eine giraffe umringt von weeezards!
  3. mikroskopische kanarienvögel!
    dieses handbuch steckt voller leben!

Sogar Kleinkinder können es.

  1. Live aus dem Jahr 2012
    dank Why’s Ergreifender Einführung…
  2. können soger säuglinge Ruby lernen! so einfach ist das!

Der nachdenkliche Leser.

  1. dieses seltsame buch, Why’s Ergreifende Einführung in Ruby, hat mich tief berührt.
  2. wirklich. ich fühle mich großartig.
  3. als ob ich eine avokado mit mayonnaise im bauch hätte.

Miep.

  1. ich bin klein.
  2. ich erlebe abenteuer.
  3. ok, jetzt musst du mal mit dem buch anfangen!


2.

Kon’nichi wa, Ruby

[o]

1. Öffnen des Buches

Nehmen wir an, du hast dieses Buch geöffnet (obwohl du es vielleicht tatsächlich geöffnet hast), und nun hast du die enorme Zwiebel in der Mitte gefunden. (Der Hersteller hat die Zwiebel dort auf meinen Wunsch hin eingeheftet.)

Du denkst dir: “Wow, da ist ja eine Zwiebel dabei!” (Auch wenn du Zwiebeln nicht unbedingt magst, wirst du sicher die Logistik zu würdigen wissen, die nötig ist, um Gemüse in angeblichen Programmier-Handbüchern zu verstecken.)

Dann fragst du dich: “Moment mal. Ich dachte, das wäre ein Buch über Ruby, diese unglaubliche neue Programmiersprache aus Japan. Auch wenn ich die Logistik zu würdigen weiß, die nötig ist, um Gemüse in angeblichen Programmier-Handbüchern zu verstecken: Warum eine Zwiebel? Was soll ich damit anfangen?”

Nein. Bitte jetzt nicht darüber sinnieren. Du sollst überhaupt nichts damit anfangen. Leg die Zwiebel beiseite und lass sie etwas mit dir tun.

Ich will ehrlich mit dir sein: Ich will, dass du weinen musst. Heulen. Schluchzen. Dieses Buch ist eine ergreifende Einführung in Ruby. Das bedeutet, dass der Code so schön ist, dass man Tränen vergießt. Das heißt herzergreifende Geschichten und düstere Wahrheiten, die dich am nächsten Morgen in den Armen des Buches aufwachen lassen. Den ganzen Tag lang drückst du das Buch an dich. Wenn nötig, mach dir eine Innentasche in deinen Bademantel für Why’s (ergreifende) Einführung in Ruby, so dass du immer und überalle die süße Gesellschaft dieses Buches genießen kannst.

Du musst wirklich wimmern. Wenigstens einmal. Zumindest schniefen. Und wenn nicht, dann wird die Zwiebel für alles sorgen.

2. Die Geschichte mit dem Hund

Probier’s mal mit diesem ergreifenden Stück Text:

Einmal ging ich gerade eine dieser geschäftigen Straßen voller Automärkte entlang (das war kurz nachdem meine Hochzeit abgesagt wurde), als ich einen ausgesetzten Hund auf der Straße fand. So ein wolliger, schwarzer Hund mit grünlich-roten Augen. Da ich mich auch ziemlich ausgesetzt fühlte, nahm ich ein paar Ballons, die am Pfosten eines Automarktes befestigt waren, und machte sie an sein Halsband. Dann entschied ich, dass er mein Hund sein würde. Ich nannte ihn Bigelow.

Wir machten uns auf, um Bigelow ein paar Hundeknochen zu kaufen und danach zu mir nach Hause zu gehen, wo wir uns in Sesseln ausruhen und Gorky’s Zygotic Mynci hören konnten. Ach, und vorher mussten wir noch zu einem Gebrauchtwarenladen, um Bigelow seinen eigenen Sessel zu besorgen.

Aber Bigelow hatte mich nicht als Herrchen akzeptiert. Fünf Minuten später ging dieser blöde Hund in eine andere Richtung und ich fand ihn nie wieder. Wenn er vorher einmal verloren gegangen war, so war er es jetzt zweimal. Also verlangsamte ich meine Schritte hin zu einem Leben mit Hundeknochen und Extrasesseln. Für fünf Minuten hatte ich einen Hund gehabt.

Dieser Benedict Arnold von Hund. Ich saß auf einer Parkbank und warf Kienäpfel nach einer Statue von drei Schafen auf einer Brücke. Danach weinte ich stundenlang. Die Tränen kamen einfach. Hier hast du also etwas Ergreifendes zum warm werden.

Ich frage mich, wo er mit den ganzen Ballons hin ist. Dieser verrückte Hund muss ausgesehen haben wie eine Party auf vier Beinen.

Wenig später hatte ich meinen eigenen Bigelow gefunden. Ich druckte einen Haufen Zeug über Ruby aus. Artikel, die ich im Netz gefunden hatte. Ich überflog sie später auf einer Bahnfahrt nach Hause. Ich blätterte fünf Minuten und gab auf. Nicht überzeugend.

Ich saß da, starrte aus dem Fenster auf die Welt, einen bombastischer Mixer vor Augen, der Graffiti und Eisen verrührt. Diese Welt ist zu große für so eine kleine Sprache, dachte ich. Das arme kleine Ding hat keine Chance. Hat keine Beine zum Stehen. Keine Arme zum Schwimmen.

Ja, da war es. Ein kleiner Mann in einem winzigkleinen Zug (zu der Zeit hatte ich immer noch einen Milchzahn) inmitten von Milliarden Menschen auf einem schwebenden blauen Stein. Wer bin ich, über Ruby zu urteilen? Woher weiß ich, dass ich nicht aus Versehen mein Handy verschlucke und noch am Abend sterbe? Why ist tot, es lebe Ruby.

Der Grabstein:

Was stoppte seine Atmung?
Da schau, es ist ein Samsung!

Mein Glück. Endlich bekomme ich einen guten, langen Schlaf unter der Erde, nur manchmal unterbrochen von Pachelbel’s Kanon aus meinen Bauch.

3. Die Rote Sonne geht auf

Jetzt fragst du dich, wieso ich meine Meinung über Ruby geändert habe. Die Antwort: Es hat einfach ==klick== gemacht. Wir passten zusammen.

So wie wenn du Jemand in der Schule begegnest, und dieser Jemand sieht aus wie ein anderer, der dich als Kind immer mit Pinseln ins Gesicht gehauen hat. Und so, ganz instinktiv, folgerst du, dass Jemand kein Freund sein kann. Du ziepst Jemand an den Haaren. Du legst das Telefon laut auf, wenn Jemand zu der wichtigsten Stelle seiner Geschichte kommen will. Du fährst mit deinen Rollschuhen dort, wo Jemand gerade laufen will!

Und irgendwie, sechs Monate später, sitzen du und Jemand an einem Springbrunnen und ihr plaudert wie die besten Freunde. Jemand sieht gar nicht so sehr wie dein Kindheitsalptraum aus. Du hast den guten Zwilling getroffen. Es hat ==klick== gemacht.

Obwohl ich dir vielleicht die Zähne ausschlagen sollte mit dem ganzen Rummel um Ruby und all den einschlägigen Abkürzungen und Buzzwords, die eng mit Ruby verbunden sind (das Zeug, bei dem deine Chefs und deren Chefs sofort die Ohren spitzen), werde ich dich einfach kosten lassen. Ich werden dich durch etwas Code fallen lassen, nur gelegentlich werde ich ein paar eigene Herzenserfahrungen einwerfen. Es wird ganz einfach und natürlich sein.

Ich sollte dich allerdings ein wenig motivieren. Also, Smotchkkiss, ich werde dir meine drei besten Gründe geben, Ruby zu lernen.

  1. Gesunder Geist.

    Vitamin R. Geht direkt in deinen Kopf. Ruby wird dir beibringen, deine Gedanken durch einen Computer auszudrücken. Du wirst Geschichten für eine Maschine schreiben.

    Kreativ sein, kreative Leute kennen lernen. Kombinieren. Begründen. Intelligent nicken. Die Sprache wird zu einem Werkzeug, um deine Gedanken besser mit der Welt zu verbinden. Ich habe bemerkt, dass viele erfahrene Ruby-Benutzer offenbar klare, objektive Denker sind. (Im Gegensatz zu: extrem befangen und ungehobelt.)

  2. Ein Mann auf einer Insel.

    Ruby wurde in Japan geboren. Das ist ziemlich komisch. Japan ist nicht gerade für seine Software bekannt. Und da Programmiersprachen meist in Englisch geschrieben werden, wer würde eine Sprache aus Japan erwarten?

    Und doch, hier haben wir Ruby. Gegen alle Wetten hat Yukihiro Matsumoto am 24. Februar 1993 Ruby geschaffen. In den letzten zehn Jahren hat er unermüdlich gearbeitet, um Ruby der Weltöffentlichkeit näher zu bringen. Es ist triumphal und edel usw. Unterstütze die Vielfalt. Hilf uns, ein wenig an der Erde zu wackeln.

  3. Frei.

    Ruby zu benutzen kostet nichts. Ruby’s Quellcode steht jedermann zum Ein- und Ausatmen zur Verfügung. Deshalb ist dieses Buch auch kostenlos. Es ist alles Teil eines elephantösen Werbegeschenks, das irgend einen Riesenhaken haben sollte.

    Du denkst, wir wollen dir Staubsauger oder gefälschte Monets andrehen. Du denkst, es wird eine 90-minütige Präsentation geben, bei der am Ende der Besitzer der Firma ankommt und dir einen Vertrag aufdrängelt.

    Nö. Gratis, frei, kostenlos.

Jetzt ist es Zeit, dass das Buch anfängt. Du kannst jetzt deinen Textmarker rausholen und anfangen, jedes Wort anzustreichen, dass dich besonders fasziniert. Ich denke, ich habe genug Haarspray und Falschgeld bei mir, um bis zur letzten Seite durchzuhalten.

4. Wie Bücher anfangen

Falls du jemals ein Buch gelesen hast, dann weißt du, dass kein Buch ohne eine bombastische Menge an Synergie anfangen kann. Ja, Synergie. Vielleicht wusstest du das nicht. Synergie bedeutet, dass du und ich zusammenarbeiten, um das hier zu einem großartigen Lese-Erlebnis zu machen.

Wir fangen das Buch an, indem wir in der Einführung gut miteinander auskommen. Dieses Zusammenspiel, diese Synergie, treibt uns voran durch das Buch, mit mir als Reiseführer. Du gibst mir ein beruhigendes Nicken oder Kichern, um deine Fortschritte zu zeigen.

Ich bin Peter Pan, der deine Hand hält. Komm, Wendy! Der zweite Stern von links und weiter bis zum Morgengrauen.

Ein Problem noch. Ich komme nicht gut mit Leuten klar. Ich kann nicht so gut Händchen halten.

Meine Mitarbeiter werden es dir bestätigen. Auf der Eröffnungsfeier Dieses Buches (die in dem Fußballstadion) hatte ich entdeckt, dass die Gurkensandwiches nicht in Geschirrtüchern serviert wurden. Das Ergebnis war, dass sich die Butter nicht richtig mit den Gurken vermischt hatte… Wie auch immer, jedenfalls habe ich einen Aufstand gemacht und ein paar der Werbe-Lastwagen draußen in Brand gesteckt. Ich habe diesen Scheinwerfer zertrümmert und so weiter. Bis tief in der Nacht hatte ich diese laute, wahnsinnige Lache. Es war ein Riesendurcheinander.

Aber, da ich nicht gut mit Leuten klarkomme, war niemand außer mir zu der Eröffnungsfeier Dieses Buches eingeladen. Es war also nicht wirklich derart peinlich. Ich habe es geheim gehalten, und niemand hat etwas von der ganzen Tortur mitbekommen.

Du musst wissen, dass Synergie in diesem Buch nicht wirklich Synergie bedeutet. Ich kann keine normale Synergie. Nein, in diesem Buch bedeutet Synergie stattdessen Comicfüchse. Ich meine damit: Dieses Buch fängt an mit einer bombastischen Menge an Comicfüchsen.

Und ich zähle auf dich, sie in Synergie zu verwandeln.


3.

Ein kurzer (und hoffentlich schmerzfreier) Ritt durch Ruby (mit Comicfüchsen)

[o]

Auftritt: Füchse.

  1. F: Ich kann nicht glauben, dass ich dafür um 8 aufgestanden bin.
    f: Wem sagst du das.
  2. F: Und überhaupt…Ich hab’ noch keinen Cent gesehen. Sie sagen, ich werde erst bezahlt, wenn das Buch fertig ist.
    f: Ich hab’ 50% im Voraus gekriegt.
  3. F: Diese Gauner!
    f: Ich sag’s dir. Bei diesen Typen geht’s nur auf die harte Tour.

Ja, das sind die beiden. Oh, mein Asthma schon wieder…ich muss kurz mal ein bisschen Medizin einatmen, bin gleich wieder da.

Füchse aus der Büchse.

  1. F: Was sollen diese kleinen Kästen? In was für eine Scheiße sind wir hier reingeraten?
    f: Keine Beine.
  2. F: GROSSER GOTT!! Wo sind meine Beine?!
    f: Tja. Die sind in der Zwischenablage von Photoshop.
  3. F: Und wenn Photoshop abstürzt??
    f: Oh Mann. Bete, dass es OS X ist.

Man hat mir gesagt, dass du für dieses Kapitel am besten einen Mop zur Hand hast; irgendwas, womit du dir dein Gesicht abwischen kannst, wenn dir der Schweiß von der Stirn trieft.

In der Tat werden wir die gesamte Sprache durchgehen. Als wenn man alle Streichhölzer aus einer Packung gleichzeitig anzündet.

1. Sprache und ich MEINE Sprache

Unsere Freunde, die zwei hilflosen Füchse, bemerken endlich die Ernst der Lage.
  1. F: “Ruby ist einfach zu lesen.”
    f: Äh…das ist meine Zeile.
  2. F: Ist das hier getarnte Werbung? So ein Infomercial? Ein Taschenbuch mit Reklame in der Mitte?
  3. f: Unsere Karriere ist voll im Eimer.

Mein Gewissen verbietet mir, Ruby als Computersprache zu bezeichnen. Das würde bedeuten, dass sie vorrangig mit Computerbegriffen arbeitet. Dass die Sprache vor allem für den Computer entworfen wurde. Dass also wir, die Programmierer, Fremde sind, die in die Heimat des Computers einwandern wollen. Es ist die Sprache des Computers, und wir sind Übersetzer für die Welt.

Aber wie nennst du eine Sprache, wenn dein Gehirn anfängt, in dieses Sprache zu denken? Wenn du beginnst, Worte und Redewendungen aus der Sprache zu benutzen, um dich auszudrücken. Nun, der Computer kann das nicht machen. Wie kann es dann eine Computersprache sein? Es ist unsere, wir sprechen sie von Natur aus!

Wir können sie nicht mehr wirklich als Computersprache bezeichnen. Sie ist Programmierersprache. Sie ist die Sprache unserer Gedanken.

Lies folgendes Beispiel laut vor.

5.times { print "Odelay!" }

In englischen Sätzen sind Satzzeichen (Punkte, Klammern, Satzzeichen) stumm. Satzzeichen geben den Wörtern zusätzliche Bedeutung, sie helfen uns, den Sinn des Satzes zu verstehen. Also lesen wir das Beispiel als: Five times print “Odelay!”.Drucke fünf mal “Odelay!”.

Und genau das tut dieses kleine Ruby-Programm. Beck’s mutierter spanischer Ausruf wird fünfmal auf den Bildschirm geschrieben.

Lies folgendes Beispiel laut vor.

exit unless "restaurant".include? "aura"

Kurze Anmerkung des Übersetzers: Die deutsche Sprache eignet sich sehr schlecht zum Übersetzen dieser Codes, da ihr Satzbau sich vom englischen massiv unterscheidet. Ich hoffe, dass der Leser der englischen Sprache mächtig ist und die Beispiele im Original genießen kann.

Hier machen wir einen kleinen Praxis-Test. Unser Programm wird sich beenden (exit), es sei denn (unless – Englisch für “es-sei-denn”, “wenn-nicht”; ein Wort, das es im Deutschen nicht gibt) das Wort restaurant enthält (include?) etwas, und zwar das Wort aura. Nochmal, auf Englisch: Exit unless the word restaurant includes the word aura. Nochmal, auf Deutsch: Beenden, wenn das Wort Restaurant nicht das Wort aura enthält.

Hast du jemals eine Programmiersprache gesehen, die Fragezeichen so effektiv einsetzt? Ruby benutzt Satzzeichen wie Ausrufe- und Fragezeichen, um die Lesbarkeit des Codes zu erhöhen. Im obigen Code fragen wir etwas; warum das nicht auch deutlich machen?

Lies folgendes Beispiel laut vor.

['toast', 'käse', 'wein'].each { |wort| print wort.capitalize }
['toast', 'cheese', 'wine'].each { |food| print food.capitalize }

each (engl. jedes) und capitalize (engl. groß schreiben) werden nicht übersetzt, weil es sich um Ruby-Standardfunktionen handelt.

Obwohl dieses Codestück weniger lesbar und satzartig ist als die vorigen, schlage ich dir vor, es laut vorzulesen. Obwohl Ruby manchmal wie Englisch aussieht, ist es eher eine Art Kurz-Englisch. Vollständig ins Englische übersetzt könnte man das Beispiel so lesen: With the words ‘toast’, ‘cheese’, and ‘wine’: take each food and print it capitalized. Oder auf Deutsch: Mit den Wörtern ‘toast’, ‘käse’ und ‘wein’: nimm jedes Wort und drucke es in Großschreibung.

Der Computer antwortet höflich: 'Toast, 'Käse und 'Wein.

An diesem Punkt fragst du dich vielleicht, wie diese Wörter zusammenarbeiten. Smotchkkiss fragt sich, was der Punkt und die geschweiften Klammern bedeuten. Ich werde die verschiedenen Wortarten im Folgenden behandlen.

Alles, was du im Moment wissen musst, ist: Ruby ist grundsätzlich aus Sätzen aufgebaut. Es sind nicht wirklich englische Sätze. Es sind kurze Zeilen aus Worten und Zeichen, die einen einzelnen Gedanken wiedergeben. Aus diesen Sätzen können Seiten werden. Oder Bücher. Sie können ganze Romane ergeben, wenn man sie zusammenhängt. Romane, die von Menschen gelesen werden können, aber ebenso von Computern.

2. Die Wortarten

Wie ein Stinktier auf dem Rücken einen weißen Streifen trägt, oder eine Braut einen wehenden weißen Schleier, so haben auch viele Wortarten in Ruby sichtbare Erkennungsmerkmale. Zeichensetzung und Groß-/Kleinschreibung werden dir helfen, Codestücke zu sehen und sofort wiederzuerkennen. Dein Verstand wird häufig rufen: Hey, dich kenn’ ich doch! Außerdem wirst du in der Lage sein, den Rubyisten-Jargon zu verstehen.

Versuch, dich auf die Optik der einzelnen Wortarten zu konzentrieren. Im Rest des Buches werden die Besonderheiten vertieft. Ich werde jede Wortwart kurz Beschreiben, aber du musst die Beschreibung nicht sofort verstehen. Am Ende des Kapitels solltest du in der Lage sein, alle Wörter eines Ruby-Programms zu erkennen.

Variablen

Jedes einfache, kleinbuchstabige Wort ist in Ruby eine Variable. Variablen können aus Buchstaben, Ziffern und Unterstrichen bestehen.

Zum Beispiel x, y, banane2 oder wachtel_am_apparat.

Variablen sind wie Spitznamen. Erinnerst du dich noch, wie alle dich Stink-Peter genannt haben? Irgend jemand rief: “Stink-Peter, komm mal her!” Und irgendwie wussten alle: Stink-Peter, das bist du.

Mit Variablen kannst du etwas, das du häufig benutzt, einen Spitznamen geben. Nehmen wir mal an, du hast ein Waisenhaus. Ein richtig verarmtes Waisenhaus. Und jedesmal, wenn Herr F. Starkbier kommt, um noch ein paar Kinder zu kaufen, bestehst du darauf, dass er einhunderteinundzwangzig Euro und acht Cent für den Teddy des Kindes bezahlt, an dem sich das Kind in den dunkleren Stunden seines alptraumartigen Lebens festhalten möchte.

teddy_steuer = 121.08

Später rufst du ihn an die Kasse (eine frisierte Registrierkasse mit Ruby!) Du musst die fälligen Gebühren zu einem total zusammenrechnen.

total = waisen_steuer + teddy_steuer + trinkgeld

Diese Variablen-Spitznamen sind hilfreich. Und im zwielichtigen Kinderhändlermilieu wird jede Hilfe gebraucht, denke ich.

Sie machen sich über meine Beispiele lustig.
F: Mann, seine Beispiele sind krank.
f: Psst. 121,08 € sind keine schlechte Teddysteuer.

Zahlen

Der einfachste Zahlentyp ist Integer (Ganze Zahl), eine Ziffernkette, die mit einem Plus- oder Minuszeichen beginnen kann.

Beispielsweise 1, 23 und -10000.

Punkte sind nicht erlaubt, aber dafür Unterstriche. Wenn du also die Tausender abgrenzen möchtest, um die Zahl lesbarer zu machen, nimm den Unterstrich:

einwohner = 12_000_000_000

Dezimalzahlen werden in Ruby Floats genannt. Floats sind Ziffernketten mit Nachkommastellen und/oder einem Exponenten.

Punktierte Anmerkung des Übersetzers: Im Englischen, Japanischen und in Ruby trennt man Dezimalzahlen mit einem Punkt anstatt mit einem Komma ab. Ab jetzt also Nachpunktstellen.

Beispiele sind 3.14, -808.08 und 12.043e-04.

Strings

Delikate Anmerkung des Übersetzers: Mein Beileid allen Informatiklehrern, die jedes Jahr ausgelacht werden, wenn sie ihren Schülern etwas über Strings (englisch string = Faden, Kette, Saite) erklären wollen. Um das klarzustellen: Es geht hier nicht um Reizwäsche und Badehöschen. Es geht einfach nur um Zeichenketten. seufz

Strings sind beliebige Zeichen (Buchstaben, Ziffern, Satzzeichen) in Anführungsstrichen. Man benutzt sowohl einfache als auch doppelte Anführungsstriche, um Strings zu erzeugen.

Beispiele: "Unterwasserlabor", '2021' oder "Diese Comics sind zum Totlachen!".

Wenn du Zeichen in Anführungsstriche setzt, werden sie zusammen in einem String gespeichert.

Denk an einen Reporter, der das Gebrabbel irgendeines Stars notiert: “Ich bin jetzt viel schlauer”, sagt Avril Lavigne. “Jetzt weiß ich, wie das im Business läuft—was man tun muss und wie ich weiterkomme.”

 avril_zitat = "Ich bin jetzt viel schlauer.
 Jetzt weiß ich, wie das im Business läuft --
 was man tun muss und wie ich weiterkomme."

Genauso, wie wir eine Zahl in der Variable teddy_steuer gespeichert haben, speichern wir jetzt eine Zeichenkette (String) in der Variable avril_zitat. Der Reporter schickt das Zitat an die Druckerei, die zufälligerweise Ruby zur Steuerung ihrer Druckpresse benutzt.

 print oprah_zitat
 print avril_zitat
 print ashlee_simpson_debakel

Sie wollen unbedingt in meine Beispiele.
F: Ruf mal irgendwas! Vielleicht benutzt er es für seine Beispiele!
f: Was denn? Sowas wie “Chunky Bacon”?

Chunky Anmerkung des Übersetzers: Da “Chunky Bacon” inzwischen Kultstatus erreicht hat, werde ich den Teufel tun, es zu übersetzen!

Symbole

Symbole sind Wörter, genau wie Variablen. Sie bestehen ebenfalls aus Buchstaben, Ziffern und Unterstrichen. Aber sie fangen mit einem Doppelpunkt an.

:a, :b oder :ponce_de_leon sind Beispiele.

Symbole sind leichter als Strings. Sie werden dort benutzt, wo man einen String braucht, den man nicht auf dem Bildschirm ausgeben will.

Man könnte sagen, ein Symbol ist ein bisschen einfacher für den Computer. Es ist wie ein Verdauungsmittel. Der Doppelpunkt deutet die kleinen Bläschen an, die aus dem Bauch deines Computers aufsteigen, während er das Symbol verdaut. Ah. Süßes Gefühl der Erleichterung.

Chunky bacon!!

Konstanten

Konstanten sind Wörter, wie Variablen, aber sie werden groß geschrieben. Wenn Variablen die in Ruby die Substantive sind, dann kannst du dir Konstanten als Eigennamen vorstellen.

Time, Array oder BunnyLakeIstVerschwunden zum Beispiel.

Im Deutschen werden Eigennamen groß geschrieben. Das Brandenburger Tor. Du kannst das Brandenburger Tor nicht einfach umherschieben. Du kannst nicht mal eben entscheiden, dass das Brandenburger Tor irgend etwas anderes sei. Eigennamen sind so. Sie bezeichnen etwas ganz Bestimmtes und verändern sich normalerweise nicht mit der Zeit.

Ebenso können Konstanten nicht verändert werden, nachdem man sie gesetzt hat.

BrandenburgerTor = "Straße des 17. Juni, Berlin-Mitte"

Wenn wir versuchen, diese Konstante zu verändern, wird Ruby sich beschweren. Sowas wird nicht gern gesehen.

Komm schon, chunky bacon.
F: Komm schon. Echt jetzt. Chunky Bacon.
f: Chunky. Bacon.

Methoden

Wenn Variablen und Konstanten die Substantive sind, dann sind Methoden sie Verben. Methoden werden üblicherweise an Variablen angehängt, mit einem Punkt. Du hast Methoden schon in Aktion gesehen.

zauntor.oeffnen

Oben ist oeffnen eine Methode. Es ist die Aktion, das Verb. Manchmal wirst du verkettete Aktionen sehen.

zauntor.oeffnen.schliessen

Wir haben dem Computer aufgetragen, das Zauntor zu öffnen und dann sofort wieder zu schließen.

zauntor.offen?

Das ist auch eine Aktion. Wir haben dem Computer gesagt, er soll nachschauen, ob das Tor offen ist. Die Methode könnte auch zauntor.schau_nach_ob_es_offen_ist heißen, aber offen? ist kurz und passt auch. Sowohl Ausrufezeichen als auch Fragezeichen können in Methodennamen benutzt werden.

Argumente für Methoden

Eine Methode braucht manchmal noch zusätzliche Informationen, um ihre Aktion auszuführen. Wenn wir wollen, dass der Computer das Tor streicht, sollten wir ihm auch eine Farbe angeben.

Argumente werden ans Ende der Methode angehängt. Sie werden normalerweise in Klammern eingeschlossen und mit Kommas getrennt.

zauntor.streichen( 3, :rot )

Das streicht das Zauntor 3 Schichten in Rot.

Es ist wie ein Korb, gefüllt mit den zusätzlichen Informationen, den die Methode mit sich herumträgt. Die Klammern sind die Henkel des Korbs. Die Kommas sind die Füße der Argumente, die aus dem Korb herausgucken. Das letzte Argument hast seine Füße eingezogen, so dass man sie nicht sieht.

Man kann die Körbe auch aneinanderhängen.

zauntor.streichen( 3, :rot ).trocknen( 30 ).schliessen()

Das streicht das Zauntor in 3 roten Schichten an, lässt es 30 Minuten trocken, und schließt es. Obwohl die letzte Methode keine Argumente hat, kannst du trotzdem Klammern setzen, wenn du magst. Es macht keinen Sinn, einen leeren Korb mit dir herum zu tragen; darum lässt man die Klammern normalerweise weg.

Einige Methoden (wie print) sind Kernel-Methoden. Diese Methoden werden in ganz Ruby verwendet. Weil sie so grundlegend sind, benutzen wir keinen Punkt.

print "Siehst du, kein Punkt."

Klassenmethoden

Genau wie die eben beschriebenen Methoden (auch Instanzmethoden genannt) werden auch Klassenmethoden an Variablen oder Konstanten angehängt. Statt eines Punktes benutzt man einen doppelten Doppelpunkt.

Tor::new( :eiche )

Wie du siehst, wird die Klassenmethode new (“neu”) oft benutzt, um Dinge zu erzeugen. Im obigen Beispiel bitten wir Ruby, ein neues Tor auch Eiche zu bauen. Natürlich braucht Ruby dazu das Wissen, wie man ein Tor baut—und einen Stapel Holz, ein paar Holzarbeiter und diese lagen, wackeligen Zweimannsägen.

Chunky Bacon bis zum Abwinken.

Globale Variablen

Globale Variablen beginnen mit einem Dollarzeichen.

Beispiel: $x, $1, $chunky und $CHunKY_bACOn.

Die meisten Variablen sind eher kurzlebig. Manche Teile deines Programms sind wie kleine Häuser. Du gehst rein und sie haben ihre eigenen Variablen. In einem Haus steht papa vielleicht für Archibald, den Handelsreisenden und Skelettsammler. In einem anderen Haus könnte papa Peter repräsentieren, den Löwendompteur mit einer Schwäche für Flanel. Jedes Haus hat seinen eigenen papa.

Mit globalen Variablen kannst du sicherstellen, dass eine Variable in jedem Haus gleich ist. Das Dollarzeichen passt gut. Jeder Haushalt in Amerika respektiert den Wert des Dollars. Die sind verrückt nach dem Zeug. Versuch es mal, klopf an irgend eine amerikanische Tür und biete ihnen Geld an. Ich kann dir versichern, dass die Leute anders reagieren, wenn du ihnen Peter anbietest, den Löwendompteur mit einer Schwäche für Flanel.

Globale Variablen können überall im Programm benutzt werden. Sie geraten niemals außer Sicht.

Instanzvariablen

Variablen, die mit einem at-Zeichen beginnen, sind Instanzvariablen.

Beispiele sind @x, @y sowie @das_ist_die_chunkychste_scheibe_bacon_die_ich_je_gesehen_habe.

Diese Variablen werden oft benutzt, um Eigenschaften (“Attribute”) zu definieren. Zum Beispiel könntest du Ruby die Breite vom zauntor angeben, indem du die Variable @breite innerhalb von zauntor setzt. Instanzvariablen werden in Ruby dazu verwendet, die Eigenschaften eines Objekts zu definieren.

Stell dir vor, das at-Zeichen steht für Attribut.

Klassenvariablen

Variablen, die mit einem doppeltem at beginnen, sind Klassenvariablen.

Zum Beispiel: @@x, @@y oder @@ich_nehme_euren_chunky_bacon_und_adoptiere_euch_zwei.

Klassenvariablen werden ebenfalls dazu benutzt, Attribute zu definieren. Aber anstatt ein Attribut für ein einzelnes Ruby-Objekt zu definieren, setzen Klassenvariablen die Eigenschaften für viele verwandte Objekte. Wie Instanzvariablen einem einzelnen zauntor Eigenschaften zuweisen, so setzen Klassenvariablen die Attribute für jedes Tor.

Das doppelte at kann für Attribut aller stehen. Zusätzliche kannst du dir einen Schwarm AT-ATs aus Star Wars vorstellen, die alle unter Rubys Kommando stehen. Du änderst eine Klassenvariable, und nicht nur eine, sondern alle ändern sich.

Juchu! Mission Chunky Bacon abgeschlossen!
F: Juchu! Ich hab keine Ahnung was Chunky Bacon ist, aber wir haben’s geschafft!
f: Wir sind im Buch!

Blöcke

Ein Block ist Code in geschweiften Klammern.

2.times { print "Ja, ich habe Chunky Bacon in meinen Beispielen benutzt, aber das war das letzte Mal!" }

Mit Blöcken kannst du eine Reihe von Befehlen gruppieren, um sie in deinem Programm hin- und herzuschieben. Die geschweiften Klammern erinnern an die Zangen einer Krabbe, die den Code gepackt hat und zusammenhält. Wenn du diese zwei Zangen siehst, denk daran, dass der Code dazwischen zu einer einzelnen Einheit komprimiert wurde.

Es ist wie eine dieser “Hello Kitty”-Schachteln, die sie im Supermarkt verkaufen, gefüllt mit winzigen Stiften und mikroskopisch kleinem Papier, alles in eine glitzernde, durchsichtige Mappe gestopft, die du unter deinem Palm verstecken kannst, um geheime Transaktionen durchzuführen. Außer, dass man hier nicht so schielen muss.

Die geschweiften Klammern können auch durch die Worte do und end ersetzt werden, was bei mehrzeiligen Blöcken besser aussieht.

 loop do
   print "Viel besser." 
   print "Ah.  Mehr Platz!" 
   print "Mein Rücken hat mich beinahe umgebracht in diesen Krabbenzangen." 
 end

Blockargumente

Blockargumente (oder Blockvariablen) sind mehrere Variablen in senkrechten Strichen, getrennt durch Kommas.

Als Beispiele: |x|, |x,y| und |in_ulm, um_ulm, um_ulm_herum|.

Blockargumente stehen am Anfang eines Blocks.

{ |x,y| x + y }

In diesem Beispiel sind |x,y| die Argumente. Nach den Argumenten kommt ein Stück Code. Der Ausdruck x + y addiert die beiden Argumente.

Stell dir die beiden senkrechten Striche als Tunnel vor. Sie erwecken den Eindruck einer Rutsche, auf der die Variablen nach unten gleiten. (Das x streckt alle Viere von sich, während das y brav die Beine kreuzt.) Diese Rutschbahn agiert als Verbindung zwischen dem Block und der Welt um ihn herum.

Variablen werden über diese Rutsche (oder diesen Tunnel) in den Block übergeben.

Und dann: Die düstere Realität.
F: Ich habe keine Frau. Keine Kinder. Ich werde keine Erben haben.
Das einzige von mir, an das sich die Welt erinnern wird, ist Chunky Bacon.
f: Autsch.

Bereiche

Ein Bereich (englisch range) sind zwei Werte in Klammern, verbunden mit einer Ellipse (Punkt-Punkt oder Punkt-Punkt-Punkt.)

(1..3) ist ein Bereich, der die Zahlen zwischen 1 und 3 darstellt.

('a'..'z') ist ein Bereich, der die Kleinbuchstaben repräsentiert.

Stell sie dir als Akkordeons vor, die man für den Transport zusammengefaltet hat. (Natürlich kannst du ein tolles Selbstwertgefühl aufbauen, wenn du ausgefaltete Akkordeons mit dir herumträgst. Aber manchmal muss man in Selbstzweifeln versinken und sie in der Transportbox verstecken.) Die Klammern sind die Griffe an den Seiten dieses kleineren Taschen-Akkordeons. Die Punkte sind die Kette, die den Balg zusammenhält.

Normalerweise benutzt man nur zwei Punkte. Wenn man den dritten Punkt dazunimmt, wird der letzte Wert des Bereichs ausgenommen.

(0...5) steht für die Zahlen von 0 bis 4.

Wenn du diesen dritten Punkt siehst, denke an ein leicht geöffnetes Akkordeon, gerade weit genug geöffnet, um einen Ton zu spielen. Dieser Ton ist der letzte Wert; er wird vom Wind hinfort geweht.

Arrays

Erzieherische Anmerkung des Übersetzers: Der Begriff des Arrays, englisch (Daten-)Feld oder Matrix, wird so häufig im Original verwendet, dass er mittlerweile zum Vokabular jedes Programmierers gehört. Ich weigere mich, Array mit Feld zu übersetzen, und überlasse das Wort den Bauern, Physikern und Fußballspielern im Land.

Ein Array ist eine kommagetrennte Liste in eckigen Klammern.

[1, 2, 3] ist ein Array von Zahlen.

['Mantel', 'Handschuhe', 'Snowboard'] ist ein Array von Strings.

Stell dir Array wir eine Raupe vor, die in deinen Code eingeheftet wurde. Die beiden Klammern halten die Raupe fest, so dass du im Auge behalten kannst, wo der Kopf und wo der Schwanz ist. Die Kommas sind die Beinchen der Raupe, die zwischen ihren einzelnen Körpersegmenten baumeln.

Es war einmal eine Raupe, deren Beine Kommas waren. Das bedeutete, dass sie sich nach jedem Schritt eine Atempause genehmigte. Die anderen Raupen bewunderten sie dafür und sie entwicklete einen ziemlich dominanten Charakter. Oh, und was für ein Philanthrop sie war! Sie war berühmt dafür, frische Blätter an die weniger Erfolgreichen zu verteilen.

Ja, ein Array ist eine Sammlung von Dingen, aber es hält diese Dinge auch in der gegebenen Reihenfolge.

Hashes

Ein Hash (englisch Gehacktes) ist eine Art Wörterbuch in geschweiften Klammern. Wörterbücher ordnen Wörtern Erklärungen zu; Ruby tut das mit Pfeilen, bestehend aus einem Ist-Gleich- und einem Größer-Als-Zeichen.

{'A' => 'Aasgeier', 'B' => 'Bachstelze'}, um ein Beispiel zu geben.

Dieses Mal stellen die Klammern kleine Bücher dar: Siehst du, wie sie kleinen, offenen Büchern mit einem Bund in der Mitte ähneln? Sie stehen für das Öffnen und Schließen unseres Wörterbuches.

Stell dir vor, unser Buch hat einen Eintrag pro Seite. Die Kommas sind die Seitenecken, die wir umblättern, um die nächsten Seite zu lesen. Und auf jeder Seite steht ein Wort, gefolgt von einem Pfeil auf die Erklärung.

 {
   'Name' => 'Peter',
   'Beruf' => 'Löwendompteur',
   'Schwäche' => 'Flanel'
 }

Ich vergleiche Hashes nicht mit Wörterbüchern, weil man darin nur Erklärungen speichern könnte. Im letzten Beispiel habe ich perönliche Informationen über Peter gespeichert, den Löwendompteur mit einer Schwäche für Flanel. Hashes sind wie Wörterbücher, weil man sie sehr leicht durchsuchen kann.

Im Gegensatz zu Arrays werden die Einträge in einem Hash nicht in einer bestimmten Reihenfolge gespeichert.

Die Füchse glauben, dass Stille den Comic töten würde.

  1. F: Langsam fühle ich mich in diesem Comic ziemlich eingeklemmt. Ist das ein Dauercomic?
    f: Wie die Peanuts?
  2. f: Vielleicht…verschwindet es, wenn wir leise sind.

Reguläre Ausdrücke

Ein Regulärer Ausdruck (englisch regular expression oder regexp) ist eine Zeichenkette in Schrägstrichen.

Um Beispiele zu nennen: /ruby/, /[0-9]+/ oder /^\d{3}-\d{3}-\d{4}/.

Reguläre Ausdrücke suchen Wörter oder Muster in Texten. Die Schrägstriche an den Seiten sind Stecknadeln.

Stell dir ein kleines Wort mit Stecknadeln an der Seite vor, dass du über ein Buch hältst. Du gehst damit langsam über den Text, und wenn es in die Nähe eines passenden Wortes kommt, fängt es an zu blinken. Du heftest den regulären Ausdruck in das Buch, genau über die Fundstelle, und die Buchstaben leuchten auf.

Ach, und wenn du die Nadeln in das Buch piekst, niest das Papier: reg-exp!

Regexen sind viel schneller, als du die Buchseiten mit dem Finger abzusuchen kannst. Ruby kann eine Regexp benutzen, um ganze Buchbände schnell zu durchsuchen.

Operatoren

Die unten aufgelisteten Operatoren werden in Ruby benutzt, um zu rechnen oder zu vergleichen. Überfliege sie mal, ein paar erkennst du sicher wieder. Du weißt schon, Addition + und Subtraktion - und so weiter.

 ** !  ~  *  /  %  +  -  &  
 << >> |  ^  >  >= <  <= <=>
 || != =~ !~ && += -= == ===
 .. ... not and or          

Keywords (Schlüsselworte)

Ruby hat einige eingebaute Worte voller einzigartiger Bedeutung. Diese Worte können nicht als Variablen benutzt werden oder für deine Zwecke verändert werden. Ein paar haben wir bereits besprochen. Sie sind in einem sicheren Haus, mein Freund. Rühr’ sie an und du kriegst einen offiziellen Syntaxfehler.

 alias   and     BEGIN   begin   break   case    class   def     defined? 
 do      else    elsif   END     end     ensure  false   for     if 
 in      module  next    nil     not     or      redo    rescue  retry 
 return  self    super   then    true    undef   unless  until   when 
 while   yield 

So weit, so gut. Dies ist die erlesene Gesellschaft der Sprache Ruby. Die nächsten drei Kapitel werden eine richtige Vergnügungsfahrt: Wir kleben die Einzelteile zusammen zu originellen Häppchen (ergreifenden) Codes.

Ich empfehle dir, die Wortarten nochmal zu überfliegen. Schaff dir einen guten Überblick. Im nächsten Abschnitt werde ich dich testen.

Out in the pickup truck.

  1. F: Ist dir aufgefallen, dass dieses Buch im Wesentlichen von einem Mondsüchtigen geschreiben wurde?
    f: Jepp.
  2. F: Ernsthaft, er ist hyperaktiv. Wenn er sich weiter so hetzt, wird er ziemlich schnell ausgebrannt sein.
  3. f: Ausgebrannt? Er wird sich in den Kopf schießen, sobald er 30 ist.

3. Falls ich dich noch nicht genug verhätschelt habe

Ich bin stolz auf dich. Jeder wird dir bestätigen, wie ich mit dir prahle. Wie ich ständig von dieser unglaublichen anonymen Person da draußen rede, die scrollt und liest und scrollt und liest. “Diese Kinder”, sage ich ihnen. “Mann, diese Kinder haben ein echtes Herz. Ich habe nie…” Und ich kann den Satz nicht mal zu Ende bringen, weil ich nur noch am Flennen bin.

Und mein Herz scheint rot durch meine filigrane Haut und sie müssen mir 10ccm JavaScript verabreichen, um mich zurückzuholen. (Ich spreche ziemlich gut an auf Gift im Blut.) Mann, das Zeug haut dir die Pfirsische aus den Kiemen!

Na gut. Du hast dich gut gehalten. Aber jetzt muss ich anfangen, der brutale Oberlehrer zu sein. Ich brauche gute Noten von dir. Bisher hast du nicht mehr getan als mit deinen Augen herumzuwackeln. Sicher, du hast vorhin Unglaubliches geleistet, beim laut vorlesen. Jetzt, Smotchkkiss, brauchen wir ein paar Typ-2-Fertigkeiten (Verstehen).

Lies die benutzen Wortarten laut vor.

5.times { print "Odelay!" }

Vielleicht deckst du diesen Absatz beim Lesen lieber zu, weil dein Blick zur Antwort abschweifen könnte. Wir haben eine Zahl 5, gefolgt von einer Methode .times. Dann die erste Krabbenzange eines Blocks. Die Kernel-Methode print hat keinen Punkt und bekommt einen String "Odelay!". Die zweite Zange schließt den Block.

Lies die benutzen Wortarten laut vor.

exit unless "restaurant".include? "aura"

Genau wie print ist auch exit eine Kernel-Methode. Wenn du bei der großen Liste mit den Schlüsselworten aufgepasst hast, weißt du, dass unless ein Schlüsselwort ist. Der String "restaurant" schmiegt sich an die Methode include?. Und zum Schluss der String "aura".

Lies die benutzen Wortarten laut vor.

 ['toast', 'käse', 'wein'].each do |wort|
     print( wort.capitalize )
 end

Diese Raupe ist ein echter Feinschmecker. Das Beispiel beginnt mit einem Array. Es enthält drei Strings ‘Toast’, ‘Käse’ und ‘Wein’. Dem Array folgt eine Methode each.

In einem Block finden wir das Block-Argument wort, das auf seine kleine Wasserrutsche in den Block flutscht. Die Methode capitalize wandelt den ersten Buchstaben des Wortes in Großbuchstaben um, das zur Variable wort geworden ist. Der umgewandelte String wird an die Kernel-Methode print weitergegeben.

Schau dir die Beispiele nochmal an, bis du sicher bist, die Einzelteile der Sprache erkannt zu haben. Sie haben alle ihre typischen Merkmale, nicht wahr? Atme tief durch und massiere deine Schläfen. Nun lass und ein wirklich dickes Codestück auseinander nehmen.

4. Ein Beispiel, um erwachsen zu werden

Platzangst.

  1. F: Junge, ich kriege Platzangst. Ich hätte meine Metallsäge mitbringen sollen.
    f: Ja, hol uns hier raus.
  2. F: Näh. Die ist draußen in meinem Pickup.
  3. f: Hey! Da fährt ein Pickup!

Lies die benutzen Wortarten laut vor.

 require 'net/http'
 Net::HTTP.start( 'www.ruby-lang.org', 80 ) do |http|
     print( http.get( '/en/LICENSE.txt' ).body )
 end

Die erste Zeile ist ein Methodenaufruf. Die Methode require wird benutzt. Ein String mit dem Inhalt 'net/http' wird ihr übergeben. Diese erste Zeile ist sozusagen ein Satz: Wir haben Ruby gesagt, sie soll ein bisschen Hilfscode laden, nämlich die Bibliothek Net::HTTP.

Die nächsten drei Zeilen gehören zusammen. Die Konstante Net::HTTP stellt die Bibliothek dar, die wir oben geladen haben. Wir benutzen daraus die Methode start. In die Methode senden wir einen String 'www.ruby-lang.org' und die Zahl 80.

Das Wort do öffnet einen Block. Der Block hat eine Blockvariable http. Im Block wird die Methode print aufgerufen. Was wird gedruckt?

Die Variable http hat eine Methode get, die wir aufrufen. In get schicken wir einen String mit dem Pfad '/en/LICENSE.txt'. Jetzt siehst du eine weitere Methode, die an get angehängt wurde: Die Methode body. Dann wird der Block mit end geschlossen.

Alles klar? Nur aus Neugier: Erkennst du, was das Beispiel tut? Hoffentlich siehst du ein paar Muster in Ruby. Wenn nicht, schüttle ein paarmal heftig den Kopf, mit dem Beispiel darin. Der Code sollte in handliche Teile zerfallen.

Zum Beispiel wird dieses Muster ein paarmal verwendet:

Variable . Methode ( Argumente )

Du siehst es innerhalb des Blocks:

http.get( '/en/LICENSE.txt' )

Wir benutzen Ruby, um eine Website zu holen. Du hast HTTP vermutlich schon mit deinem Browser benutzt. HTTP ist das Hypertext Transfer Protocol. HTTP wird benutzt, um Websites über das Internet zu transportieren. Stell dir einen Busfahrer vor, der durch das Internet fährt und uns Websites zurückmitbringt. Auf seiner Mütze stehen die Buchstaben HTTP.

Die Variable http ist dieser Busfahrer. Die Methode ist eine Nachricht (engl. message) an den Busfahrer: Gehe etwas holen (engl. to get = holen), und zwar die Website namens '/en/LICENSE.txt'.

Hier siehst du die Methodenverkettung:

http.get( '/en/LICENSE.txt' ).body

Da wir eine Website vom Busfahrer http zurück bekommen werden, kannst du das auch so lesen:

Website .body

Und diese Zeile:

print( http.get( '/en/LICENSE.txt' ).body )

Dieser Code holt dir eine Website. Wir senden ihr die Nachricht body, die uns das ganze HTML in einem String liefert. Den drucken wir dann mit print. Schau dir an, wie man das Grundmuster Punkt-Methode verketten kann. Das nächste Kapitel wird alle möglichen Arten dieser Ruby-Muster erforschen. Das wird ein Spaß.

So, was tut der Code jetzt? Er schreibt den HTML-Quellcode der Ruby-Homepage auf den Bildschirm. Mit einem webfähigen Busfahrer.

5. Und so kommt der Ritt zu seinem ruhigen, gepolsterten Ende

Dem Truck hinterher rennend.

  1. F: Da vorne! Wir müssen ihn verfolgen!
    f: Wer klaut sowas?
  2. F: Die Kupplung ist sehr launisch. Das darf nicht wahr sein.

Jetzt haben wir ein Problem. Ich habe das Gefühl, dass du das Ganze hier viel zu sehr genießt. Und wir haben noch nichtmal das Kapitel erreicht, in dem ich Springseil-Reime benutze, um die beizubringen, wie man XML parst!

Wenn du das das hier schon genießt, dann wird es wirklich schlimm. Zwei Kapitel weiter wirst du deine eigenen Ruby-Programme schreiben. Genauer gesagt ist es fast soweit, dass ich dich dazu bringe, dein eigenes Rollenspiel zu schreiben, dein eigenes Datei-Austausch-Netzwerk (à la BitTorrent), und ein Programm, das echte Zufallszahlen aus dem Internet saugt.

Beweis: siehe Kaffeesatz.
Spass-Maßeinheiten
Aquaplaning | Streichelzoo | W(e)EiR | Schädeltrauma

Und, weißt du (das musst du wissen!), das hier kann zur Besessenheit werden. Zuerst wirst du völlig vergessen, mit dem Hund rauszugehen. Er wird an der Haustür stehen und mit dem Kopf dagegen pochen, während deine Augen den Code verschlingen, den deine Finger in den Computer spielen.

Durch deine Nachlässigkeit wird es gefährlich. Die Berge ausgedruckten Codes werden die Lüftung zudecken. Dein Ofen wird ersticken. Der Müll wird sich auftürmen: Kartons eilig bestellter Pizzen und Werbung, um deren Entsorgung du dich nicht kümmern kannst. Du wirst verdrecken und die Luft verpesten. Moos wird die Wände überwuchern, das Wasser wird klumpig, Tiere werden einziehen, Bäume werden durch den Boden wachsen.

Aber dein Computer ist gut versorgt. Und du, Smothkkiss, wirst ihn mit deinem Wissen füttern. In den Äonen, die du mit deinem Rechner verbracht hast, wirst du zur Hälfte eine CPU sein. Und er wird halb Mensch sein. Deine Arme sind direkt an die Ports angeschlossen. Deine Augen werden die Ausgabe direkt vom DVI-24-Stecker bekommen. Deine Lungen sitzen über dem Prozessor, um ihn zu kühlen.

Und gerade als der Raum kurz davor ist, über dir zusammenzubrechen, weil die ganze Überwucherung dich und die Maschine verschluckt, wirst du dein Script fertig stellen. Du und deine Maschine werden dieses neueste Ruby-Script ausführen, ein Produkt deiner Obsession. Und das Script wird Kettensägen feuern, die die Bäume zu kappen, und Herde steuern, die dein Haus warmhalten. Nano-Bauroboter werden aus deinem Script strömen, um dein Quartier umzubauen; sie werden kacheln, renovieren, chromieren, polieren, desinfizieren. Mächtige Androiden werden dein bröckelndes Haus in starke, stabile Architektur verwandeln. Große Säulen und Statuen werden wachsen. Du wirst der Herr über diesen Palast sein und über die Berge und Inseln in der Umgebung deiner Festung.

Also ich denke, das passt schon. Was sagst du? Lass uns endlich mit diesem Script anfangen?


4.

Floating Little Leaves of Code

[o]

Impossibly deep in the caverns of Ambrose... the Elf with a pet ham! ...and the cat Trady Blix.

I’ve never seen the ham do anything but leak juice. Today, our business in Ambrose Caverns is with the elf. He is a crucial part of the next lessons. Let’s all make him feel welcome. Go start warming up your listening hats! (And please change out of those ridiculous stirrup pants.)

A prompt warning: this lesson is much slower. Stay with it. This will be a long, deep breath. The most crucial stage of your instruction. It may seem like you’re not learning much code at first. You will be learning concepts. By the end of this chapter, you will know Ruby’s beauty. The coziness of the code will become a down sleeping bag for your own solace.

1. The Leaf as a Status Symbol in Ambrose

Alright, Elf. Give us a quick rundown of the currency issues you’ve faced there in your kingdom.

Blue Crystals got the shaft.

Yeah, that’s not the way I remember it. This Elf was paging me constantly. When I refused to call him back, he somehow left a message on my pager. Meaning: it beeped a couple times and then printed out a small slip of paper. The slip said something to the effect of, “Get down here quick!” and also, “We’ve got to rid the earth of this scourge of enterpreneurial caterpillars, these twisted insect vikings are suffocating my blue crystals!”

Lately, the exchange rate has settled down between leaves and crystals. One treegrown note is worth five crystals. So the basic money situation looks like this:

 blue_crystal = 1
 leaf_tender = 5

This example is, like, totally last chapter. Still. It’s a start. We’re setting two variables. The equals sign is used for assignment.

Now leaf_tender represents the number 5 (as in: five blue crystals.) This concept right here is half of Ruby. We’re defining. We’re creating. This is half of the work. Assignment is the most basic form of defining.

You can’t complain though, can you Elf? You’ve built an empire from cashing your blue crystals into the new free market among the forest creatures. (And even though he’s an elf to us, he’s a tall monster to them.)

Animal Perfect, LLC

Nonono. Hang on a sec. You’re not ready for what the Elf here is doing in his caves. You’ll think it’s all positively inhumane, naughty, sick, tweeested, yada yada.

Now You’re Going to Hear the Animal Perfect Mission Statement Because This Is A Book And We Have Time And No Rush, Right?

Back, back, way back before speedboats, I owned a prize race horse who took a stumble on the track. She did ten front flips and crashed into a guy who was carrying a full jar of mayonnaisse. We had blood and mayonnaisse up and down the track. Needless to say, she was a disaster.

The vet took one look at her and swore she’d never walk again. Her legs were gone and the vet wouldn’t allow a legless horse to just sit around. We’d need to put her down. He swore his life and career on it, insisting we divide into two parallel lines. The people who could not refute the doctor’s claims on one side; those too stubborn to accept his infallable medical reasoning on the other. The Elf, his pet ham, and I were the only ones in that second line.

So while the others heaped up trophies and great wreaths around the horse, bidding it a fond farewell before the bullet came to take him home, the Elf and I frantically pawed the Internet for answers. We took matter into our own hands, cauterizing her leg wounds with live crawdads. It worked great! We now had a horse again. Or at least: a horse body with a crustaceous abdominal frosting.

She scurried everywhere after that and lived for years in pleasantly moist underground cavities.

Animal Perfect is now the future of animal enhancement. They build new animals and salvage old-style animals for parts. Of course, they’ve come a long ways. When Animal Perfect started, you’d see a full-grown bear walk into Animal Perfect and you’d see a full-grown bear with sunglasses walk out. Completely cheesy.

Stick around and you’ll see a crab with his own jet pack. That’s a new 2004 model jetcrab.

But now, the whole operation is up and running. And the cleanliness of the place is astonishing. All the equipment is so shiny. Everything is in chrome. Oh, and all the staff have concealed weapons. They’re trained to kill anyone who enters unannounced. Or, if they run out of bullets, they’re trained to pistol whip anyone who enters unannounced.

Elf, make me a starmonkey.

First, the star is caught.

Some imaginary Ruby for you:

pipe.catch_a_star

Variable pipe. Method catch_a_star. A lot of Rubyists like to think of methods as a message. Whatever comes before the dot is handed the message. The above code tells the pipe to catch_a_star.

This is the second half of Ruby. Putting things in motion. These things you define and create in the first half start to act in the second half.

  1. Defining things.
  2. Putting those things into action.

So what if the star catching code works? Where does the star go?

captive_star = pipe.catch_a_star

See, it’s up to you to collect the miserable, little star. If you don’t, it’ll simply vanish. Whenever you use a method, you’ll always be given something back. You can ignore it or use it.

If you can learn to use the answers that methods give you back, then you will dominate.

Star is ratcheted to the monkey's face.

Quickly then.

starmonkey = ratchet.attach( captive_monkey, captive_star )

The ratchet gets an attach message. What needs to be attached? The method arguments: the captive_monkey and the captive_star. We are given back a starmonkey, which we have decided to hang on to.

Frog on the hand.

This is turning out to be such a short, little proggie that I’m just going to put it all together as one statement.

starmonkey = ratchet.attach( captive_monkey, pipe.catch_a_star ) + deco_hand_frog

See how pipe.catch_a_star is right in the arguments for the method? The caught star will get passed right to the ratchet. No need to find a place to put it. Just let it go.

2. Small and Nearly Worthless

Law-va.

The hotel here in Ambrose is no good at all. The beds are all lumpy. The elevator is tiny. One guy put all his bags in the elevator and found out there wasn’t room for him. He hit the button and chased up the stairs after it all. But the stairwell turned out to be too narrow and his shoulders got wedged going up.

The soap mini-bars they give you are sized down for elves, so it’s impossible to work up a lather. I hate it. I keep mistaking them for contact lenses.

I turned on the faucet and nothing came out. Thing is: Ambrose is a place with magical properties, so I took a chance. I put my hands under the spigot. Invisible, warm wetness. I felt the hurried sensation of running water, darting through my fingers. When I took my hands away, they were dry and clean.

It was an amazing nothingness to experience. It was just like nil.

Nil

In Ruby, nil represents an emptiness. It is without value. It isn’t zero. Zero is a number.

It’s Ruby’s own walking dead, a flatlined keyword. You can’t add to it, it doesn’t evolve. But it’s terribly popular. This skeleton’s smiling in all the pictures.

plastic_cup = nil

The above plastic_cup is empty. You could argue that the plastic_cup contains something, a nil. The nil represents the emptiness, though, so go ahead and call it empty.

Some of you who have programmed before will be tempted to say the plastic_cup is undefined. How about let’s not. When you say a variable is undefined, you’re saying that Ruby simply has no recollection of the variable, it doesn’t know the var, it’s absolutely non-existent.

But Ruby is aware of the plastic_cup. Ruby can easily look in the plastic_cup. It’s empty, but not undefined.

False

Shape of a cat.

The cat Trady Blix. Frozen in emptiness. Immaculate whiskers rigid. Placid eyes of lake. Tail of warm icicle. Sponsored by a Very Powerful Pause Button.

The darkness surrounding Blix can be called negative space. Hang on to that phrase. Let it suggest that the emptiness has a negative connotation. In a similar way, nil has a slightly sour note that it whistles.

Generally speaking, everything in Ruby has a positive charge to it. This spark flows through strings, numbers, regexps, all of it. Only two keywords wear a shady cloak: nil and false draggin us down.

You can test that charge with an if keyword. It looks very much like the do blocks we saw in the last chapter, in that both end with an end.

 if plastic_cup
   print "Plastic cup is on the up 'n' up!" 
 end

If plastic_cup contains either nil or false, you won’t see anything print to the screen. They’re not on the if guest list. So if isn’t going to run any of the code it’s protecting.

But nil and false need not walk away in shame. They may be of questionable character, but unless runs a smaller establishment that caters to the bedraggled. The unless keyword has a policy of only allowing those with a negative charge in. Who are: nil and false.

 unless plastic_cup
   print "Plastic cup is on the down low." 
 end

You can also use if and unless at the end of a single line of code, if that’s all that is being protected.

 print "Yeah, plastic cup is up again!" if plastic_cup
 print "Hardly. It's down." unless plastic_cup

And another nice trick: stack the if and unless.

 print "We're using plastic 'cause we don't have glass." if plastic_cup unless glass_cup

This trick is a gorgeous way of expressing, Do this only if a is true and b isn’t true.

Now that you’ve met false, I’m sure you can see what’s on next.

True

approaching_guy = true

I saw true at the hotel buffet tables today. I cannot stand that guy. His stance is way too wide. And you’ve never met anyone who planted his feet so hard in the ground. He wears this corny necklace made out of shells. His face exudes this brash confidence. (You can tell he’s exerting all of his restraint just to keep from bursting into Neo flight.)

To be honest, I can’t be around someone who always has to be right. This true is always saying, “A-OK.” Flashing hang ten. And seriously, he loves that necklace. Wears it constantly.

As you’d suspect, he’s backstage at everything on the if event schedule.

print "Hugo Boss" if true acts like print "Hugo Boss".

Occassionally, if will haul out the velvet ropes to exercise some crowd control. The double equals gives the appearance of a short link of ropes, right along the sides of a red carpet where only true can be admitted.

 if approaching_guy == true
   print "That necklace is classic." 
 end

The double equals is simply an ID check. Do the gentleman at both ends of this rope appear to match?

In this way, you control who if lets in. If you have a hard time getting along with true as I do, you can heartily welcome false.

 if approaching_guy == false
   print "Get in here, you conniving devil." 
 end

Same goes for unless. The gateway is yours. Take possession of it.

Again, I Want You to Dominate

Now, you want a head trip? The double equals sign is a method. Can you guess how it works? Here, check it out with the dot and parens:

approaching_guy.==( true )

Ruby allows the shortcut, though. You can drop the dot and back away slowly.

Now, do you remember what you need to do to dominate in Ruby? Use the answers the methods give you.

 if nil.==( true )
   print "This will never see realization." 
 end

In the above, how is the method’s answer being used?

Let’s take the statement nil == true. This will fail every time. No match. When there’s no match, the double equals method answers with false. A shake of the head. That answer is given to if, who can’t accept a false. The print never sees realization.

 at_hotel = true
 email = if at_hotel
           "why@hotelambrose.com" 
         else
           "why@drnhowardcham.com" 
         end

Even though if isn’t a method, if does give a return answer. Look at the above and wonder over what happens when at_hotel is true.

The if will return the answer given by the code it chooses to run. In the case of at_hotel being true, the first string, my e-mail address at Hotel Ambrose, will be returned. The else keyword marks code which will run, should if fail. If at_hotel is false, the if will answer with my e-mail address at Dr. N. Howard Cham’s office, where I take my apprenticeship.

Should you have several lines of code in an if or unless, only the answer from the last full statement will be used.

 email = if at_hotel
           address = "why" 
           address << "@hotelambrose" 
           address << ".com" 
         end

Three lines of code inside the if. The first line assigns a string with my name in it to a variable. The second and third lines add the rest of my e-mail address on to the end. The double less-than << is the concatenation operator. To concatenate is to append, or add to the end.

Just as we saw with the equality checker ==, the concatenator is a method. After adding to the end of the string, the concatenator also answers with that very string. So, the third line, which could be read as address.<<( ".com" ), gives back address, which the if then hands back for email’s assignment.

Here’s a question: what if the if fails? What if at_hotel is false in the above example? Is anything returned? Nothing is assigned to email, right?

Yes, nothing is returned. By which I mean: nil is returned. And often nil is a very useful answer.

 print( if at_hotel.nil?
          "No clue if he's in the hotel." 
        elsif at_hotel == true
          "Definitely in." 
        elsif at_hotel == false
          "He's out." 
        else
          "The system is on the freee-itz." 
        end )

You can use the nil? method on any value in Ruby. Again, think of it as a message. To the value: “Are you nil? Are you empty?”

If at_hotel is empty, Ruby doesn’t have any idea if I’m in the hotel or not. So if answers with the “No clue” string. In order to handle the true or false possibilities, the elsif keyword is used. While you can have only one if and one else, you can fill the inbetween with an exorbitant number of elsif keywords. Each elsif acts as a further if test. Checking for a positive charge.

If you’re doing okay at this point, then you’re in tip-top shape for the rest of the book. You have seen some pretty tough code in the last few examples. You strong fellow.

3. Chaining Delusions Together

55,000 starmonkeys and one spirited Olympic hopeful.

You finish reading the above comic and retire to your daybed for reflection. It’s one of those canopy affairs which is always logjammed with pillows. You sit atop the pile, gazing out upon the world. You see the tall smokestacks belching wide spools of fume and haze. The tangled concourses of freeways smattered with swift, shimmering traffic is but a gently pulsing eye muscle from your vantage point.

It is all so fantastic. How the colors of the horizon spread across the landscape as a great mix of butter and grease with a tablespoon of vanilla extract.

Yet, for all of the beauty which beckons for your attention, the images of the Elf and his Olympic Hopeful return. And more especially, that order for 55,000 starmonkeys. 55,000 starmonkeys, you think. Fifty-five Thousand.

You think of just the number itself. 55,000. It’s walking down a road. It might be in a forest, you don’t know for sure as your eyes are fixed right on the number itself. It’s stopping and talking to people. To tennis players, to a men’s choral group. There is merriment and good feeling. When it laughs, its lower zeros quiver with glee.

You want to talk to it. You want to skip along that forest trail with it. You want to climb aboard a jet bound to Brazil with it. And after five days and four nights at the leisureful Costa do Sauipe Marriott Resort & Spa, to marry it, to bear a family of 55,000 starmonkeys with it. To take possession of Nigeria with it.

With a flying leap, you dismount your pillow tower of isolation. Scrambling with the key, you unlock your roll top desk and pull out a sheet of paper, holding it firmly upon the desk. You begin scribbling.

Take possession of Nigeria with my new 55,000 starmonkeysOver it, build Nigeria-sized vegetarians only casino and go-cart arenaWings… we could have our own special sauce on the wings that’s differentMustard + codeine = Smotchkkiss’ Starry Starmonkey Glow SauceFranchise, franchise… logosEmployee instructional videosWhen you give the customer change, let them reach inside the frog on your hand to get itIf they have no change, at least put their reciept some place where they have to touch the frogWe’re leveling the playing field hereAdvertise cheap pizza, let’s make our money off sodaCollect all 4 frosted glasses

Wow, the ideas are really coming out. You literally had to smack yourself to stop. We need to put these in a safe place. Actually, we should store them on your computer and mangle the words. You look out the window and watch for FBI. I’m going to start this script.

The Flipping Script

 print "Type and be diabolical: " 
 idea_backwards = gets.reverse

Let this script be your confidante. It will ask for evil plans and turn their letters backwards. The gets method is built into Ruby. It’s a kernel method like print. This method gets will pause Ruby to let you type. When you hit Enter, gets will then stop paying attention to your keyboard punchings and answer back to Ruby with a string that contains everything you typed.

The reverse method is then used on the string that gets is giving back. The reverse method is part of the String class. Which means that anything which is a string has the reverse method available. More on classes in the next chapter, for now just know that a lot of methods are only available with certain types of values.

I don’t think reverse is going to cut it. The authorities only need to put a mirror to “airegiN fo noissessop ekaT.” Bust us when starmonkeys start to touch down in Lagos.

The capital letters give it away. Maybe if we uppercase all letters in the string before we reverse it.

 idea_backwards = gets.upcase.reverse

Your Repetitiveness Pays Off

You hand me a legal pad, doused in illegible shorthand. Scanning over it, I start to notice patterns. That you seem to use the same set of words repeatedly in your musings. Words like starmonkey, Nigeria, firebomb. Some phrases even. Put the kabosh on. That gets said a lot.

Let us disguise these foul terms, my brother. Let us obscure them from itching eyes that cry to know our delicate schemes and to thwart us from having great pleasure and many go-carts. We will replace them with the most innocent language. New words with secret meaning.

I start up a word list, a Ruby Hash, which contains these oft seen and dangerous words of yours. In the Hash, each dangerous word is matched up against a code word (or phrase). The code word will be swapped in for the real word.

 code_words = {
   'starmonkeys' => 'Phil and Pete, those prickly chancellors of the New Reich', 
   'catapult' => 'chucky go-go', 'firebomb' => 'Heat-Assisted Living', 
   'Nigeria' => "Ny and Jerry's Dry Cleaning (with Donuts)",
   'Put the kabosh on' => 'Put the cable box on'
 }

The words which are placed before the arrow are called keys. The words after the arrows, the definitions, are often just called values.

Notice the double quotes around Ny and Jerry's Dry Cleaning (with Donuts). Since a single quote is being used an apostrophe, we can’t use single quotes around the string. (Although, you can use single quotes if you put a backslash before the apostrophe such as: 'Ny and Jerry\'s Dry Cleaning (with Donuts)'.)

Should you need to look up a specific word, you can do so by using the square brackets method.

code_words['catapult'] will answer with the string 'chucky go-go'.

Look at the square brackets as if they are a wooden pallet the word is sitting upon. A forklift could slide its prongs into each side of the pallet and bring it down from a shelf back in the warehouse. The word on the pallet is called the index. We are asking the forklift to find the index for us and bring back its corresponding value.

If you’ve never been to a warehouse, you could also look at the brackets as handles. Imagine an industrious worker putting on his work gloves and hefting the index back to your custody. If you’ve never used handles before, then I’m giving you about thirty seconds to find a handle and use it before I blow my lid.

As with many of the other operators you’ve seen recently, the index brackets are simply a shortcut for a method.

code_words.[]( 'catapult' ) will answer with the string 'chucky go-go'.

Making the Swap

I went ahead and saved the Hash of code words to a file called wordlist.rb.

 require 'wordlist'

 # Get evil idea and swap in code words
 print "Enter your new idea: " 
 idea = gets
 code_words.each do |real, code| 
   idea.gsub!( real, code )
 end

 # Save the jibberish to a new file
 print "File encoded.  Please enter a name for this idea: " 
 idea_name = gets.strip
 File::open( "idea-" + idea_name + ".txt", "w" ) do |f|
   f << idea
 end

Script starts by pulling in our word list. Like gets and print, the require method is a kernel method, you can use it anywhere. I give it the string 'wordlist' and it will look for a file named wordlist.rb.

After that, there are two sections. I am marking these sections with comments, the lines that start with pound symbols. Comments are useful notes that accompany your code. Folks who come wandering through your code will appreciate the help. When going through your own code after some time has passed, comments will help you get back into your mindset. And there’s software out there that can take your comments and build documents from them. (RDoc and Ri—see Expansion Pak #1!)

I like comments because I can skim a big pile of code and spot the highlights.

As the comments tell us, the first section asks you for your evil idea and swaps in the new code words. The second section saves the encoded idea into a new text file.

 code_words.each do |real, code| 
   idea.gsub!( real, code )
 end

You see the each method? The each method is all over in Ruby. It’s available for Arrays, Hashes, even Strings. Here, our code_words dictionary is kept in a Hash. This each method will hurry through all the pairs of the Hash, one dangerous word matched with its code word, handing each pair to the gsub! method for the actual replacement.

In Ruby, gsub is short for global substitution. The method is used to search and replace. Here, we want to find all the occurences of a dangerous word and replace with its safe code word. With gsub, you provide the word to find as the first argument, then the word to put in its place as the second argument.

Why aren’t we hanging on to the answer from gsub? Doesn’t gsub give us an answer back that we should keep? You’d think the line would read:

 safe_idea = idea.gsub( real, code )

Yes, with gsub we’d need to hang on to its answer. We’re using a variation of gsub that is totally hyper. Notice the exclamation mark on the gsub! used inside the each block. The exclamation mark is a sign that gsub! is a bit of a zealot. See, gsub! will go ahead and replace the words in idea directly. When it’s done idea will contain the newly altered string and you won’t be able to find the old string.

Call gsub! a destructive method. It makes its changes to the value directly. Whereas gsub will leave the value intact, answering back with a new string which contains the alterations. (Why must gsub! scream when he descends upon his prey? Merciless assailant!)

Text Files of a Madman

Let us now save the encoded idea to a file.

 # Save the jibberish to a new file
 print "File encoded.  Please enter a name for this idea: " 
 idea_name = gets.strip
 File::open( 'idea-' + idea_name + '.txt', 'w' ) do |f|
   f << idea
 end

This section starts by asking you for a name by which the idea can be called. This name is used to build a file name when we save the idea.

The strip method is for strings. This method trims spaces and blank lines from the beginning and end of the string. This will remove the Enter at the end of the string you typed. But it’ll also handle spaces if you accidentally left any.

After we have the idea’s name, we open a new, blank text file. The file name is built by adding strings together. If you typed in 'mustard-plus-codeine', then our math will be: 'idea-' + 'mustard-plus-codeine' + '.txt'. Ruby presses these into a single string. 'idea-mustard-plus-codeine.txt' is the file.

We’re using the class method File::open to create the new file. Up until now, we’ve used several kernel methods to do our work. We hand the print method a string and it prints the string on your screen. One secret about kernel methods like print: they are actually class methods.

Kernel::print( "55,000 Starmonkey Salute!" )

What does this mean? Why does it matter? It means Kernel is the center of Ruby’s universe. Wherever you are in your script, Kernel is right beside you. You don’t even need to spell Kernel out for Ruby. Ruby knows to check Kernel.

Most methods are more specialized than print or gets. Take the File::open for example. The creator of Ruby, Matz, has given us many different methods which which read, rename, or delete files. They are all organized inside the File class.

File::read( "idea-mustard-plus-codeine.txt" ) will answer back with a string containing all of the text from your idea file.

File::rename( "old_file.txt", "new_file.txt" ) will rename old_file.txt.

File::delete( "new_file.txt" ) will nuke the new file.

These File methods are all built right into Ruby. They are all just stored in a container called the File class. So, while you can safely call kernel methods without needing to type Kernel, Ruby doesn’t automatically check the File class. You’ll need to give the full method name.

 File::open( 'idea-' + idea_name + '.txt', 'w' ) do |f|
   f << idea
 end

We pass two arguments into File::open. The first is the file name to open. The second is a string containing our file mode. We use 'w', which means to write to a brand-new file. (Other options are: 'r' to read from the file or 'a' to add to the end of the file.)

The file is opened for writing and we are handed back the file in variable f, which can be seen sliding down the chute into our block. Inside the block, we write to the file. When the block closes with end, our file is closed as well.

Notice we use the concatenator << to write to the file. We can do this because files have a method called << just like strings do.

Settle Down, Your Ideas Aren’t Trapped

Here, let’s get your ideas back to their original verbage, so you can rumminate over their brilliance.

 require 'wordlist'

 # Print each idea out with the words fixed
 Dir['idea-*.txt'].each do |file_name|
   idea = File.read( file_name )
   code_words.each do |real, code| 
     idea.gsub!( code, real )
   end
   puts idea
 end

By now, you should be up to snuff with most of this example. I won’t bore you with all of the mundane details. See if you can figure out how it works on your own.

We have an interesting class method here, though. The Dir::[] method searches a directory (some of you may call them “folders”). Just as you’ve seen with Hashes, the index brackets can be class methods. (Can you start to see the shiny, glinting gorgeousness of Ruby?)

So we’re using the forklift to get those files in the directory which match 'idea-*.txt'. The Dir::[] method will use the asterisk as a wildcard. We’re basically saying, “Match anything that starts with idea- and ends with .txt.” The forklift shuffles off to the directory and comes back with a list of all matching files.

That list of files will come in the form of Array the Caterpillar, with a String for each file. If you are curious and want to play with with Dir::[], try this:

p Dir['idea-*.txt'] will print:

['idea-mustard-plus-codeine.txt'] (an Array of file names!)

Yes, the p method works like print. But where print is designed for displaying strings, p will print anything. Check this out.

p File::methods will print:

["send", "display", "name", "exist?", "split", ... a whole list of method names! ]

4. The Miracle of Blocks

Flowerboyz?  Heard it before.

Since you and I are becoming closer friends as we share this time together, I should probably let you in on a bit of the history going on here. It’s a good time for a break I say.

First, you should know that Blix is my cat. My second pet to Bigelow. Granted, we hardly see each other anymore. He’s completely self-sufficient. I’m not exactly sure where he’s living these days, but he no longer lives in the antechamber to my quarters. He emptied his savings account about seven months ago.

He does have a set of keys for the house and the Seville. Should he ever find himself stranded, I will gladly step away from our differences and entertain his antics around the house again.

Make no mistake. I miss having him around. Can’t imagine he misses my company, but I miss his.

A Siren and A Prayer

I first saw Blix on television when I was a boy. He had a starring role on a very gritty police drama called A Siren and A Prayer. The show was about a god-fearing police squad that did their jobs, did them well, and saw their share of miracles out on the beat. I mean the officers on this show were great guys, very religious, practically clergy. But, you know, even clergymen don’t have the good sense to kill a guy after he’s gone too far. These guys knew where to draw that line. They walked that line every day.

So, it was a pretty bloody show, but they always had a good moral at the end. Most times the moral was something along the lines of, “Wow, we got out of that one quick.” But there’s serious camaraderie in a statement like that.

The show basically revolved around this one officer. “Mad” Dick Robinson. People called him Mad because he was basically insane. I can’t remember if he was actually clinically insane, but people were always questioning his decisions. Mad often blew his top and chewed out some of the other officers, most of whom had unquestionable moral character. But we all know it’s a tough world, the stakes are high out there, and everyone who watched the show held Mad in great regard. I think everyone on the squad grew quite a bit as people, thanks to Mad’s passion.

The officers couldn’t do it all themselves though. In every single episode, they plead with a greater force for assistance. And, in every single episode, they got their tips from a cat named Terry (played by my cat Blix.) He was just a kitten at the time and, as a young boy tuning into A Siren and A Prayer, I found myself longing for my own crime-sniffing cat. Terry took these guys down the subway tunnels, through the rotting stench of abandoned marinas, into backdoors of tall, industrial smokestacks.

Sometimes he was all over an episode, darting in and out, preparing traps and directing traffic. But other times you wouldn’t see him the whole episode. Then you’d rewind through the whole show and look and look and look. You’d give up. He can’t be in that episode.

Still, you can’t bear to let it go, so you go comb through the whole episode with the jog on your remote, combing, pouring over each scene. And there he is. Way up behind the floodlight that was turned up too high. The one that left Mad with permanent eye damage. Why? Why burn out the retinas of your own colleague, Terry?

But the question never got answered because the series was cancelled. They started to do special effects with the cat and it all fell apart. In the last episode of the show, there is a moment where Terry is trapped at the top of a crane, about to fall into the searing slag in the furnace of an iron smelt. He looks back. No going back. He looks down. Paws over eyes (no joke!), he leaps from the crane and, mid-flight, snags a rope and swings to safety, coming down on a soft antelope hide that one of the workers had presumably been tanning that afternoon.

People switched off the television set the very moment the scene aired. They tried changing the name. First it was God Gave Us a Squad. Kiss of Pain. Then, Kiss of Pain in Maine, since the entire precinct ended up relocating there. But the magic was gone. I went back to summer school that year to make up some classes and all the kids had pretty much moved on to football pencils.

Blocks

A couple years ago, I started teaching Blix about Ruby. When we got to this part in his lessons, the part that covers blocks, he said to me, “Blocks remind me of Mad Dick Robinson.”

“Oh?” I hadn’t heard that name in awhile. “I can’t see how that could be.”

“Well, you say blocks can be difficult to understand.”

“They’re not difficult,” I said. “A block is just code that’s grouped together.”

“And Mad was just an officer, sworn to uphold his duty,” he said. “But he was a real miracle to watch out in the field. Now, this first example you’ve shown me…” He pointed to an example I’d written down for him.

 kitty_toys =
   [:shape => 'sock', :fabric => 'cashmere'] +
   [:shape => 'mouse', :fabric => 'calico'] +
   [:shape => 'eggroll', :fabric => 'chenille']
 kitty_toys.sort_by { |toy| toy[:fabric] }

“This is a small miracle,” he said. “I can’t deny its beauty. Look, there are my kitty toys, laid out with their characteristics. Below them, the block, sorting them by fabric.”

“I apologize if your list of toys looks a bit tricky,” I said. Like you, he had learned about the Array, the caterpillar stapled into the code, with square brackets on each side and each item separated by commas. (Ah, here is one: ['sock', 'mouse', 'eggroll'].) He had also been taught the Hash, which is like a dictionary, with curly braces on each end which look like small, open books. Commas in the Hash between each pair. Each word in the dictionary matched up with its definition by an arrow. (Be beholden: {'blix' => 'cat', 'why' => 'human'}.)

“Yes, vexing,” he said. “It has square brackets like it’s an Array, but with the arrows like it’s a Hash. I don’t think you’re going to get away with that.”

“It does seem a bit subversive, doesn’t it?” I said, tease-nudging him with a spoon. “I’ve done your kitty toy list in a mix of the two. I’m using a shortcut. Which is: If you use arrows inside of an Array, you’ll end up with a Hash inside of that Array.

“Oh, I see,” he said. “You criss-crossed ‘em. How neat!”

“Yes, yes, you’re on it,” I said. He was also very good with a protractor. “I have three Arrays, each with a Hash inside. Notice the plus signs? I’m adding them into one big Array. Here’s another way of writing it…” I jotted down.

 kitty_toys = [
   {:shape => 'sock', :fabric => 'cashmere'},
   {:shape => 'mouse', :fabric => 'calico'},
   {:shape => 'eggroll', :fabric => 'chenille'}
 ]

One Array, which acts as our list of chew toys. Three Hashes in the Array to describe each toy.

Sorting and Iterating to Save Lives

“Let’s sort your toys by shape now,” I said. “Then, we’ll print them out in that order.”

 kitty_toys.sort_by { |toy| toy[:shape] }.each do |toy|
   puts "Blixy has a #{ toy[:shape] } made of #{ toy[:fabric] }" 
 end

“How does sort_by work?” asked Blix. “I can tell it’s a method you can use with Arrays. Because kitty_toys is an Array. But what is toy?”

“Okay, toy is a block argument,” I said. “Remember: the skinny pipes on each side of toy make it a chute.”

“Sure, but it looks like you’re using it like a Hash. Inside the block you have toy[:shape]. That looks like a Hash.”

“The sort_by method is an iterator, Blix. It iterates, or cycles, through a list of things. You remember that episode when Mad…”

“Episode?” he said. Yeah, he can’t understand the concept of TV dramas. Yeah, I’ve tried explaining.

“Or, yeah, remember that one eyewitness account we watched where Mad was trying to talk down that crazy spelling bee contestant from the ledge of an college library?”

“I remember it better than you because I was riding in a remote control plane.” Yep, it was one of those episodes.

“Do you remember how Mad got the guy to come down?” I asked.

“People in spelling bees love letters,” said Blix. “So what Mad did was a genius move on his part. He started with the letter A and gave reasons, for all the letters of the alphabet, why the guy should walk back down the building and be safe on the ground.”

”’A is for the Architecture of buildings like this,’” I said, in a gruff Mad voice. ”’Which give us hope in a crumbling world.’”

”’B is for Big Guys, like your friend Mad the Cop,’” said Blix. ”’Guys who help people all the time and don’t know how to spell too great, but still help guys who spell really great.’”

“See, he went through all the letters, one at a time. He was iterating through them.” It Err Ate Ing.

“But the guy jumped anyway, Why. He jumped off on letter Q or something.”

”’Q is for Quiet Moments that help us calm down and think about all of life’s little pleasures, so we don’t get all uptight and starting goofing around on tiptoes at the very edge of a big, bad building.’”

“And then he jumped,” said Blix. He shook his head. “You can’t blame Mad. He did his best.”

“He had a big heart, that’s for sure,” I said, patting Blix on the shoulder.

 kitty_toys.sort_by { |toy| toy[:shape] }.each do |toy|
   puts "Blixy has a #{ toy[:shape] } made of #{ toy[:fabric] }" 
 end

“As for your sort_by, it starts at the top of the list and goes through each item, one at a time. So toy is one of those items. With each item, sort_by stops and slides that item down the chute, under the toy name, and let’s you figure out what to do with it.”

“Okay, so toy takes turns being each of the different toys I have.”

“That’s right,” I said. “You know how I’ve really been harping on using the answers that methods give you? Here, we’re simply looking up the toy’s shape inside the block. The block then answers to sort_by with the shape string, such as "mouse" or "sock". Once it’s done cycling through the whole list, sort_by will have alphabetically compared each of the shape strings and will give back a new sorted Array.”

An Unfinished Lesson

“That’s good enough for today,” said Blix. “Can I have a fresh saucer of milk, please?”

I filled his saucer to the brim and he guzzled from it for some time while I took a poker and jabbed at coals in the fireplace. My mind wandered and I couldn’t help but think further of blocks. I wondered what I would teach Blix next.

I probably would have taught him about next. When you are iterating through a list, you may use next to skip on to the next item. Here we’re counting toys that have a non-eggroll shape by skipping those that do with next.

 non_eggroll = 0
 kitty_toys.each do |toy|
   next if toy[:shape] == 'eggroll'
   non_eggroll = non_eggroll + 1
 end

I could also have taught him about break, which kicks you out of an iterating loop. In the code below, we’ll print out (with p) each of the toy Hashes until we hit the toy whose fabric is chenille. The break will cause the each to abruptly end.

 kitty_toys.each do |toy|
   break if toy[:fabric] == 'chenille'
   p toy
 end

I never got to teach him such things. I continued poking away at a particularly stubborn coal which was caught in the iron curtain of the fireplace and threatened to drop on my antelope skin rug.

As I hacked away ferociously at the black stone, Blix slipped away, presumably on the bus bound for Wixl, the very bustling metropolis of the animal economies. Who knows, he may have first stopped in Ambrose or Riathna or any of the other villages along the way. My instinct say that Wixl was his definitely his final stop.

Without any student to instruct and coax along, I found myself quite lonely, holed up in the estate. In the stillness of the dead corridors, I began to sketch out a biography in the form of this guide.

I worked on it whenever I found myself bored. And when I wasn’t bored, I could always switch on The Phantom Menace to get me in the mood.

Someone let them all out.


5.

Them What Make the Rules and Them What Live the Dream

[o]

Through space and time... in his bell jar... on a mission to find himself...

Frankly, I’m sick and tired of hearing that Dr. Cham was a madman. Yes, he tried to bury himself alive. Yes, he electrocuted his niece. Yes, in fact, he did dynamite a retirement home. But this was all with good cause and, in each case, I believe he took the correct course of action.

I’m sure you’d like to side with popular opinion, but you’re bound to feel some small trickle of admiration for him once he’s taken time to teach you all about Ruby’s class definitions. And moreso when you learn about mixins. And perhaps, by the end of the chapter, we can all start to look beyond the Doctor’s grievous past and stop calling him a madman.

So if you need to call him a madman, I’d start heading down to the train tracks to smash up some long flourescent light bulbs. Get it out of your system right now, before we dig in.

1. This One's For the Disenfranchised

Some people still can't get past what he did.

If you give me a number, which is any year from Dr. Cham’s life, I’ll give you a synopsis of that time period. And I’ll do it as a Ruby method, so it’s an independent piece, an isolated chunk of code which can be hooked up to the voice of a robotic volcano, when such a thing becomes the apex of authoritative voice talents.

Okay, so I need you to notice def and case and when. You’ve seen the Ranges, the closed accordions of 1895..1913, back in chapter 3. They contain both ends and in between. And the backslashes at the end of each line simply ignore the Enter key at the end of each line, assuring Ruby that there is more of this line to come.

So, please: def and case and when.

 def dr_chams_timeline( year )
   case year
   when 1894
     "Born." 
   when 1895..1913
     "Childhood in Lousville, Winston Co., Mississippi." 
   when 1914..1919
     "Worked at a pecan nursery; punched a Quaker." 
   when 1920..1928
     "Sailed in the Brotherhood of River Wisdomming, which journeyed \
      the Mississippi River and engaged in thoughtful self-improvement, \
      where he finished 140 credit hours from their Oarniversity." 
   when 1929
     "Returned to Louisville to pen a novel about time-travelling pheasant hunters." 
   when 1930..1933
     "Took up a respectable career insuring pecan nurseries.  Financially stable, he \
      spent time in Brazil and New Mexico, buying up rare paper-shell pecan trees.  Just \
      as his notariety came to a crescendo: gosh, he tried to buried himself alive." 
   when 1934
     "Went back to writing his novel.  Changed the hunters to insurance tycoons and the \
      pheasants to Quakers." 
   when 1935..1940
     "Took Arthur Cone, the Headmaster of the Brotherhood of River Wisdomming, as a \
      houseguest.  Together for five years, engineering and inventing." 
   when 1941
     "And this is where things got interesting." 
   end
 end

The def keyword. Here is our first method definition. A plain kernel method, which can be used anywhere in Ruby. And how do we run it?

 puts dr_chams_timeline( 1941 )

Which answers with “And this is where things got interesting.” It’s the same story again and again: use your answers. I’ve set things up above so that the case statement always answers with a string. And since the case statement is the final (and only) statement in the method, then the method answers with that string. Trickling water spilling down from ledge to ledge.

Let me be clear about the case statement. Actually, I should call it a case..when statement, since they cannot be used separately. The case keyword is followed by a value, which is compared against each of the values which follow when keywords. The first value to qualify as a match is the one the case uses and the rest are ignored. You can do the same thing with a bunch of if..elsif statements, but it’s wordier.

 case year
 when 1894
   "Born." 
 when 1895..1913
   "Childhood in Lousville, Winston Co., Mississippi." 
 else
   "No information about this year." 
 end

Is identical to:

 if 1894 === year
   "Born." 
 elsif 1895..1913 === year
   "Childhood in Lousville, Winston Co., Mississippi." 
 else
   "No information about this year." 
 end

The triple equals is a length of velvet rope, checking values much like the double equals. It’s just: the triple equals is a longer rope and it sags a bit in the middle. It’s not as strict, it’s a bit more flexible.

Take the Ranges above. (1895..1913) isn’t at all equal to 1905. No, the Range (1895..1913) is only truly equal to any other Range (1895..1913). In the case of a Range, the triple equals cuts you a break and lets the Integer 1905 in, because even though it’s not equal to the Range, it’s included in the set of Integers represented by the Range. Which is good enough in some cases, such as the timeline I put together earlier.

Which actually looked like a timeline, didn’t it? I mean, sure, dr_chams_timeline method is code, but it does read like a timeline, clean and lovely.

What research revealed.

But Was He Sick??

You know, he had such bad timing. He was scattered as a novelist, but his ventures into alchemy were very promising. He had an elixir of goat’s milk and sea salt that got rid of leg aches. One guy even grew an inch on a thumb he’d lost. He had an organic health smoke that smelled like foot but gave you night vision. He was working on something called Liquid Ladder, but I’ve never seen or read anything else about it. It can’t have been for climbing. Who knows.

One local newspaper actually visited Dr. Cham. Their book reviewer gave him four stars. Really. She did an article on him. Gave him a rating.

Just know that Dr. N. Harold Cham felt terrible about his niece. He felt the shock treatment would work. The polio probably would have killed her anyway, but he took the chance.

On Sept. 9, 1941, after sedating her with a dose of phenacetin in his private operating room, he attached the conducting clips to Hannah’s nose, tongue, toes, and elbows. Assisted by his apprentice, a bespeckled undergraduate named Marvin Holyoake, they sprinkled the girl with the flakes of a substance the doctor called opus magnum. A white powder gold which would carry the current and blatantly energize the girl, forcing her blood to bloom and fight and vanquish.

But how it failed, oh, and how, when the lever was tossed, she arched and kicked—and KABLAM!—and BLOY-OY-OY-KKPOY! Ringlets of hair and a wall of light, and the bell of death rang. The experiment collapsed in a dire plume of smoke and her innocence (for weeks, everyone started out with, “And she will never have the chance…”) was a great pit in the floor and in their lungs.

To Hannah, I code.

 opus_magnum = true
 def save_hannah
   success = opus_magnum
 end

A method is its own island. And what goes on inside is unaffected by the simple variables around it. Dr. Cham couldn’t breach the illness of his niece, no more than an opus_magnum variable can penetrate the steely exterior of a method.

Should we run the save_hannah method, Ruby will squawk at us, claiming it sees no opus_magnum.

I’m talking about scope. Microscopes narrow and magnify your vision. Telescopes extend the range of your vision. In Ruby, scope refers to a field of vision inside methods and blocks.

A method’s def statement opens its vision. Variable names introduced there will be seen by the method and kept meaningful until its end closes its eyes. You can pass data into a method by using arguments and data can be returned from the method, but the names used inside the method are only good for its scope.

Some variables have wider scope. Global variables like $LOAD_PATH, which start with a cash symbol, are available in any scope. Instance variables like @names, which start with an at are available anywhere inside a class scope. Same goes for class variables like @@tickets. Class and instance variables will be explored in a moment.

Blocks have scope, but it’s a bit fuzzier. More flexible.

 verb = 'rescued'
 ['sedated', 'sprinkled', 'electrocuted'].
 each do |verb|
   puts "Dr. Cham " + verb + " his niece Hannah." 
 end
 puts "Yes, Dr. Cham " + verb + " his niece Hannah."

The block iterates (spins, cycles) through each of the Doctor’s actions. The verb variable changes with each pass. In one pass, he’s sedating. In the next, he’s powdering. Then, he’s electrocuting.

So, the question is: after the block’s over, will he have rescued Hannah?

 Dr. Cham sedated his niece Hannah.
 Dr. Cham sprinkled his niece Hannah.
 Dr. Cham electrocuted his niece Hannah.
 Yes, Dr. Cham electrocuted his niece Hannah.

Blocks are allowed to see variables in the vicinity. The block noticed that the verb variable existed and it overwrote its contents as it went along. When the block completed and its tiny life ended, the verb variable came out a changed creature.

If a block uses a variable which hasn’t been used previously, though, then that variable vanishes at the end of the block. The block’s scope closes and the variable goes with it. Say that verb wasn’t used before the block.

 ['sedated', 'powdered', 'electrocuted'].
 each do |verb|
   puts "Dr. Cham " + verb + " his niece Hannah." 
 end
 puts "Yes, Dr. Cham " + verb + " his niece Hannah."

Pulls an error: undefined local variable or method `verb'. Poof.

It must be something difficult, even for a great scientist, to carry away the corpse of a young girl whose dress is still starched and embroidered, but whose mouth is darkly clotted purple at the corners. In Dr. Cham’s journal, he writes that he was tormented by her ghost, which glistened gold and scorched lace. His delusions grew and he ran from hellhounds and massive vengeful, angelic hands.

Only weeks later, he was gone, propelled from these regrets, vanishing in the explosion that lifted him from the planet.

And even as you are reading this now, sometime in these moments, the bell jar craft of our lone Dr. Cham touched down upon a distant planet after a sixty year burn. As the new world came into view, as the curvature of the planet widened, as the bell jar whisked through the upset heavens, tearing through sheets of aurora and solar wind, Dr. Cham’s eyes were shaken open.

Safe landing.  Amazement.

What you are witnessing is the landing of Dr. Cham on the planet Endertromb. From what I can gather, he landed during the cusp of the Desolate Season, a time when there really isn’t much happening on the planet. Most of the inhabitants find their minds locked into a listless hum which causes them to disintegrate into just vapid ghosts of one-part-wisdom and three-parts-steam for a time.

My modest grasp of the history and climate of Endertromb has been assembled from hanging around my daughter’s organ instructor, who grew up on the planet.

Dead husbands could destroy the Doctor.

I frequently drill my daughter’s organ instructor in order to ensure that he can keep appointments adequately. That he can take house calls at odd hours and promptly answer emergency calls. When he finally revealed to me that he was an alien whose waking day consisted of five-hundred and forty waking hours, I was incredibly elated and opened a contractual relationship with him which will last into 2060.

For three days (by his pocket watch’s account), Dr. Cham travelled the dark shafts of air, sucking the dusty wind of the barren planet. But on the third day, he found the Desolate Season ending and he awoke to a brilliant vista, decorated with spontaneous apple blossoms and dewy castle tiers.

2. A Castle Has Its Computers

The panoramic vales of Sedna on Endertromb.

Our intrepid Doctor set off for the alien castle, dashing through the flowers. The ground belted past his heels. The castle inched up the horizon. He desired a stallion, but no stallion appeared. And that’s how he discovered that the planet wouldn’t read his mind and answer his wishes.

As my daughter’s organ instructor explained it, however, the planet could read minds and it could grant wishes. Just not both at the same time.

One day as I quizzed the organ maestro, he sketched out the following Ruby code on a pad of cheese-colored paper. (And queer cheese smells were coming from somewhere, I can’t say where.)

 require 'endertromb'
 class WishMaker
   def initialize
     @energy = rand( 6 )
   end
   def grant( wish )
     if wish.length > 10 or wish.include? ' '
       raise ArgumentError, "Bad wish." 
     end
     if @energy.zero?
       raise Exception, "No energy left." 
     end
     @energy -= 1
     Endertromb::make( wish )
   end
 end

This is the wish maker.

Actually, no, this is a definition for a wish maker. To Ruby, it’s a class definition. The code describes how a certain object will work.

Each morning, the wish maker starts out with up to five wishes available for granting. A new WishMaker is created at sun up.

 todays_wishes = WishMaker.new

The new method is a class method which creates a new, blank object. It also calls the object’s initialize method automatically. In the WishMaker definition, you’ll see the initalize method, which contains a single line of code: @energy = rand( 6 ).

The rand( 6 ) picks a number between 0 and 5. This number will represent the number of wishes left in the day. So, occassionally there are no wishes available from the wish maker.

The random number is assigned to an instance variable which is named @energy. This instance variable will be available any time throughout the class. The variable can’t be used outside the scope of the class.

In chapter three, we briefly looked at instance variables and decided to respect them as attributes. (The at symbol could mean attribute.) Instance variables can used to store any kind of information, but they’re most often use to store bits of information about the object represented by the class.

In the above case, each wish maker for the day has its own energy level. If the wish maker were a machine, you might see a gauge on it that points to the energy left inside. The @energy instance variable is going to act as that gauge.

 todays_wishes = WishMaker.new
 todays_wishes.grant( "antlers" )

Okay, step back and ensure you understand the example here. The WishMaker class is an outline we’ve laid out for how the whole magic wish program works. It’s not the actual genie in the bottle, it’s the paperwork behind the scenes. It’s the rules and obligations the genie has to live by.

It’s todays_wishes that’s the genie in the bottle. And here we’re giving it a wish to grant. Give us antlers, genie. (If you really get antlers from this example, I don’t want to hear about it. Go leap in meadows with your own kind now.)

In the last chapter, the drill was: Ruby has two halves.

  1. Defining things.
  2. Putting those things into action.

What are the actions in Ruby? Methods. And now, you’re having a lick of the definition language built-in to Ruby. Method definitions using def. Class definitions using class.

At this point in your instruction, it’s easier to understand that everything in Ruby is an object.

 number = 5
 print number.next                  # prints '6'

 phrase = 'wishing for antlers'
 print phrase.length                # prints '19'

 todays_wishes = WishMaker.new
 todays_wishes.grant( "antlers" )

And, consequently, each object has a class behind the scenes.

 print 5.class                       # prints 'Integer'
 print 'wishing for antlers'.class   # prints 'String'
 print WishMaker.new.class           # prints 'WishMaker'

Dr. Cham never saw the wish maker as he hustled across the landspace. It lay far beyond his landing in the valley of Sedna. Down sheer cliffs stuffed with layers of thicket, where you might toss your wish (written on a small 1” x 6” slip), down into the gaping void. Hopefully it will land on a lizard’s back, sticking to its spindly little horn.

And let’s say your wish makes it that far. Well, then, down the twisted wood goes the skinny salamander, scurrying through the decaying churches which had been pushed over that steep canyon ledge once and for all. And the expired priest inside, who weathered the fall as well, will kill the little amphibian—strangle it to death with a blessed gold chain—and save it for the annual Getting To Know You breakfast. He’ll step on your precious little wish and, when the thieves come, that slip will still be there, stuck on his sole. Of course, the thieves’ preferred method of torture is to cut a priest in thin deli-shaved slices from top to bottom. Who can cull evidence from that? And when they chop that last thin slice of shoe sole, they’ll have that rubber scalp in hand for good luck and good times. But they canoe much too hard, these thieves. They slap their paddles swiftly in the current to get that great outboard motor mist going. But the shoe sole is on a weak chain, tied to one man’s belt. And a hairy old carp leaps, latches on to that minute fraction of footwear. And the thieves can try, but they don’t see underwater. If they could, they’d see that mighty cable, packed with millions of needly fiber optics. Indeed, that fish is a peripheral plugged right into the core workings of the planet Endertromb. All it takes is one swallow from that fish and your wish is home free!

And that’s how wishes come true for children in this place.

Once my daughter’s organ instructor had drawn up the class for the wish maker, he then followed with a class for the planet’s mind reader.

 require 'endertromb'
 class MindReader
   def initialize
     @minds = Endertromb::scan_for_sentience
   end
   def read
     @minds.collect do |mind|
        mind.read
     end
   end
 end

Much as you’ve seen before, the initalize happens when a new MindReader object is created. This initialize gathers scans the planet for mindshare. It looks like these minds are stored in an array, since they are later iterated over using the collect method.

Both the wish maker and the mind reader refer to a class named Endertromb. This class is stored in a file endertromb.rb, which is loaded with the code: require 'endertromb'. Often you’ll use other classes to accomplish part of your task. Most of the latter half of this book will explore the wide variety of helpful classes that can be loaded in Ruby.

Dr. Cham Ventures Inside

But as Dr. Cham neared the castle, although the planet was aware of his thoughts, sensing his wonderment and anticipation, all Dr. Cham felt was deadness. He tromped up the steps of its open gate and through the entrance of the most beautiful architecture and was almost certain it was deserted.

For a while he knocked. Which paid off.

Blocky whale greeting.

He watched the baby whale rise like a determined balloon. He marvelled at his first alien introduction and felt some concern that it had passed so quickly. Well, he would wait inside.

As he stepped through the castle door, he felt fortunate that the door hadn’t been answered by a huge eagle with greedy talons, eager to play. Or a giant mouse head. Or even a man-sized hurricane. Just a tubby little choo-choo whale.

“Not a place to sit down in this castle,” he said.

At first, he had thought he had just entered a very dim hallway, but as his eyes adjusted, he saw the entrance extended into a tunnel. The castle door had opened right into a passage made of long, flat slabs of rock. Some parts were congruous and resembled a corridor. Other parts narrowed, and even tilted, then finally tipped away out of view.

The passage was lit by small doorless refrigerators, big enough to hold an armful of cabbage, down by his feet. He peered inside one, which was hollow, illuminated along all sides, and turning out ice shards methodically.

He pawed the ice chips, which clung dryly to his fingertips, and he scrubbed his hands in the ice. Which left some muddy streaks on his hands, but satisfied a small part of his longing to bathe. How long had it been? Ten years? Thirty?

Along the passage, long tubes of cloth cluttered some sections. Later, bright pixel matter in porcelain scoops and buckets.

He happened upon a room which had been burrowed out of the tunnel which had a few empty turtle shells on the ground and a large illuminated wall. He stared into the room, bewildered. What could this be? In one state of mind, he thought of having a seat on a shell. This could be the entrace at last, some kind of receiving room. On the other hand, spiders could pour out of the shell’s hollow when he sat. He moved on.

Meal in a Castle’s Pocket

As he journeyed along the passageways (for the central tunnel forked and joined larger, vacuous caverns), he picked up themes in some locations. Groups of rooms infested with pumping machinery. Cloth and vats of glue dominated another area. He followed voices down a plush, pillowed cavity, which led him to a dead end: a curved wall with a small room carved at eye-level.

He approached the wall and, right in the cubby hole, were two aardvarks eating at a table.

They gazed at him serenely, both munching on some excavated beetle twice their size, cracked open and frozen on its back on the table.

“Hello, little puppets,” he said, and they finished their bites and kept looking with their forks held aloof.

“I wish my niece Hannah were here to meet you,” he told the attentive miniature aardvarks. “She’d think you were an intricate puppet show.” He peered in at the dining area, shelves with sets of plates, hand towels. Half of a tiny rabbit was jutting out from the top a machine, creamy red noodles were spilling out underneath it. A door at the back of the room hung ajar. Dr. Cham could see a flickering room with chairs and whirring motors through the door.

“Any child would want this dollhouse,” he said. “Hannah, my niece, as I mentioned, she has a wind-up doll that sits at a spindle and spins yarn. It’s an illusion, of course. The doll produces no yarn at all.”

One of the aardvarks opened a trapdoor in the floor and pressed a button down inside, which lit. Then, a small film projector slowly came up on a rod. The other aardvark sat and watched Dr. Cham.

“But Hannah still reaches down into the dollhouse and collects all the imaginary yarn into a bundle. Which she takes to her mother, my sister, who is very good at humoring Hannah. She sews a dress to the doll’s dimensions, which Hannah takes back to the doll.

“And she tells the doll, ‘Here, look, your hard work and perserverance has resulted in this beautiful dress. You can now accept the Chief of Police’s invitation to join him tonight at the Governor’s Mansion.’ And she has a doll in a policeman’s uniform who plays the part of the Chief. He’s too scrawny to be an actual Chief, that would require quite a bit of plastic.”

The aardvark responsible for the film projector loaded a reel and aimed the projector at the back wall. The film spun to life and the aardvark took a seat. A green square appeared on the wall. The attentive aardvark stared at Dr. Cham still.

“Your films are coloured,” said Dr. Cham. “What a lovely, little life.”

The film played on: a blue square. Then, a red circle. Then, an orange square. The attentive aardvark turned away, watched the screen change to a pink triangle, and both aardvarks resumed eating.

A purple star. A red square. With quietness settling, Dr. Cham could hear notes droning from the projector. Like a slow, plodding music box trying to roll its gears along the train tracks.

“Yes, enjoy your supper,” said Dr. Cham and he politely tipped his head away, marching back up the path he’d taken.

Another Dead End Where Things Began

He found himself lost in the castle’s tunnels. Nothing looked familiar. He wasn’t worried much, though. He was on another planet. He would be lost regardless.

He wound through the tunnels, attempting to recall his paths, but far too interested in exploring to keep track of his steps. He followed a single tunnel deep, down, down, which slanted so steeply that he had to leap across ledges and carefully watch his footholds. The gravity here seemed no different than Earth. His legs were pulled into slides just as easily.

Although he had no absolute way of knowing where he was, he felt certain that he had left the castle’s boundaries. This deep, this long of a walk. It had been an hour since he’d entered through the door. And, as the tunnel wound back up, he was sure that he would emerge into a new dwelling, perhaps even a manhole which he could peek out from and see the castle. Perhaps he shouldn’t have come so far down this route. He hoped nothing was hibernating down here.

The tunnel came to a stop. A dark, dead end.

At the end of the tunnels: a computer and a book.

He had time. So he read the book. He read of the foxes and their pursuit of the porcupine who stole their pickup truck. He read of the elf and the ham. He saw the pictographs of himself and found he could really relate to his own struggles. He even learned Ruby. He saw how it all ended.

Were I him, I couldn’t have stomached it. But he did. And he pledged in his bosom to see things out just as they happened.

On the computer monitor, Dr. Cham saw the flashing irb prompt. Like Dr. Cham, you might recognize the irb prompt from The Tiger’s Vest (the first expansion pak to this book, which includes a basic introduction to Interactive Ruby.)

Whereas he had just been exploring tunnels by foot, he now explored the machine’s setup with the prompt. He set the book back where he had found it. He didn’t need it anymore. This was all going to happen whether he used it or not.

He started with:

 irb> Object::constants
   => ["Marshal", "String", "Dir", "LoadError", "Float", ... and so on ]

This command lists all the top-level constants. Classes are also listed as constants, so this list can be great to see what’s loaded into Ruby at any time.

He scanned the list for anything unfamiliar. Any classes which didn’t come with Ruby. Marshal, String, Dir, LoadError, Float. Each of those came with Ruby.

But further down the list:

 ... "Struct", "Values", "Time", "Elevator", "Range" ...

Elevator? Exactly the kind of class to poke around with. He had a go.

 irb> Elevator::methods
   => ["method", "freeze", "allocate", ... another long list ... ]
 irb> Elevator::class_variables
   => ['@@diagnostic_report', '@@power_circuit_active', '@@maintenance_password']
 irb> Elevator::constants
   => []

Looks like the Elevator class had plenty of methods. Most of these looked like they were the same methods every object has in Ruby. For example, method, freeze and allocate come with every class in Ruby. (Elevator::freeze would keep the Elevator class from being changed. Elevator::allocate would make a new Elevator object without calling the initialize method.)

The class_variables were interesting to Dr. Cham. This elevator appeared genuine. But no available constants. This tells us there are no classes nested inside the Elevator class.

He tried to create an Elevator object.

 irb> e = Elevator::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

He tried a few passwords.

 irb> e = Elevator::new( "going up" )
 AccessDeniedError: bad password
 irb> e = Elevator::new( "going_up" )
 AccessDeniedError: bad password
 irb> e = Elevator::new( "stairs_are_bad" )
 AccessDeniedError: bad password
 irb> e = Elevator::new( "StairsAreBad" )
 AccessDeniedError: bad password

That was useless. Oh, wait! The maintenance password. Listed in the class_variables.

 irb> Elevator::maintenance_password
 NoMethodError: undefined method `maintenance_password' for Elevator:Class
         from (irb):1
         from :0

Hmm. Instance variables are only available inside an object. And class variables are only available inside a class. How to get at that password?

 irb> class Elevator
 irb>   def Elevator.maintenance_password
 irb>     @@maintenance_password
 irb>   end
 irb> end
   => nil
 irb> Elevator::maintenance_password
   => "stairs_are_history!"

Alright! He got the password. Did you see that?

He added a class method to the Elevator class. Isn’t that great how you can start a new class definition for Elevator and Ruby just adds your changes to the existing class definition?

Class methods are usually called with the double colon. But, a period is fine as well. Since Elevator is a class itself, Ruby will figure that if you call Elevator.maintenance_password, you’re calling a class method. The double colon simply helps make class methods obvious to the reader.

And justly so. Class methods are a bit unusual. Normally you won’t want to store information directly inside of a class. However, if you have a bit of information that you need to share among all objects of a class, then you have a good reason to use the class for storage. It’s understandable that the @@maintenance_password would be stored in the class, instead of in each separate object. This way, the objects can simply reach up into the class and see the shared password.

Here’s probably how the password protection works.

 class Elevator
   def initialize( pass )
     raise AccessDeniedError, "bad password" \
       unless pass.equals? @@maintenance_password
   end
 end

Passwording a class like this is pointless, since anything in Ruby can be altered and overwritten and remolded. Dr. Cham had the password and ownership of the elevator is his.

 irb> e = Elevator.new( "stairs_are_history!" )
 #<Elevator:0x81f12f4 @level=4>
 irb> e.level = 1

Dr. Cham was standing right there when the elevator doors, off behind the computer terminal, opened for him. With an exasperated sense of accomplishment and a good deal of excitement surrounding all of the events that lie ahead, he stepped into the elevator and pressed 4.

3. The Continued Story of My Daughter's Organ Instructor

I know you may be alarmed to hear that I have a daughter. You think my writing is indicative of a palsied or infantile mind. Well, please rest. I don’t have a daughter. But I can’t let that stop me from sorting out her musical training.

As I was related these elaborate histories of the planet Endertromb, I found myself wandering through hallways, running my fingertips along the tightly buttoned sofas and soaking myself in the saturated bellowings of the pipes, as played by my daughter’s organ instructor. His notes resounded so deep and hollow in the walls of his manor that I began to casually mistake them for an ominous silence, and found it even easier to retreat into deep space with my thoughts. To think upon the ancient planet and its darker philosophies: its flesh temples, tanned from the dermal remains of its martyrs; its whale cartels, ingesting their enemies and holding them within for decades, dragging them up and down the staircases of ribs; its poison fogs and its painful doorways; and, the atrocious dynasties of The Originals, the species which claims fathership to all of the intellegent beings across the universe.

But, eventually, I’d hear those pipes of a higher octave sing and I’d be back in the very same breezy afternoon where I’d left.

How interesting that even the breeze of our planet is quite a strange thing to some outsiders. For he had also told me of the travellers from Rath-d, who ventured to Earth five centuries ago, but quickly dissipated in our air currents since they and their crafts and their armor were all composed of charcoal.

I had sat at the organ, listening to his faint tales of his colony, while he punctuated his symphonies to greater volumes and the story would disappear for awhile, until the coda came back around. He spoke of he and his brothers piling into the hollow of his mother’s tail and tearing the waxy crescent tissue from the inner wall. Juicy and spongy and syrupy soap which bleached their mouths and purged their esophagus as it went down. They chewed and chomped the stuff and it foamed. After they ate, they blew bubbles at each other, each bubble filled with a dense foam, which they slept upon. And early in the morning, when mother opened her tail again, she watched serenely as her babies lay cradled in the stew of dark meatballs and sweet, sticky froth.

He spelled out all the tastes of Endertromb. Of their salmon’s starchy organs, which cooked into a pasta, and its eyes which melted into rich cream. Of their buttermelon with tentacles. And he was just beginning to appreciate the delicacies as a child, only to be lifted from a schoolyard by a pair of upright pygmy elephants who reached at him, through the heavens, and snatched upon his collar with a vast length of crane.

They transplanted him on Earth, led him from their craft, trumpeting their snouts loudly for the city of Grand Rapids to hear, then left, weeping and embracing each other.

“But, strangely (em-pithy-dah), I learned upon, played upon (pon-shoo) the organs on my home (oth-rea) planet,” he said.

My daughter’s organ instructor speaks these extra words you see in parentheses. Who knows if they are from his native tongue or if they are his own soundful hiccups. He keeps another relic from Endertromb as well: he has twelve names.

“No, (wen-is-wen),” he said. “I have one name (im-apalla) which is said (iff) many-many different ways.”

I call him Paij-ree in the morning and Paij-plo in the later evening. Since it is day as I write, I will call him Paij-ree here.

Mumble-Free Earplugs

Alien at the keys.

So I told Paij-ree, “Paij-ree, I am writing a book. To teach the world Ruby.”

“Oh, (pill-nog-pill-yacht) nice,” he said. He’s known Ruby longer than I have, but still: I will be my daughter’s Ruby instructor.

And I said, “Paij-ree, you are in the book. And the stories of your planet.” I talk to him like he’s E.T. I don’t know why. Just like how I said next, “And then maybe someday you can go home to your mom and dad!”

To which he said, “(pon-shoo) (pon-shoo) (em-pithy-dah).” Which is his way of speaking out loud his silence and awe.

He wanted to see what I’d written, so I showed him this short method I’ve written for you.

 def wipe_mutterings_from( sentence )
   while sentence.include? '('
     open = sentence.index( '(' )
     close = sentence.index( ')', open )
     sentence[open..close] = '' if close
   end
 end

“Can you see what this does, Paij-ree? Any old Smotchkkiss can use this method to take all the incoherent babblings out of your speaking,” I said.

And I fed something he said earlier into the method.

 what_he_said = "But, strangely (em-pithy-dah), 
   I learned upon, played upon (pon-shoo) the 
   organs on my home (oth-rea) planet." 
 wipe_mutterings_from( what_he_said )
 print what_he_said

And it came out as a rather plain sentence.

 But, strangely , 
 I learned upon, played upon the
 organs on my home planet.

“You shouldn’t use that (wary-to) while loop,” he said. “There are lovelier, (thopt-er), gentler ways.”

In the wipe_mutterings_from method, I’m basically searching for opening parentheses. When I find one, I scan for a closing paren which follows it. Once I’ve found both, I replace them and their contents with an empty string. The while loop continues until all parentheses are gone. The mutterings are removed and the method ends.

“Now that I look at this method,” I said. “I see that there are some confusing aspects and some ways I could do this better.” Please don’t look down on me as your teacher for writing some of this code. I figure that it’s okay to show you some sloppy techniques to help you work through them with me. So let’s.

Okay, Confusing Aspect No. 1: This method cleans a string. But what if we accidentally give it a File? Or a number? What happens? What if we run wipe_mutterings_from( 1 )?

If we give wipe_mutterings_from the number 1, Ruby will print the following and exit.

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

What you see here is a rather twisted and verbose (but at times very helpful) little fellow called the backtrace. He’s a wound-up policeman who, at the slightest sign of trouble, immediately apprehends any and all suspects, pinning them against the wall and spelling out their rights so quickly that none can quite hear it all. But it’s plain that there’s a problem. And, of course, it’s all a big misunderstanding, right?

When Ruby reads you these Miranda rights, listen hardest to the beginning. The first line is often all you need. In this first line is contained the essential message. And in the above, the first line is telling us that there is no include? method for the number 1. Remember, when we were talking about the reverse method in the last chapter? Back then, I said, ”a lot of methods are only available with certain types of values.” Both reverse and include? are methods which work with strings but are meaningless and unavailable for numbers.

To be clear: the method tries to use to the number. The method will start with sentence set to 1. Then, it hits the second line: while sentence.include? '('. Numbers have no include? method. Great, the backtrace has shown us where the problem is. I didn’t expect anyone to pass in a number, so I’m using methods that don’t work with numbers.

See, this is just it. Our method is its own little pocket tool, right? It acts as its own widget independent of anything else. To anyone out there using the wipe_mutterings_from method, should they pass in a number, they’ll be tossed this panic message that doesn’t make sense to them. They’ll be asked to poke around inside the method, which really isn’t their business. They don’t know their way around in there.

Fortunately, we can throw our own errors, our own exceptions, which may make more sense to someone who inadvertantly hands the wrong object in for cleaning.

 def wipe_mutterings_from( sentence )
   unless sentence.respond_to? :include?
     raise ArgumentError, 
       "cannot wipe mutterings from a #{ sentence.class }" 
   end
   while sentence.include? '('
     open = sentence.index( '(' )
     close = sentence.index( ')', open )
     sentence[open..close] = '' if close
   end
 end

This time, if we pass in a number (again, the number 1), we’ll get something more sensible.

 ArgumentError: cannot wipe mutterings from a Fixnum
         from (irb):3:in `wipe_mutterings_from'
         from (irb):12

The respond_to? method is really nice and I plead that you never forget it’s there. The respond_to? checks any object to be sure that it has a certain method. It then gives back a true or false. In the above case, the incoming sentence object is checked for an include? method. If no include? method is found, then we raise the error.

You might be wondering why I used a symbol with respond_to?. I used a symbol :include? instead of a string 'include?'. Actually, either will work with respond_to?.

Usually symbols are used when you are passing around the name of a method or any other Ruby construct. It’s more efficient, but it also catches the eye. The respond_to? asks Ruby to look inside itself and see if a method is available. We’re talking to Ruby, so the symbol helps denote that. It’s not a big deal, Ruby just recognizes symbols quicker than strings.

Now, Confusing Aspect No. 2: Have you noticed how our method changes the sentence?

 something_said = "A (gith) spaceship." 
 wipe_mutterings_from( something_said )
 print something_said

Did you notice this? In the first line of the above code, the something_said variable contains the string "A (gith) spaceship.". But, after the method invocation, on the third line, we print the something_said variable and by then it contains the cleaned string "A spaceship.".

How does this work? How does the method change the string? Shouldn’t it make a copy of the string before changing it?

Yes, absolutely, it should! It’s bad manners to change strings like that. We’ve used gsub and gsub! in the last chapter. Do you remember which of those two methods is a destructive method, which changes strings directly?

Either we need to call this method wipe_mutterings_from! (as a courtesy to all the other good folks out there that might use this method) or change the method to work on a copy of the string rather than the real thing. Which is an easy change! We just need to dup the string.

 def wipe_mutterings_from( sentence )
   unless sentence.respond_to? :include?
     raise ArgumentError, 
       "cannot wipe mutterings from a #{ sentence.class }" 
   end
   sentence = sentence.dup
   while sentence.include? '('
     open = sentence.index( '(' )
     close = sentence.index( ')', open )
     sentence[open..close] = '' if close
   end
   sentence
 end

The dup method makes a copy of any object. Look at that line we added again on its own:

 sentence = sentence.dup

What a peculiar line of code. How does sentence become a copy of sentence? Does it erase itself? What happens to the original sentence? Does it disappear?

Remember that variables are just nicknames. When you see sentence = "A (gith) spaceship.", you see Ruby creating a string and then giving that string a nickname.

Likewise, when you see sentence = sentence.dup, you see Ruby creating a new string and then giving that string a nickname. This is handy inside your method because now sentence is a nickname for a new copy of the string that you can safely use without changing the string that was passed into the method.

You’ll see plenty of examples of variable names being reused.

 x = 5
 x = x + 1
 # x now equals 6

 y = "Endertromb" 
 y = y.length
 # y now equals 10

 z = :include?
 z = "a string".respond_to? z
 # z now equals true

And, yes, sometimes objects disappear. If you can’t get to an object through a variable, then Ruby will figure you are done with it and will get rid of it. Periodically, Ruby sends out its garbage collector to set these objects free. Every object is kept in your computer’s memory until the garbage collector gets rid of it.

Oh, and one more thing about dup. Some things can’t be dup’d. Numbers, for instance. Symbols (which look like :death) are identical when spelled the same. Like numbers.

Also, some of the special variables: nil, true, false. These are things that Ruby won’t let you alter, so there’s so point making a copy anyway. I mean, imagine if you could change false to be true. The whole thing becomes a lie.

Perhaps Confusing Aspect No. 3 is a simple one. I’m using those square brackets on the string. I’m treating the string like it’s an Array or Hash. I can do that. Because strings have a [] method.

When used on a string, the square brackets will extract part of the string. Again, slots for a forklift’s prongs. The string is a long shelf and the forklift is pulling out a slab of the string.

Inside the brackets, we pass the index. It’s the label we’ve placed right between the prongs where the worker can see it. When it comes to strings, we can use a variety of objects as our index.

 str = "A string is a long shelf of letters and spaces." 
 puts str[0]       # prints 65 (the character code for an 'A')
 puts str[0..-1]   # prints 'A string is a long shelf of letters and spaces.'
 puts str[1..-2]   # prints ' string is a long shelf of letters and spaces'
 puts str[1, 3]    # prints 'A s'
 puts str['shelf'] # prints 'shelf'

Alright, the last Confusing Aspect No. 4: this method can be sent into an endless loop. You can give this method a string which will cause the method to hang and never come back. Take a look at the method. Can you throw in a muddy stick to clog the loop?

 def wipe_mutterings_from( sentence )
   unless sentence.respond_to? :include?
     raise ArgumentError, 
       "cannot wipe mutterings from a #{ sentence.class }" 
   end
   sentence = sentence.dup
   while sentence.include? '('
     open = sentence.index( '(' )
     close = sentence.index( ')', open )
     sentence[open..close] = '' if close
   end
   sentence
 end

Here, give the muddy stick a curve before you jam it.

 muddy_stick = "Here's a ( curve." 
 wipe_mutterings_from( muddy_stick )

Why does the method hang? Well, the while loop waits until all the open parentheses are gone before it stops looping. And it only replaces open parentheses that have a matching closing parentheses. So, if no closing paren is found, the open paren won’t be replaced and the while will never be satisfied.

How would you rewrite this method? Me, I know my way around Ruby, so I’d use a regular expression.

 def wipe_mutterings_from( sentence )
   unless sentence.respond_to? :gsub
     raise ArgumentError, 
       "cannot wipe mutterings from a #{ sentence.class }" 
   end
   sentence.gsub( /\([-\w]+\)/, '' )
 end

Do your best to think through your loops. It’s especially easy for while and until loops to get out of hand. Best to use an iterator. And we’ll get to regular expressions in time.

In summary, here’s what we’ve learned about writing methods:

  1. Don’t be surprised if people pass unexpected objects into your methods. If you absolutely can’t use what they give you, raise an error.
  2. It’s poor etiquette to change objects your method is given. Use dup to make a copy. Or find a method like gsub that automatically makes a copy as it does its job.
  3. The square brackets can be used to lookup parts inside any Array, Hash or String objects, as these objects provide a [] method. Also, since these objects provide a []= method, the square brackets can be used in assignment (on the left-hand side of the equals sign) to change the parts of those objects.
  4. Watch for runaway loops. Avoid while and until if you can.

The Mechanisms of Name-Calling

Cat salesmen from the sky.

Forthwith there is a rustling in the trees behind Paij-ree’s house and it turns out to be a man falling from the sky. His name is Doug and he sells cats.

So, just as he comes into to view, when his shadow (and the shadows of the cats tied to his foot) obscures the bird on the lawn that we’re trying to hit with a racquetball, as he’s squeezing a wisp of helium from his big balloon, we shout, “Hello, Doug!”

And he says, “Hello, Gonk-ree! Hello, Why!”

Paij-ree checks his pockets to be sure he has the dollar-twenty-seven he’ll need in order to buy the three cats he’ll need to keep the furnace stoked and the satellite dish turning. These cats generate gobs of static once Paij-ree tosses them in the generator, where they’ll be outnumbered by the giant glass rods, which caress the cats continually—But, wait! Did you see how the cat broker called him Gonk-ree?

And he calls him Gonk-ree in the morning and Gonk-plo at night.

So the suffix is definitely subject to the sunlight. As far as I can tell, the prefix indicates the namecaller’s relationship to Paij-ree.

 class String

   # The parts of my daughter's organ
   # instructor's name.
   @@syllables = [
     { 'Paij' => 'Personal',
       'Gonk' => 'Business',
       'Blon' => 'Slave',
       'Stro' => 'Master',
       'Wert' => 'Father',
       'Onnn' => 'Mother' },
     { 'ree'  => 'AM',
       'plo'  => 'PM' }
   ]

   # A method to determine what a
   # certain name of his means.
   def name_significance
     parts = self.split( '-' )
     syllables = @@syllables.dup
     signif = parts.collect do |p|
       syllables.shift[p]
     end
     signif.join( ' ' )
   end

 end

Now I’ve gone beyond just showing you sloppy code. Here be a grave debauchery and a crime against nature. A crime most languages won’t allow you to commit. We’re changing the String, one of the core classes of Ruby!

“I know this is a bit dangerous,” I said, when I passed this one under Paij-ree’s nose. “I hope nobody gets hurt.”

“Every Smotchkkiss must taste what this (kep-yo-iko) danger does,” he said. “Dogs and logs and swampy bogs (kul-ip), all must be tasted.” And he took a swig of his Beagle Berry marsh drink.

So what is it that I’m adding to the String class? Two things: a class variable and a method. A normal instance method.

I like to look at the at symbol as a character meaning attribute. The double at stands for attribute all. A class variable. All instances of a class can look at this variable and it is the same for all of them. The @@syllables variable is an Array that can now be used inside the String class.

The new method is name_significance and this new method can be used with any string.

print "Paij-ree".name_significance prints out Personal AM.

As you can see, Paij-ree is a personal name. A name friends use in the early hours.

Make sure you see the line of code which uses self. This is a special variable, a variable which represents the object whose method you are calling. To simplify things a bit, let’s try making a method which breaks up a string on its dashes.

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

Again, here’s a method which can be used with any string.

"Gonk-plo".dash_split return the Array ['Gonk', 'plo'].

Using self marks the beginning of crossing over into many of the more advanced ideas in Ruby. This is definition language. You’re defining a method, designing it before it gets used. You’re preparing for the existence of an object which uses that method. You’re saying, “When dash_split gets used, there will be a string at that time which is the one we’re dash-splitting. And self is a special variable which refers to that string.”

Ruby is a knockout definition language. A succulent and brain-splitting discussion is coming your way deeper in this book.

Most often you won’t need to use self explicitly, since you can call methods directly from inside other method definitions.

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

In the name_significance method, find the loop. Learning about Array#collect is essential. Let’s look close.

 signif = parts.collect do |p|
   syllables.shift[p]
 end

The parts Array contains the separated name. ['Paij', 'plo'], for instance. We’re iterating through each item in that Array with collect. But collect steps beyond what each does. Like each, collect slides each item down the chute as a block variable. And then, at the end of the block, collect keeps the answer the block gives back and adds it to a new Array. The collect method is the perfect way of building a new Array which is based on the items in an existing Array.

Doug has three cats for sale. One is twelve cents, one is sixty-three cents, one is nine cents. Let’s see how much each cat would cost if we added a 20% tip.

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

I say Paij-ree’s property is a very charming section of woods when it’s not raining cats and Doug. For many days, Paij-ree and I camped in tents by the river behind his house, subsisting on smoked blackbird and whittling little sleeping indians by the dusklight. On occassion he would lose a game of spades and I knew his mind was distracted, thinking of Endertromb. All of this must have been stirring inside of him for sometime. I was the first ear he’d ever had.

“I just came from Ambrose,” I said. “Sort of my own underground home, a place where elves strive to perfect animals.”

He mumbled and nodded. “You can’t be (poth-in-oin) part of (in) such things.”

“You think we will fail?”

“I (preep) have been there before,” he said. And then, he spoke of the Lotteries.

4. The Goat Wants to Watch a Whole Film

Blinky, winky, a goat... awakes...

The elevator had opened into a green room full of shelves and file cabinets. Reels of tape and film canisters and video tape everywhere. Dr. Cham hadn’t a clue what most of it was. All he saw was a big, futuristic mess.

He called out again, stumbling through alleys of narrow shelves, “Hello-o-o?? I’m looking for intellegent life! I’m a space traveller!” He tripped when his foot slid right into a VCR slot. “Any other beings I can communicate with?”

Hand cupped around mouth, he yelled, “Hello-o-o?”

“Crying out loud.” The sleepy goat came tromping down the aisle.

The goat already knows Dr. Cham.

“I hate that book,” said the goat. “I believe the author is disingenuous.”

“Really?” asked Dr. Cham.

“I’m sure it’s all true. It’s just so heavily embellished. I’m like: Enough already. I get it. Cut it out.”

“I’m not quite sure what to make of it,” said the Doctor. “It seems like an honest effort. I actually wrote something in Ruby back there.”

“It doesn’t give goats a very good name,” said the goat.

“But you are the only goat in the book,” said the Doctor.

“And I’m totally misquoted.”

The mechanics behind devouring Dr. Cham.

The goat closed his mouth and Dr. Cham held his heart.

“I’m actually very literate,” said the goat. “Albeit, more recently, I’ve switched to movies. I love foreign films. One of my relatives just brough back Ishtar from your planet. Wow, that was excellent.”

“I haven’t been to my planet in a long time. It would be difficult to consider it my home at this stage.”

“Well, Warren Beatty is delightful. His character is basically socially crippled. He actually tries to kill himself, but Dustin Hoffman sits in the window sill and starts crying and singing this totally hilarious heartbreak song. I’ve got it here, you should see it.”

“Can I get something to eat?” asked the Doctor. And he still felt filthy.

“How about we watch a film and you can have a buttermelon with tentacles?” said the goat.

So, they worked their way back toward the goat’s projector. Back by the freezer locker, they sat on a giant rug and broke off the appendages of frozen buttermelons. The shell was solid, but once it cracked, rich fruit cream was in abundance. Sweet to taste and a very pleasant scent.

“First film, you’ve got to see,” said the goat. “Locally filmed and produced. I’m good friends with the lady who did casting. Dated her for awhile. Knew everyone who was going to play the different roles long before it was announced.”

The goat set the projector by Dr. Cham. “I’ve got the music on the surround sound. You can man the knob.”

The Originals and their lonesome planet.

Dr. Cham’s mind wandered at this point in the presentation, just as the land war mounted between the two throngs of animal settlers. The details of their wars and campaigns continued to consume the spool of transparent film that Dr. Cham was feeding through the projector.

War after war after war. The Sieging of Elmer Lake. The Last Stand of Newton P. Giraffe and Sons. Dog Invasion of Little Abandoned Cloud. No animals died in these wars. Most often an attack consisted of bopping another animal on the head. And they philipped each other’s noses. But, believe me, it was humiliating.

Blasted crying shame. Things could have worked out.

The Birth of an Object

“Don’t worry,” said the goat, anxious to sway Dr. Cham’s attention back to the film. “Things do work out.”

In Ruby, the Object is the very center of all things. It is The Original.

 class ToastyBear < Object; end

The angle bracket indicates inheritance. This means that the new ToastyBear class is a new class based on the Object class. Every method that Object has will be available in ToastyBear. Constants available in Object will be available in ToastyBear.

But every object inherits from Object. The code…

 class ToastyBear; end

Is identical to…

 class ToastyBear < Object; end

Inheritance is handy. You can create species of objects which relate to each other. Often, when you’re dissecting a problem, you’ll come across various objects which share attributes. You can save yourself work by inheriting from classes which already solve part of that problem.

You may have a UnitedStatesAddress class which stores the address, city, state, and zip code for someone living in the United States. When you start storing addresses from England, you could add a UnitedKingdomAddress class. If you then ensure that both addresses inherit from a parent Address class, you can design your mailing software to accept any kind of address.

 def mail_them_a_kit( address )
   unless address.is_a? Address
     raise ArgumentError, "No Address object found." 
   end
   print address.formatted
 end

Also, inheritance is great if you want to override certain behaviours in a class. For example, perhaps you want to make your own slight variation to the Array class. You want to enhance the join method. But if you change Array#join directly, you will affect other classes in Ruby that use Arrays.

So you start your own class called ArrayMine, which is based on The Original Array.

 class ArrayMine < Array
   # Build a string from this array, formatting each entry
   # then joining them together.
   def join( sep = $,, format = "%s" )
     collect do |item|
       sprintf( format, item )
     end.join( sep )
   end
 end

ArrayMine is now a custom Array class with its own join method. Array is the superclass of ArrayMine. Every object has a superclass method where you can verify this relationship.

 irb> ArrayMine.superclass
   => Array

Perfect. We manage a hotel and we have an Array of our room sizes: [3, 4, 6]. Let’s get it nicely printed for a brochure.

 rooms = ArrayMine[3, 4, 6]
 print "We have " + rooms.join( ", ", "%d bed" ) + " rooms available."

Which prints, “We have 3 bed, 4 bed, 6 bed rooms available.”

Dr. Cham was looking around for a bathroom, but archival video tape was everywhere. He eventually found a place, it may have been a bathroom. It had a metal bin. More importantly, it was dark and out of eyesight.

While he’s in there, let me add that while The Originals slaughtered The Invaders to prove their rights as First Creatures, the Ruby Object doesn’t have any such dispute. It is the absolute king Object the First.

Watch.

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

Even Class is an Object! See, although classes are the definition language for objects, we still call class methods on them and treat them like objects occassionally. It may seem like a dizzying circle, but it’s truly a very strict parentage. And it ensures that when you alter the Object, you alter everything in Ruby. Which is impossibly scary and all-powerful and cataclysmic and awesome! Ruby does not restrict you, my sister, my brother!

Between Class and Object, do you see Module? If Object is the king, the one who has sired every other part of Ruby, then Module is the poor waifish nun, shielding and protecting all her little Ruby townspeople children. (To complete the analogy: Class is the village school teacher and Kernel is the self-important colonel.)

The whole point of Module’s existence is to give food and shelter to code. Methods can stay dry under Module’s shawl. Module can hold classes and constants and variables of any kind.

“But what does a Module do?” you ask. “How is it gainfully employed??”

“That’s all it does!!” I retort, stretching out my open palms in the greatest expression of futility known to man. “Now hear me—for I will never speak it again—that Module Mother Superior has given these wretched objects a place to stay!!”

 # See, here is the module -- where else could our code possibly stay?
 module WatchfulSaintAgnes

   # A CONSTANT is laying here by the doorway.  Fine.
   TOOTHLESS_MAN_WITH_FORK = ['man', 'fork', 'exposed gums']

   # A Class is eating, living well in the kitchen.
   class FatWaxyChild; end

   # A Method is hiding back in the banana closet, God knows why.
   def timid_foxfaced_girl; {'please' => 'i want an acorn please'}; end

 end

Now you have to go through Saint Agnes to find them.

 >> WatchfulSaintAgnes::TOOTHLESS_MAN_WITH_FORK
 => ["man", "fork", "exposed gums"]
 >> WatchfulSaintAgnes::FatWaxyChild.new
 => #<WatchfulSaintAgnes::FatWaxyChild:0xb7d2ad78>
 >> WatchfulSaintAgnes::instance_methods
 => ["timid_foxfaced_girl"]

Always remember that a Module is only an inn. A roof over their heads. It is not a self-aware Class and, therefore, cannot be brought to life with new.

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

St. Agnes has given up her whole life in order that she may care for these desperate bits of code. Please. Don’t take that away from her.

If you wanted to steal from St. Agnes, though, I can help you. You can bring in a larger abbey to swallow up the ministry of WatchfulSaintAgnes and then what is she left with?

For this you can use extend, which will pull all the methods from a module into a class or an object.

 >> class TheTimeWarnerAolCitibankCaringAndLovingFacility; end
 >> TheTimeWarnerAolCitibankCaringAndLovingFacility.extend WatchfulSaintAgnes
 >> TheTimeWarnerAolCitibankCaringAndLovingFacility::instance_methods
 => ["timid_foxfaced_girl"]

In truth, no one’s stolen from WatchfulSaintAgnes, only borrowed. The timid_foxfaced_girl now has two addresses.

You gotta admit. The old abbey can get bought out a zillion times and that little fox-faced girl will still be back in the banana closet wanting an acorn! Too bad we can’t feed her. She’s a method with no arguments.

When Dr. Cham came out refreshed, the filmstrip was a bit behind. But the goat hadn’t noticed, so the Doctor advanced frames until it made some sense.

The goats that told a planet it was ugly.

So the invaders left the planet.

“This planet is decrepit,” said Dr. Cham. “The castle is nice. But inside it’s a disaster.”

“The whole castle look is a projection,” said the goat. “All the flowers and apple blossoms and the sky even. It’s a low-resolution projection.”

“Yes? It is enchanting.”

“I guess.”

The spool ends.

“That’s messed up!” said the goat. “That’s not the way the film ends! There’s no blood! What happened? What happened? Did you screw up the knob, idiot?”

“Well, I don’t know,” said Dr. Cham. He turned the knob reverse and forward. Tapped the lens.

“Check the film! Check the film!”

Dr. Cham pulled out a length of film from the projection feed, melted and dripping from its end.

“Curse that! These projectors are quality! I’ve never had this happen. There’s no way.”

Hunting For a Voice

“I don’t think it was the projector,” said Dr. Cham. “Something flew across that screen and uttered a blistering moan.”

“I don’t have any dupes of that movie,” said the goat somberly. “And that girl. That casting director. I never see her anymore.”

Dr. Cham stood up and looked over the dumpy aisles of magnetic carnage, searching.

“Oh, hey, you should call that girl,” the goat went on. “You could talk to her, get an understanding. Tell her about me. Don’t act like your my friend, just, you know, ‘Oh, that guy? Yeah, whatta maroon.’”

Dr. Cham spotted the doorway and exited.

The hallways were an entirely new world of mess. In the goat’s archives, the shelves had been messy. In the hallway, shelves were completely tipped. Sinks were falling through the ceiling. The Doctor ventured under the debris, kicking through plywood when necessary.

“You shouldn’t be out here,” said the goat. “You’re on someone else’s property at this point. A couple of pygmy elephants own all this. They’re nasty guys. They’ll beat the crap outta you with their trunks. They ball it up and just whack ya.”

Dr. Cham pushed a file cabinet out of his way, which fell through a flimsy wall, then through the floor of the next room over. And they heard it fall through several floors after that.

“I’m trying to remember how it goes in the book,” said Dr. Cham, as he walked swiftly through the hall. “That milky fog that swept across the projection. We find that thing.” He jiggled a door handle, broke it off. Forged through the doorway and disappeared inside.

“You really get a kick out of beating stuff up, don’t you?” said the goat. “Walls, doors.” The goat headbutted a wall. The wall shuddered and then laid still.

Then, it was quiet. And black.

The goat stayed put in the bleak hallway, expecting Dr. Cham to flip over a few desks and emerge, ready to move on from the room he’d busted into. But Dr. Cham didn’t return, and the goat opted to share a moment with the neglected wreckage left by his neighbors. Not that he could see at all. He could only hear the occassional rustling of the piles of invoices and carbon copy masters and manila envelopes when he shifted his legs.

The ground seemed to buckling right under the goat, as if the heaps of kipple around him were beginning to slide toward his weight. He would be at the center of this whirlpool of elephant documentation. Would he die of papercuts first? Or would he suffocate under the solid burial by office supplies?

A soft light, however, crept up to him. A floating, silver fish. No, it was a—was it scissors? The scissors grew into a shimmering cluster of intellegent bread, each slice choking on glitter. But, no, it was hands. And an Easter hat.

The goat alone in the hallway, meets an apparition.

In another room, Dr. Cham stood under the clear glass silently. The ceiling had abruptly gone transparent, then starlight washed over his pants and jacket. He walked further to the room’s center in muted colors, lit as softly as an ancient manuscript in its own box at the museum. More stars, more cotton clusters of fire, unveiled as he came across the floor. And it peeked into view soon enough, he expected it to be larger, but it wasn’t.

Earth. Like a painted egg, still fresh. He felt long cello strings sing right up against his spine. How could that be called Peoplemud? Here was a vibrant and grassy lightbulb. The one big ball that had something going for it.

He thought of The Rockettes. Actually, he missed The Rockettes. What a bunch of great dancers. He had yelled something to The Rockettes when he saw them. Something very observant and flattering.

Oh, yes, while The Rockettes were spinning, arm in arm, he had yelled, “Concentric circles!” Which no one else cared to observe.

And this thought was enough to feed Dr. Cham’s superiority complex. He wore a goofy smile as he retraced his footsteps. He truthfully felt his genius coming through in such a statement. To realize the simplicity of a circle was his. He reflected on it all the way back to the hallway.

Which I think is great. Adore yourself when you have a second.

The Doctor knows this ghost.

“Oh, right,” said the goat. “Your niece. The niece you killed. I’m with ya now.”

For just a few moments, they all looked at each other. Just enough time for both Dr. Cham and the goat to think: Oh, yeah. Hannah causes us a lot of trouble. She’s already talking about maple donuts.

“Does she start talking about maple donuts right away like that?” asked the goat.

“Yes, she does,” said the Doctor. “She brings it up to you, then she brings it up to me. She sees a maple donut somewhere—I don’t quite remember where.”

“Do I see a real maple donut?” Hannah said. “I need a real one.”

“Okay, okay,” said the goat. “Yeah, I remember: here’s where she says that if she gets a real maple donut, she’ll become a real person again. Because her real destiny was to own a bakery and you ruined that destiny and now she’s trapped as a ghost.”

“Hey, that’s the truth!” Hannah yelped.

“It’s terrible that we must bear through this whole scene again,” said the Doctor. “The donuts are immaterial. They should be left out altogether.”

“Man, I am having a hard time remembering all of this chapter,” said the goat. “I don’t even remember how to get out of this hallway. I must have read that book like thirty times. Do we blast through a wall? Do we scream until someone finds us?”

“We get Hannah to float through walls and she finds some kind of machine,” says Dr. Cham. “I have to write a program—it all works out somehow.”

“But, you know what I’m saying?” said the goat. “I forget all the details. Especially the earlier chapters. I mean I can remember the ending perfectly. It’s hard to sit through all this. The end is so much better.”

Dr. Cham folded his arms and teetered on a heel. “The porcupine.” He smiled greedily at the goat.

“Oh, totally. The porcupine is definitely who I want to meet,” said the goat. “I wonder what he does with all that money when the book is over.”

Dr. Cham nodded respectfully. “I’m very excited to see him wearing slippers.”

“Those infernal slippers!” said the goat and he haw-hawed coarsely, a shower of saliva cascading from his jaws.

Hannah’s mind rattled, waiting for this nonsense to break for a moment. She tipped her head on its side and the rattle slid along the curve of her cranium. The little noise died away, though, as the back of her head vanished (fluxed out is what she called it) and then her head was back again with its little rattle and she caught herself doing that careless moaning again. HRRRRRR-RRR-OH-RRRR-RRRR.

“I’m not as into the chunky bacon stuff,” said the goat. “I don’t see what’s so great about it.”

Could she speak while moaning? BON-BON. With a French moan. BOHN-BOHN. BOHN-APPE-TEET-OHHHH-RRRR.

“I know she’s harmless, but that sound freaks me out. My hair is completely on end.”

“Hannah?” said Dr. Cham. “Where are you, child? Come do a good turn for us, my niece.”

She was right near them, in and out. And they could hear her cleaning up her voice, bright, speaking like a angel scattering stardust. Yes, the whole maple donut story came out again, and more about the bakery she would own, the muffins and rolls and baguettes.

5. The Theft of the Lottery Captain

The piping and mixtures of the lotteries.

And now, Paij-ree’s stories of the Lotteries.

On Endertromb, the organist’s father invented the lottery. The idea came while he was praying to Digger Dosh.

Digger Dosh is sort of like their God. But ten times scarier. This guy dug an infinitely deep tunnel straight through the planet and came out dead. But he’s really not dead. He’s really just one second behind them. And he eats time.

It’s kind of complicated because Digger Dosh totally kills people. But I guess if you do what he says, it’s not so bad. Maybe I’ll talk about it later. It’s such a pain to talk about because it’s so scary and yet one of my friends actually believes the whole thing. I get kind of choked up—not like I’m crying, more like I’m choking.

Anyway, once while praying, three numbers came to Paij-ree’s father.

He then asked his mind, “What are these numbers?”

And his mind played a short video clip of him selling all kinds of numbers. And, for years and years, travelling and selling numbers.

And he asked his brain, “People will buy numbers?”

And his brain said, “If they buy the right three numbers, give them a prize.”

At which he imagined himself launching off a ski jump and showering people with presents. No question: he would be an icon.

So he went and did as his brain said and sold numbers. The father’s simple lottery consisted of three unique numbers, drawn from a set of 25 numbers.

 class LotteryTicket

   NUMERIC_RANGE = 1..25

   attr_reader :picks, :purchased

   def initialize( *picks )
     if picks.length != 3
       raise ArgumentError, "three numbers must be picked" 
     elsif picks.uniq.length != 3
       raise ArgumentError, "the three picks must be different numbers" 
     elsif picks.detect { |p| not NUMERIC_RANGE === p }
       raise ArgumentError, "the three picks must be numbers between 1 and 25." 
     end
     @picks = picks
     @purchased = Time.now
   end

 end

Yes, the LotteryTicket class contained the three numbers (@picks) and the time when the ticket was bought (@purchased). The allowed range of numbers (from one to twenty-five) is kept in the constant NUMERIC_RANGE.

The initialize method here can have any number of arguments passed in. The asterisk in the picks argument means that any arguments will be passed in as an Array. Having the arguments in an Array means that methods like uniq and detect can be used on the arguments together.

This class contains two definitions: the method definition (def) and an attributes definition (attr_reader). Both are really just method definitions though.

The attr_reader shortcut is identical to writing this Ruby code:

 class LotteryTicket
   def picks; @picks; end
   def purchased; @purchased; end
 end

Attributes are wrapper methods for instance variables (such as @picks) which can be used outside of the class itself. Paij-ree’s father wanted to code a machine which could read the numbers and the date of purchase from the ticket. In order to do that, those instance variables must be exposed.

Let’s create a random ticket and read back the numbers:

 ticket = LotteryTicket.new( rand( 25 ) + 1,
             rand( 25 ) + 1, rand( 25 ) + 1 )
 p ticket.picks

Running the above, I just got: [23, 14, 20]. You will get an error if two of the random numbers happen to be identical.

However, I can’t change the lottery ticket’s picks from outside of the class.

 ticket.picks = [2, 6, 19]

I get an error: undefined method `picks='. This is because attr_reader only adds a reader method, not a writer method. That’s fine, though. We don’t want the numbers or the date to change.

So, the tickets are objects. Instances of the LotteryTicket class. Make a ticket with LotteryTicket.new. Each ticket has it’s own @picks and it’s own @purchased instance variables.

The lottery captain would need to draw three random numbers at the close of the lottery, so we’ll add a convenient class method for generating random tickets.

 class LotteryTicket
   def self.new_random
     new( rand( 25 ) + 1, rand( 25 ) + 1, rand( 25 ) + 1 )
   end
 end

Oh, no. But we have that stupid error that pops up if two of the random numbers happen to be identical. If two numbers are the same, the initialize throws an ArgumentError.

The trick is going to be restarting the method if an error happens. We can use Ruby’s rescue to handle the error and redo to start the method over.

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

Better. It may take a couple times for the numbers to fall together right, but it’ll happen. The wait will build suspense, huh?

The lottery captain kept a roster of everyone who bought tickets, along with the numbers they drew.

 class LotteryDraw
   @@tickets = {}
   def LotteryDraw.buy( customer, *tickets )
     unless @@tickets.has_key?( customer )
       @@tickets[customer] = []
     end
     @@tickets[customer] += tickets
   end
 end

Yal-dal-rip-sip was the first customer.

 LotteryDraw.buy 'Yal-dal-rip-sip',
     LotteryTicket.new( 12, 6, 19 ),
     LotteryTicket.new( 5, 1, 3 ),
     LotteryTicket.new( 24, 6, 8 )

When it came time for the lottery draw, Paij-ree’s father (the lottery captain) added a bit of code to randomly select the numbers.

 class LotteryTicket
   def score( final )
     count = 0
     final.picks.each do |note|
       count +=1 if picks.include? note
     end
     count
   end
 end

The score method compares a LotteryTicket against a random ticket, which represents the winning combination. The random ticket is passed in through the final variable. The ticket gets one point for every winning number. The point total is returned from the score method.

 irb> ticket = LotteryTicket.new( 2, 5, 19 )
 irb> winner = LotteryTicket.new( 4, 5, 19 )
 irb> ticket.score( winner )
   => 2

You will see how brilliant Paij-ree is, in time. His father commissioned him to finish the lottery for him, while the demand for tickets consumed the lottery captain’s daylight hours. Can’t you just imagine young Paij-ree in his stuffy suit, snapping a rubber band in his young thumbs at the company meetings where he proposed the final piece of the system? Sure, when he stood up, his dad did all the talking for him, but he flipped on the projector and performed all the hand motions.

 class << LotteryDraw
   def play
     final = LotteryTicket.new_random
     winners = {}
     @@tickets.each do |buyer, ticket_list|
       ticket_list.each do |ticket|
         score = ticket.score( final )
         next if score.zero?
         winners[buyer] ||= []
         winners[buyer] << [ ticket, score ]
       end
     end
     @@tickets.clear
     winners
   end
 end

His father’s associates were stunned. What was this? (Paij-ree knew this was just another class method definition—they would all feel completely demoralized when he told them so.) They couldn’t understand the double angle bracket up there! Yes, it was a concatenator, but how is it in the class title?

Infants, thought Paij-ree, although he held everyone of those men in very high esteem. He was just a kid and kids are tough as a brick’s teeth.

The << operator allows you to alter the definition of an object. Had Paij-ree simply used class LotteryDraw, his play method would be a normal instance method. But since he used the << operator, the play method will be added directly to the class, as a class method.

When you see class << obj, believe in your heart, I’m adding directly to the definition of obj.

The budding organ instructor also threw in a tricky syntax worth examining. In the ninth line, a winner has been found.

 winners[buyer] ||= []
 winners[buyer] << [ ticket, score ]

The ||= syntax is a shortcut.

 winners[buyer] = winners[buyer] || []

The double pipe is an or logic. Set winners[buyer] equal to winners[buyer] or, if winners[buyer] is nil, set it to []. This shortcut is a little strange, but if you can really plant it in your head, it’s a nice timesaver. You’re just making sure a variable is set before using it.

 irb> LotteryDraw.play.each do |winner, tickets|
 irb>   puts winner + "won on " + tickets.length + " ticket(s)!" 
 irb>   tickets.each do |ticket, score|
 irb>     puts "\t" + ticket.picks.join( ', ' ) + ": " + score
 irb>   end
 irb> end

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

But these salad days were not to continue for Paij-ree and his father. His father often neglected to launder his uniform and contracted a moss disease on his shoulders. The disease gradually stole his equilibrium and his sense of direction.

His father still futilely attempted to keep the business running. He spiraled through the city, sometimes tumbling leg-over-leg down the cobbled stone, most often slowly feeling the walls, counting bricks to the math parlours and coachmen stations, where he would thrust tickets at the bystanders, who hounded him and slapped him away with long, wet beets. Later, Paij-ree would find him in a corner, his blood running into the city drains alongside the juices of the dark, splattered beets, which juice weaseled its way up into his veins and stung and clotted and glowed fiercely like a congested army of brake lights fighting their way through toll bridges.

A Word About Accessors (Because I Love You and I Hope For Your Success and My Hair is On End About This and Dreams Really Do Come True)

Earlier, I mentioned that attr_reader adds reader methods, but not writer methods.

 irb> ticket = LotteryTicket.new
 irb> ticket.picks = 3
 NoMethodError: undefined method `picks=' for #<LotteryTicket:0xb7d49110>

Which is okay in this case, since Paij-ree’s father didn’t want the numbers to be changed after the ticket was bought. If we were interested in having instance variables which had both readers and writers, we would use attr_accessor.

 class LotteryTicket
   attr_accessor :picks, :purchased
 end

Which is exactly the same as this lengthier code:

 class LotteryTicket
   def picks;           @picks;            end
   def picks=(var);     @picks = var;      end
   def purchased;       @purchased;        end
   def purchased=(var); @purchased = var;  end
 end

Holy cats! Look at those writer methods for a moment. They are the methods named picks= and purchased=. These methods intercept outside assignment to instance variables. Usually you will just let attr_reader or attr_accessor (or even perhaps attr_writer) do the work for you. Other times you may want to put a guard at the door yourself, checking variables in closer detail.

 class SkatingContest
   def the_winner; @the_winner; end
   def the_winner=( name )
     unless name.respond_to? :to_str
       raise ArgumentError, "The winner's name must be a String,
         not a math problem or a list of names or any of that business." 
     end
     @the_winner = name
   end
 end

Most of the time you won’t use this. But, as we move along through your lessons, you’ll find that Ruby has lots of escape hatches and alley ways you can sneak into and hack code into. I’m also preparing you for metaprogramming, which, if you can smell that dragon, is ominously near.

Paij-ree was an enterprising young Endertromaltoek. He hammered animal bones into long, glistening trumpets with deep holes that were plugged by corks the musicians banded to their fingers. Sure, he only sold three of those units, but he was widely reviled as a freelance scholar, a demonic one, for he was of a poorer class and the poor only ever acquired their brilliance through satanic practice. Of course, they were right, indeed, he did have a bargain with the dark mages, whom he kept appointments with annually, enduring torturous hot springs, bathing as they chanted spells.

He adored his father, even as his father deteriorated into but a gyroscope. He idolized the man’s work and spent his own small earnings playing the lottery. He loved to watch the numerals, each painted upon hollow clay balls, rise in the robloch (which is any fluid, pond or spill that has happened to withstand the presence of ghosts), the great bankers tying them together on a silver string, reading them in order.

Even today, Paij-ree paints the scenes with crude strokes of black ink on sheets of aluminum foil. It is very touching to see him caught up in the preciousness of his memory, but I don’t know exactly why he does it on aluminum foil. His drawings rip too easily. Paij-ree himself gets mixed up and will serve you crumbcake right off of some of this art, even after it has been properly framed. So many things about him are troubling and absurd and downright wretched.

The disease spread over his father’s form and marshy weeds covered his father’s hands and face. The moss pulled his spine up into a rigid uprightness. So thick was the growth over his head that he appeared to wear a shrub molded into a bowler’s hat. He also called himself by a new name—Quos—and he healed the people he touched, leaving a pile of full-blooded, greenly-cheeked villages in his wake as he travelled the townships. Many called him The Mossiah and wept on his feet, which wet the buds and caused him to weed into the ground. This made him momentarily angry, he harshly jogged his legs to break free and thrashed his fists wildly in the sky, bringing down a storm of lightning shards upon these pitiful.

Paij-ree was apart from the spiritual odysseys of his father (in fact, thought the man dead), so he only saw the decay of the lottery without its captain present. Here is where Paij-ree went to work, reviving the dead lottery of his family.

Gambling with Fewer Fingers

The city was crowded with people who had lost interest in the lottery. The weather had really worn everyone down as well. Such terrible rain flooding their cellars. The entire city was forced to move up one story. You’d go to put the cap back on your pen and you’d ruin the pen, since the cap was already full of slosh. Everyone was depleted, many people drowned.

Paij-ree found himself wasting his days in a quadruple bunkbed, the only furniture that managed to stay above sea level. He slept on the top bed. The third bed up was dry as well, so he let a homeless crater gull nest upon it. The gull didn’t need the whole bed, so Paij-ree also kept his calculators and pencils down there.

At first, these were very dark times for both of them, and they insisted on remaining haggard at all times. Paij-ree became obsessed with his fingernails, kept them long and pristine, while the rest of him deteriorated under a suit of hair. In the company of Paij-ree, the crater gull learned his own eccentrity and plucked all the feathers on the right side of his body. He looked like a cutaway diagram.

They learned to have happier times. Paij-ree carved a flute from the wall with his nails and played it often. Mostly he played his relaxed ballads during the daytime. In the evening, they pounded the wall and shook the bed frame in time to his songs. The gull went nuts when he played a certain four notes and he looped this section repeatedly, watching the gull swoop and circle in ectasy. Paij-ree could hardly keep his composure over the effect the little tune had and he couldn’t keep it together, fell all apart, slobbering and horse-giggling.

Paij-ree called the gull Eb-F-F-A, after that favorite song.

Friendship can be a very good catalyst for progress. A friend can find traits in you that no one else can. It’s like they searched your person and somehow came up with five full sets of silverware you never knew were there. And even though that friend may not understand why you had these utensils concealed, it’s still a great feat, worth honoring.

While Eb-F-F-A didn’t find silverware, he did find something else. A pile of something else. Since Paij-ree was stranded on the quadruple bed, the gull would scout around for food. One day, he flew down upon a barrel, floating over where the toolshed had been. Eb-F-F-A walked on top of the barrel, spinning it back to Paij-ree’s house and they cracked it open, revealing Paij-ree’s lost collection of duck bills.

Yes, real duck bills. (Eb-F-F-A was esophagizing his squawks, remaining calm, sucking beads of sweat back into his forehead—ducks were not of his chosen feather, but still in the species.) Paij-ree clapped gleefully, absolutely, he had intended to shingle his house with these, they could have deflected a bit of the torrent. Probably not much, nothing to cry about.

And the roof glue was at the barrel’s bottom and they were two enterprising bunkmates with time to kill, so they made a raft from the previously-quacked lip shades. And off they were to the country! Stirring through a real mess of city and soup. How strange it was to hit a beach and find out it was just the old dirt road passed Toffletown Junction.

In the country, they sold. It was always a long walk to the next plantation, but there would be a few buyers up in the mansion (“Welcome to The Mansion Built on Beets”, they’d say or, “The Mansion Built on Cellophane Substitutes—don’t you know how harmful real cellophane can be?”) And one of the families wrapped up some excess jelly and ham in some cellophane for the two travellers. And they almost died one day later because of it.

Then, when the heat came and, as the first countryside lottery was at nigh, a farmer called to them from his field, as he stood by his grazing cow. Paij-ree and Eb-F-F-A wandered out to him, murmuring to each other as to whether they should offer him the Wind-Beaten Ticket Special or whether he might want to opt in to winning Risky Rosco’s Original Homestyle Country Medallion.

But the farmer waved them down as he approached, “No, put your calculators and probability wheels away. It’s for my grazledon.” He meant his cow. The Endertromb version: twice as much flesh, twice as meaty, doesn’t produce milk, produces paper plates. Still, it grazes.

“Your grazledon (poh-kon-ic) wants a lucky ticket?” asked Paij-ree.

“He saw you two and got real excited,” said the farmer. “He doesn’t know numbers, but he understands luck a bit. He almost got hit by a doter plane one day and, when I found him, he just gave shrug. It was like he said, ‘Well, I guess that worked out okay.’”

“The whole (shas-op) lottery is numer-(ig-ig)-ic,” said Paij-ree. “Does he know (elsh) notes? My eagle knows (losh) notes.” Paij-ree whistled at the crater gull, who cooed back a sustained D.

The farmer couldn’t speak to his grazledon’s tonal awareness, so Paij-ree sent the gull to find out (D-D-D-A-D, go-teach-the-gra-zle) while he hacked some notes into his calculator.

 class AnimalLottoTicket

   # A list of valid notes.
   NOTES = [:Ab, :A, :Bb, :B, :C, :Db, :D, :Eb, :E, :F, :Gb, :G]

   # Stores the three picked notes and a purchase date.
   attr_reader :picks, :purchased

   # Creates a new ticket from three chosen notes.  The three notes
   # must be unique notes.
   def initialize( note1, note2, note3 )
     if [note1, note2, note3].uniq!
       raise ArgumentError, "the three picks must be different notes" 
     elsif picks.detect { |p| not NOTES.include? p }
       raise ArgumentError, "the three picks must be notes in the chromatic scale." 
     end
     @picks = picks
     @purchased = Time.now
   end

   # Score this ticket against the final draw.
   def score( final )
     count = 0
     final.picks.each do |note|
       count +=1 if picks.include? note
     end
     count
   end

   # Constructor to create a random AnimalLottoTicket
   def self.new_random
     new( NOTES[ rand( NOTES.length ) ], NOTES[ rand( NOTES.length ) ],
          NOTES[ rand( NOTES.length ) ] )
   rescue ArgumentError
     redo
   end

 end

No need for the animal’s tickets to behave drastically different from the traditional tickets. The AnimalLottoTicket class is internally different, but exposes the same methods seen in the original LotteryTicket class. The score method is even identical to the score method from the old LotteryTicket class.

Instead of using a class variable to store the musical note list, they’re stored in a constant called AnimalLottoTicket::NOTES. Variables change and the note list shouldn’t change. Constants are designed to stay the same. You can still change the constant, but you’ll have to be tricky or Ruby will speak up.

 irb> AnimalLottoTicket::NOTES = [:TOOT, :TWEET, :BLAT]
 (irb):3: warning: already initialized constant NOTES
   => [:TOOT, :TWEET, :BLAT]

The gull came back with the grazledon, his name was Merphy, he was thrilled to play chance, he puffed his face dreamily, whistled five and six notes in series, they all held his collar, pulled him close to the calculator and let him breathe three notes, then they choked the bedosh outta him until his ticket was printed and everything was nicely catalogued inside @@tickets['merphy']. Thankyou, see ya at the draw!

So, the fever of the lottery became an epidemic among the simple minds of the animals. Paij-ree saved his costs, used the same LotteryDraw class he’d used in the corporate environment of the lottery from his childhood. And soon enough, the animals were making their own music and their own maps and films.

“What about The Originals?” I asked Paij-ree. “They must have hated your animals!”

But he winced sourly and pinched his forehead. “I am an Original. You as well. Do we (ae-o) hate any of them?”

Not too long after the lottery ended, Paij-ree felt the crater gull Eb-F-F-A lighting upon his shoulder, which whistled an urgent and sad C-Eb-D C-A-Eb. These desparate notes sent an organ roll of chills straight through Paij-ree. Had the King God of Potted Soil, Our Beloved Topiary, the Mossiah Quos, Literal Father of That Man Who Would Be My Daughter’s Organ Instructor—had he truly come to his end? How could this be? Could the great arbors no longer nourish him and guide the moist crosswinds to him? Or did his own spindly lichen hedge up his way and grow against his breathing?

You never mind, went the tune of the gull. He has detoriated and weakened and fallen in the lit door of your home cottage. His tendrils needing and crying for the day to not end. For the sun to stay fixed and wide and attentive.

Plor-ian, the house attendant, kept the pitchers coming and Quos stayed well watered until Paij-ree arrived to survey the decaying buds of soft plant and the emerging face of his father, the lottery captain. His skin deeply pocked like an overly embroidered pillow. Great shoots springing from his sleeves now curled back with lurching thirst.

Paij-ree combed back the longer stems around his father’s eyes and those coming from the corners of his mouth. While I’d like to tell you that Paij-ree’s tears rolled down his sleeves and into the pours of his father, rejuvenating and restoring the grassy gentleman: I cannot say this.

Rather, Paij-ree’s tears rolled down his sleeves and into the creaking clapboard floor, nourishing the vile weeds, energizing the dark plant matter, which literally lept through the floor at night and strangled Our Quos. Yank, pull, crack. And that was his skull.

So Paij-ree could never be called Wert-ree or Wert-plo after that.

6. Them What Make the Rules

Hannah lept back from the wall and clenched down on her fingers.

“This is the wall,” said Dr. Cham. “The Originals are in there. My child, can you lead us to the observation deck?”

“You expect us to go up against those guys?” asked the goat. “They’re mad as koalas. But these koalas have lasers!”

“We prevail, though,” said Dr. Cham. “You and I know this.”

“Okay, well I’m muddled on that point,” said the goat. “Do we really win? Or could we be thinking about Kramer vs. Kramer? Does Dustin Hoffman win or do we win?”

“No. No. No. No.” Hannah hovered and dragged her legs along the wall nervously. “There is a man with a huge face in there!”

“Mr. Face,” said the Doctor. “He is the original face.”

“He didn’t see me,” said Hannah and moaned. HOMA-HOMA-ALLO-ALLO.

She made that hollow weeping through the crumbling mouseholes and the freezer gateways, fluxing in and out, causing the video checkpoints to hiss and the wall panels to brace themselves and fall silent. The three passed through two levels of frayed security and emerged in the observation deck overlooking the cargo bay.

Klon Ooper. Corwood. Mr. Face. Vonblisser.  The Originals.

“The last living among The Originals,” said Dr. Cham. “Are you alright with this, Hannah?” Which she didn’t hear in any way, as her eyes laid fixed on the legendary creatures.

“Look at them,” said the goat. “These guys wrote the rule books, Doctor. We owe everything to these guys.”

“What about God?” said Dr. Cham.

“I don’t really know,” said the goat. “Hannah probably knows better than any of us about that.”

Hannah said nothing. She only really knew one other ghost and that was her Post-Decease Mediator, Jamie Huft. Who didn’t seem to have any answers for her and required questions to be submitted in writing with a self-addressed stamped envelope included. Hannah hadn’t gotten the ball rolling on that P.O. Box yet.

“We must be up in the mountains,” said the goat. “Look out at that blackness.”

“I saw another deck like this down by where we found Hannah,” said Dr. Cham. “Down closer to your living area. You should take time to search for it. It’s very peaceful there. You can see Earth and the seven seas.”

“The seven seas?” The goat wondered if that was near The Rockettes. He’d read his share of material on precision dancing and he’d seen that line of legs, mincing across the stage like a big, glitsy rototiller.

Hannah stirred to life.

Hannah panicks. Maple donuts are within reach.

They couldn't hear them, but they saw their slides.

And none of the three spoke when The Originals flicked off the slide projector and boarded a very slender rocketship and cleanly exploded through a crevice in the cargo bay roof.

“Oh, boy,” said the goat.

“What?” said Hannah.

“You’re going to die,” said the goat.

Dr. Cham looked over the controls in front of them, a long panel of padded handles and green screens.

“I’m already dead. I’m a ghost.”

The goat looked down at the Doctor, who was rummaging under the control panel. “Okay, well if your uncle isn’t going to have a talk with you, I’m going to make things very clear. There’s a good chance these guys are going to build a bomb. And you see how I’m fidgeting? You see how my knees are wobbling?”

“Yeah.”

“Yeah, that’s how real this is, kid. I don’t remember anything from that confounded book except that these guys are building a bomb that can blow up the ghost world. Because once the ghost world’s gone, then Digger Dosh gets his one second back. It’s a trade they’ve worked out. Hell, it’s sick stuff, that’s all you need to know.”

“But I’m dead.”

“Okay, well, we’re talking, aren’t we? You can talk, so are you dead?” The goat shook his head. “I wish I could remember if we win or if it was Dustin Hoffman.”

Hannah cried. “Why do I have to die again?” She wailed and her legs fell into flux and she sunk into the floor. MOH-MOHHH-MAO-MAOOO.

Dr. Cham had forceably yanked on a plush handle, which unlocked and slid open like a breadbox. He reached his hands inside and found a keyboard firmly bolted deep inside.

“That’s it,” he said and pulled up irb, which appeared on a display to the left of his concealed typing. He checked the Ruby version.

 irb> RUBY_VERSION
   => "1.8.3"

Ruby was up-to-date. What else could he do? Scanning constants and class_variables was pointless. The only reason that had worked with the Elevator class was because someone had left irb running with their classes still loaded.

He had just loaded this irb, so no special classes were available yet. He had to find some classes. He started by loading the `rbconfig` file to get an idea of what Ruby’s settings were.

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

Too much information to sort through there. The Config::CONFIG constant is a Hash that contains every environment setting used to setup Ruby. You can find the operating system name at Config::CONFIG['host_os']. The directory where core Ruby libraries are stored can be found at Config::CONFIG['rubylibdir']. Ruby programs can store helper files at Config::CONFIG['datadir'].

What Dr. Cham really needed, though, was a list of all the libraries that aren’t core Ruby libraries. Libraries which were installed by The Originals or whoever manned this console. He checked a few global variables for this information.

 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", "bay://Ruby/lib/1.9", 
       "bay://Ruby/lib/1.9/i686-unknown", "."]

Aha, good. Dr. Cham stroked his beard and looked over his irb session. The $" global variable contains an Array of every library which has been loaded with require. Most of these libraries had been loaded by irb. He had loaded 'rbconfig.rb' earlier, though.

The $: global variable, which can also be accessed as $LOAD_PATH, contains a list of all the directories which Ruby will check when you try to load a file with require. When Dr. Cham ran require 'rbconfig', Ruby checked each directory in order.

 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

The second path was where Ruby ended up finding the rbconfig.rb file. Dr. Cham guessed that the first five paths were absolute paths. These were paths to directories on a drive called bay. Absolute paths may vary on your system. On Windows, absolute paths will start with a drive letter. On Linux, absolute paths start with a slash.

The directory "." indicates a relative path. The lone period represents the current work directory. The directory where Dr. Cham started up irb. So, after Ruby has searched all the standard places, it checks the current directory.

The goat had peeked his head around Dr. Cham and was watching all these instructions transpire, as he licked his lips to keep his salivations from running all over the monitors and glossy buttons. He had been interjecting a few short cheers (along the lines of: No, not that or Yes, yes, right or Okay, well, your choice), but now he was fully involved, recommending code, “Try require 'setup' or, no, try 3 * 5. Make sure that basic math works.”

“Of course the math works,” said Dr. Cham. “Let me be, I need to find some useful classes.”

“It’s a basic sanity test,” said the goat. “Just try it. Do 3 * 5 and see what comes up.”

Dr. Cham caved.

 irb> 3 * 5
   => 15

“Okay, great! We’re in business!” the goat tossed his furry face about in glee.

Dr. Cham patted the goat’s head, “Well done. We can continue.”

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

Dr. Cham had use chdir to change the current working directory over the the first path listed in $LOAD_PATH. This first path in site_ruby is a common place to store custom classes.

Here were the three legendary classes that my daughter’s organ instructor had inscribed for me earlier in this chapter. And, Dr. Cham, having read this selfsame chapter, recognized these three pieces of the system immediately.

The Endertromb class which contained the mysteries of this planet’s powers. The MindReader class which, upon scanning the minds of its inhabitants, read each mind’s contents. And, finally, the crucial WishMaker class which powered the granting of ten-letter wishes, should the wish ever find its way to the core of Endertromb.

“How about 4 * 56 + 9?” asked the goat. “We don’t know if it can do compound expressions.”

“I’ve got the MindReader right here,” said Dr. Cham. “And I have the WishMaker here next to it. This planet can read minds. And this planet can make wishes. Now, let’s see if it can do both at the same time.”

7. Them What Live the Dream

While The Originals’ craft had long disappeared, Dr. Cham frantically worked away at the computer built into the control panel up in the observation deck. Hannah had disappeared into the floor (or perhaps those little sparks along the ground were still wisps of her paranormal presence!) and the goat amicably watched Dr. Cham hack out a Ruby module.

 require 'endertromb'
 module WishScanner
   def scan_for_a_wish
     wish = self.read.detect do |thought|
       thought.index( 'wish: ' ) == 0
     end
     wish.gsub( 'wish: ', '' )
   end
 end

“What’s your plan?” asked the goat. “It seems like I could have solved this problem in like three lines.”

“This Module is the new WishScanner technology,” he said. “The scanner only picks up a wish if it starts with the word wish and a colon and a space. That way the planet doesn’t fill up with every less-than-ten-letter word that appears in people’s heads.”

“Why don’t you just use a class?” asked the goat.

“Because a Module is simpler than a class. It’s basically just a storage facility for methods. It keeps a group of methods together. You can’t create new objects from a method.”

“But aren’t you going to want a WishScanner object, so you can actually use it?” said the goat, appalled.

“I’m going to mix it into the MindReader,” said Dr. Cham. And he did.

 require 'mindreader'
 class MindReader
   include MindScanner
 end

“Now, the MindScanner module is mixed in to the MindReader,” said Dr. Cham. “I can call the scan_for_a_wish method on any MindReader object.”

“So, it’s a mixin,” said the goat. “The MindScanner mixin.”

“Yes, any module which is introduced into a class with include is a mixin to that class. If you go back and look at the scan_for_a_wish method, you’ll see that it calls a self.read method. I just have to make sure that whatever class I’m mixing MindScanner into has a read method. Otherwise, an error will be thrown.”

“That seems really wierd that the mixin requires certain methods that it doesn’t already have. It seems like it should work by itself.”

Dr. Cham looked up from the keyboard at the goat. “Well, it’s sort of like your video collection. None of your video cassettes work unless they are put in a machine that uses video cassettes. The depend on each other. A mixin has some basic requirements, but once a class meets those requirements, you can add all this extra functionality in.”

“Hey, that’s cool,” said the goat.

“You read the book thirty times and you didn’t pick that up?” asked Dr. Cham.

“You’re a much better teacher in person,” said the goat. “I really didn’t think I was going to like you very much.”

“I completely understand,” said the Doctor. “This is much more real than the cartoons make it seem.”

 require 'wishmaker'
 reader = MindReader.new
 wisher = WishMaker.new
 loop do
   wish = reader.scan_for_a_wish
   if wish
     wisher.grant( wish )
   end
 end

Irb sat and looped on the screen. It’ll do that until you hit Control-C. But Dr. Cham let it churn away. Looping endlessly, scanning the mind waves for a proper wish.

And Dr. Cham readied his wish. At first, he thought immediately of a stallion. To ride bareback over the vales of Sedna. But he pulled the thought back, his wish hadn’t been formed properly. A stallion was useless in pursuing The Originals, so he closed his eyes again, bit his lip and he thought to himself: wish: whale.

Last Whale to Peoplemud

The blocky, sullen whale appeared down at the castle entrance, where Hannah was bashing on a rosebud with her hand. She whacked at it with a fist, but it only stayed perfect and pleasant and crisp against the solid blue sky of Endertromb.

“I’m bored,” she said to the whale. BOHR-BOHR-OHRRRRRR.

“Ok,” said the whale, deep and soft. As the word slid along his massive tongue, its edges chipped off and the word slid out polished and worn in a bubble by his mouth’s corner.

“I always have to die,” said the young ghost. “People always kill me.”

The whale fluttered his short fins, which hung at useless distance from the ground. So, he pushed himself toward her with his tail. Scooting over patches of grass.

“People kill, so who do they kill?” said the girl. “Me. They kill me every time.”

The whale made it to within three meters of the girl, where he towered like a great war monument that represents enough dead soldiers to actually steal a lumbering step towards you. And now, the whale rested his tail and, exhausted by the climb thus far, let his eyelids fall shut and became a gently puffing clay mountain, his shadow rich and doubled-up all around the hardly visible Hannah.

But another shadow combined, narrow and determined. Right behind her, the hand came on to her shoulder, and the warm ghost inside the hand touched her sleeve.

“How did you get down here?” said the girl.

Dr. Cham sat right alongside her and the goat walked around and stood in front.

“Listen to us,” said Dr. Cham. “We’ve got to follow this mangy pack of ne’er-do-wells to the very end, Hannah. And to nab them, we need your faithful assistance!”

“I’m scared,” cried Hannah.

“You’re not scared,” said the goat. “Come on. You’re a terrifying little phantom child.”

“Well,” she said. “I’m a little bored.”

Dr. Cham bent down on a knee, bringing his shaggy presence toward the ground, his face just inches from hers. “If you come with us, if you can trust what we know, then we can bag this foul troupe. Now, you say your destiny is to be a baker. I won’t dispute that. You have every right on Earth—and Endertromb, for that matter—to become a baker. Say, if you didn’t become a baker, that would be a great tragedy. Who’s going to take care of all those donuts if you don’t?”

She shrugged. “That’s what I’ve been saying.”

“You’re right,” said the Doctor. “You’ve been saying it from the start.” He looked up to the sky, where the wind whistled peacefully despite its forceful piercing by The Originals’ rocketship. “If your destiny is to be a baker, then mine is to stop all this, to end the mayhem that is just beginning to boil. And hear me, child—hear how sure and solid my voice becomes when I say this—I ended your life, I bear sole responsibility for your life as an apparition, but I will get it back. It’s going to take more than a donut, but you will have a real childhood. I promise you.”

On the wished whale... away...

Sure, it took a minute for the goat to cut his wish down to ten letters, but he was shortly on his way, following the same jetstreams up into the sky, up toward Dr. Cham and his ghost niece Hannah. Up toward the villanous animal combo pak called The Originals. Up toward The Rockettes.

And Digger Dosh bludgeoned and feasted on each second they left behind them.


6.

Downtown

[o]

Lost in Wixl This heist goes all the way up?

Oblivious to their involvement in the expansive plan of The Originals, both the tall fox and the much shorter fox had wandered right into the red alert zone, the city Wixl. I desire a spatula to scoop them aside with, shuffle them off to the coast near the beach hatcheries, hide them in piles of fish eggs, hold down their pointy ears, concealing their luxurious hides. And above them I would stand, casting an unmoving shadow, holding my rifle aloof.

I can’t. I have you to teach. I have to groom and care for myself. The lightbulbs upstairs need changing. A free pack of halogen lightbulbs just showed up out of the mail. Somebody out there is obviously trying to get me to use them. So I’m going to screw ‘em in. And just stand there, casting an unmoving shadow, holding my rifle aloof.

Should that shadow be nice and defined, then I’ll keep ‘em.

1. If I Were Looking For a Vehicle

Sitting for a moment.

I like seeing these two out in the wild. They got pretty bored here in the studio. They started making up wierd slogans and stuff. They had some phrase they kept repeating, forming fixations upon. You can’t be exposed to all that contrived fox nonsense.

Let’s just say: I am really trying my best to keep things collegiate. Having never attended college, I can’t well say if every passage written chimes right with the stringent criteria which academia demands. I have university friends aplenty, some who tour the globe in their pursuits, and I try to inflect my voice with just their blend of high culture.

Sometimes I applaud myself for going beyond the work of my educated friends—only in quiet corridors, we never butt heads publicly—because I have actually subscribed to a school of thought while they are still in their books, turning and turning.

I am a preeventualist. I have dabbled in it long enough and am glad to come forth with it. Inevitably, some of you have already started mining this book for Marxist symbology. I am sad to kill those interpretations, but I believe any nihilist conclusions you’ve drawn will still hold up under scrutiny.

Anyway, I’ll drop the rhetoric. I only mention preeventualism because, aside from being a refreshing and easy alternative to the post-modernism we’re born with, this meta-cult offers a free lost-and-found service for the residents of Wixl.

 require 'open-uri'
 open( "http://preeventualist.org/lost" ) do |lost|
   puts lost.read
 end

I have no way of alerting the foxes to this service. And I’m sure it’s too soon for their truck to be listed. Still, the good intentions are here.

If you’re connected to the Internet, the above Ruby should have downloaded the web page from the Internet and printed it to the screen. In a message resembling this:

                   THE PREEVENTUALIST'S LOSING AND FINDING REGISTRY
          (a free service benefiting the ENLIGHTENED who have been LIGHTENED)

                                      ---
                      updates are made daily, please check back!
                                      ---

                         this service is commissioned and
                     subsidized in part by The Ashley Raymond
                                Youth Study Clan

                                      ...
                      all seals and privileges have been filed
                under the notable authorship of Perry W. L. Von Frowling,
          Magistrate Polywaif of Dispossession.  Also, Seventh Straight Winner
                   of the esteemed Persistent Beggar's Community Cup.
                                      ...

  ABOUT THE REGISTRY
  ==================
  Hello, if you are new, please stay with us.  A brief explanation of our service will 
  follow.  First, a bit of important news from our beloved magistrate.  (The kids call
  him Uncle Von Guffuncle. Tehe!)

  IMPORTANT NEWS
  ==============
  / 15 April 2005 /
  hi, big news.  we were on channel 8 in wixl and ordish.  cory saw it.  i was on and 
  jerry mathers was on.  if you didn't see it, e-mail cory.  he tells it the best.  all 
  i can say is those aren't MY hand motions!! (joke for people who watch channel 8.)  
  thanks harry and whole channel 8 news team!!
                                                   - perry

  / 07 April 2005 /
  we're all sifting through the carpet here at hq, but if you could all keep an eye out 
  for caitlin's clipboard, she's too quiet of a gal to post it and i know that it's 
  REALLY important to her.  she had a few really expensive panoramic radiographs of her 
  husband's underbite clipped to a few irreplacable photos of her husband in a robocop 
  costume back when the underbite was more prominent.  she says (to me), "they'll know
  what i mean when they see them."  i don't know what that means.  :(

  i've checked: * the front desk * the hall * the waiting area * the bathroom * the candy 
  closet * the big tv area * the lunch counter * the disciples room * gaff's old room
  (the one with the painting of the cherry tree) * the server room * staircase.  i'll 
  update this as i find more rooms.
                                                   - love, perry

  / 25 Feb 2005 /
  server went down at 3 o'clock.  i'm mad as you guys.  gaff is downstairs and he'll 
  be down there until he gets it fixed. :O -- UPDATE: it's fixed, back in bizz!!
                                                   - perry

  / 23 Feb 2005 /
  i know there's a lot of noise today.  stanley bros circus lost twelve llamas and a
  trailer and a bunch of Masterlocks and five tents.  they're still finding lost stuff.
  pls keep your heads, i need everyone's help.  these entertainers have _nothing_.  i 
  mean it.  i gave a guy a purple sticker today (it's just something i like to do as a
  kind gesture) and he practically slept on it and farmed the ingredients for pizza sauce
  on it.  they are on rock bottom.

  so please donate.  i know we don't have paypal or anything.  so if you want to donate,
  just post that you found something (a children's bike, a month of perishable canned 
  goods) and that it has the circus people's names written on it or something.
                                                   - great, perry

  / 15 Nov 2004 /
  preeventualist's day sale.  if you lose something today, you get to pick one free 
  item (of $40 value or less) from the house of somebody who found something.  we're 
  having so much fun with this!!  this is EXACTLY how i got my rowing machine last year
  and i LOVE IT!!
                                                   - perry

I think the Youth Study Clan is doing a great job with this service. It’s a little hokey and threadbare, but if it can get animals to stop using their instinctive means of declaring ownership, then hats off.

Still, a preeventualist youth group? How can that be? You’ve got to at least flirted with real cynicism before you can become a preeventualist. And you definitely can’t attend school. So, I don’t know.

Going back to the list of instructions from the Preeventualist’s Losing and Finding Registry.

 USING THE L&F SERVER
 ====================
 The L&F is a free service.  The acts of losing and finding are essential qualities in
 building a preeventualist lifestyle.  We hope to accomodate your belief.

 We do not use HTML, in order to simplify our work here.  Our guys are already working
 fifteen hour days.  (Thanks, Terk!!  Thanks, Horace!!)

 You may search our service for your lost items.  Or you may add your lost (or found)
 item to our registry.  This is done by typing the proper address into your browser.

 SEARCHING
 =========
 To search for lost items, use the following address:

   http://preeventualist.org/lost/search?q={search word}

 You may replace {search word} with your search term.  For example, to search for "cup":

   http://preeventualist.org/lost/search?q=cup

 You will be given a list of cups which have been lost or found.

 If you want to search for only lost cups or only found cups, use the `searchlost' and
 `searchfound' pages:

   http://preeventualist.org/lost/searchlost?q=cup

I’m not playing games. I know where the truck is. Really, I’m not teasing you. I’ll show you in just a sec. I’m just saying, look at the foxes:

Hummmmm.

They are helpless. And yet, here is this great tool. A possible key to getting out of this mess. I just want to poke around, see if there are any clues here.

 require 'open-uri'

 # Searching all found items containing the word `truck'.
 open( "http://preeventualist.org/lost/searchfound?q=truck" ) do |truck|
   puts truck.read
 end

I’m not seeing anything about the tall fox’s truck in this list. That’s okay. The foxes are out of it anyway. We have some time.

You’ve learned a very simple technique for retrieving a web page from the Internet. The code uses the OpenURI library, which was written by one of my favorite Rubyists, Akira Tanaka. He’s simplified reading from the Internet so that it’s identical to reading a file from your computer.

In a previous chapter, we stored your diabolical ideas in a text file. You read these files in Ruby using open.

 require 'open-uri'

 # Opening an idea file from a folder on your computer.
 open( "folder/idea-about-hiding-lettuce-in-the-church-chairs.txt" ) do |idea|
   puts idea.read
 end

Files are input-output objects. You can read and write to a file. In Ruby, all IO (input-output) objects have read and write methods. The open method slides an IO object down the chute into a block for your use. IO is your ticket to the outside world. It’s the rays of sunlight cast through the prison bars. (However, you can’t write to a web page with OpenURI. You’ll need to find a tool for copying to your web server. An FTP program, for instance.)

If someone wants to read your diabolical idea about hiding lettuce in the church chairs, assuming you’ve posted it as a web page:

 require 'open-uri'

 # Opening an idea file available on a web site.
 open( "http://your.com/idea-about-hiding-lettuce-in-the-church-chairs.txt" ) do |idea|
   puts idea.read
 end

The OpenURI library also understands FTP addresses as well. This widens the possibilities for where you can store files. On your system or elsewhere on the Internet.

Reading Files Line by Line

When you’re using OpenURI to get information from the web with the open and read methods, the page is given to you as a String. You can also read the page one line at a time, if you’re searching for something. Or if the page is big and you want to conserve your computer’s memory.

 require 'open-uri'
 open( "http://preeventualist.org/lost/searchfound?q=truck" ) do |truck|
   truck.each_line do |line|
     puts line if line['pickup']
   end
 end

The above code will retrieve the list of trucks found by preeventualists, then display only those lines that actually contain the word ‘pickup’. That way we can trim out the descriptions and look for only the pertinent lines.

Above, the index brackets are used on a string, so the string is searched for whatever is inside the brackets. Since the string 'pickup' is inside the brackets, the line string is searched for the word “pickup”.

On being funny.

When a web page is loaded with read, the entire page is loaded into memory. Usually this only takes up a few thousand bytes. But if a page is big (several megabytes), you’ll probably want to use each_line, which loads one line at a time to avoid exhausting memory.

Yielding is Kiddie Blocks

Ruby often uses iterators in this fashion. Yes, iterators are used for cycling through each item in a collection of items, such as an array or hash. Now look at an IO source as a collection of lines. The iterator can crawl that collection of lines.

 class IO
   # Definition for the each_line method.  Notice how it has no
   # argument list.  Blocks don't need to be listed as arguments.
   def each_line
     until eof?        # until we reach the end of the file...
       yield readline  # pass a line into the block
     end
   end
 end

The yield keyword is the easiest way to use a block. One word. Just like a curtain has a pullstring or like a suitcase has a handle. Inside a method, you can press the blinking yield button and it will run the block attached to that method. Glowing a strong red color until the code inside the block is done. And then it goes back to blinking and you can press the button again if you like.

 def yield_thrice
   yield
   yield
   yield
 end

Punch the yield button three times quick and the block gets to live its life three times.

 irb> a = ['first, birth.', 'then, a life of flickering images.', 'and, finally, the end.']
 irb> yield_thrice { puts a.shift }
 # prints out:
 #   first, birth.
 #   then, a life of flickering images.
 #   and, finally, the end.

The shift method pulls the first item off an array. The barber shift cuts the hair off and hands it over. Then, the scalp. And just keeps going, whittling the poor guy down to nothing.

You’ve seen blocks attached to methods. Any Ruby method can have block attached to the end.

 # The brief style of attaching a block to a method.
 # Here the block is surrounded with curly braces.
 open( "idea.txt" ) { |f| f.read }

 # The verbose style of attaching a block to a method.
 # Here the block is surrounded with `do' and `end'
 open( "idea.txt" ) do |f|
   f.read
 end

If you pass arguments to yield, those arguments will also be passed to the block. The block is riding in a little sidecar attached to the method’s motorcycle. The method yells out a list arguments, screaming to the block over all the wind as they’re racing through the desert. The block taps his helmet like, “I get it, my brain gets it.”

 # The method opens two files and slides the resulting IO objects down the
 # chute to an attached block.
 def double_open filename1, filename2
   open( filename1 ) do |f1|
     open( filename2 ) do |f2|
       yield f1, f2
     end
   end
 end

 # Prints the files out side-by-side.
 double_open( "idea1.txt", "idea2.txt" ) do |f1, f2|
   puts f1.readline + " | " + f2.readline
 end

You may also wonder what the yield keyword has to do with street signs. And really, it’s a good question with, I believe, a good answer. When you run a method, you are giving that method control of your program. Control to do its job and then come back to with an answer.

With yield, the method is stopping at the intersection, giving control back to you, to your block. The method is letting you do your work before resuming its work. So while the each_line method does the work of actually reading lines from a file, the block attached to the each_line method is handed the line itself and gets a chance to hammer away at it in the sidecar.

Preeventualism in a Gilded Box

You’ve learned so much about OpenURI and using yield to write your own iterators. You know your way around the lost-and-found service. Really, you can starting hunting through the Wixl junk drawer without me.

Let’s neatly encapsulate the entire service into a single class.

 require 'open-uri'
 module PreEventualist
   def self.open page, query
     qs = 
       query.map do |k, v|
         URI.escape "#{ k }=#{ v }" 
       end.join "&" 
     URI.parse( "http://preeventualist.org/lost/" + page + "?" + qs ).open do |lost|
       lost.read.split( "--\n" )
     end
   end
   def self.search word
     open "search", "q" => word
   end
   def self.searchlost word
     open "searchlost", "q" => word
   end
   def self.searchfound word
     open "searchfound", "q" => word
   end
   def self.addfound your_name, item_lost, found_at, description
     open "addfound", "name" => your_name, "item" => item_lost, 
                      "at" => found_at, "desc" => description
   end
   def self.addlost your_name, item_found, last_seen, description
     open "addlost", "name" => your_name, "item" => item_found,
                     "seen" => last_seen, "desc" => description
   end
 end

At some point with your code, you need to start shaping it into something neat. Save the above module in a file called preeventualist.rb.

This module is a very simple library for using the Preeventualist’s service. This is exactly the way libraries are written. You whip up a module or a class, store it in a file, and, if you’re happy with it and want the world to benefit, put it on the web.

These stragglers can you use your module just like I used OpenURI earlier.

 irb> require 'preeventualist'
 irb> puts PreEventualist.search( 'truck' )
 irb> puts PreEventualist.addfound( 'Why', 'Ruby skills', 'Wixl park',
        "I can give you Ruby skills!\nCome visit poignantguide.net!" )

2. Meanwhile, The Porcupine Stops To Fill-Up

The porcupine pays for gas.  Kites?

3. A Sponsored Dragon-Slaying

The slayer hops in.

“Look around,” said Fox Small. “Some of us don’t have time for quests. Some of us have major responsibilities, jobs, so on. Livelihood, got it?”

Heyyyy, my JOB was to kill the drgn!!” screamed the wee rabbit, blinking his eyes and bouncing frantically from tree to tree to pond to pond. “His snout was a HUGE responsibility!! His smoky breath was mine to reckon with!! I spent fifty dollars on the cab JUST to get out there, which was another huge huge ordeal. You have nothing on me, not a single indictment, my whole HERONESS is absoflutely unimpeachable, my whole APPROACH is abassoonly unapricotable, just ask Lester.”

“Who’s Lester?” said the Fox Small.

“Lester’s my cab driver! He parked at the base of Dwemthy’s Array!!” The rabbit ricocheted madly like a screensaver for a supercomputer. ”Just ask Dwemthy!!”

“Well,” said the Fox Small. He turned back to look up at Fox Tall, who was sitting straight and looking far into the distance. “Wait, they have a parking lot on Dwemthy’s Array?”

”YEP!! And a pretzel stand!!”

“But, it’s an Array? Do they sell churros?”

”CHOCOLAVA!!” bleeted the rabbit.

“What about those glow-in-the-dark ropes that you can put in your hair? Or you can just hold them by your side or up in the air—”

”BRAIDQUEST!!”

“You should get a cut of the salesman’s commission,” spoke Fox Small. “Folks came out to see you kill the dragon, right?”

”BUT!! I don’t operate the tongs that actually extract the chocolava.”

“I’m just sayin. You do operate the killing mechanism. So you have a stake in the ensalada.”

“OH NO!! I left my favorite lettuce leaves in Dwemthy’s Array!!” squealed the rabbit, twirling like a celebratory saber through the quaking oak. Distantly: “Or Lester’s trunk, maybe?”

“You know—Gheesh, can you stay put??” said Fox Small.

“My radio,” said Fox Tall, stirring to life for a moment, “in my pickup.” The glaze still seeping from his eyes. His stare quivered and set back into his face, recalling another time and place. A drive out to Maryland. Sounds of Lionel Richie coming in so clearly. The wipers going a bit too fast. He pulls up to a house. His mother answers the door. She is a heavily fluffed fox. Tears and makeup.

Slumping back down, “That porcupine is changing my presets.”

The rabbit bounded up on to the armrest of the park bench and spoke closely. ”BUT!! Soon I will feast on drgn’s head and the juices of drgn’s tongue!!” The rabbit sat still and held his paws kindly.

“(Which I hope will taste like cinnamon bears,)” whispered the rabbit, intimately.

“I love cinammon,” said Fox Small. “I should go killing with you some time.”

“You should,” said the rabbit and the eyes shine-shined.

“Although, salivating over a tongue. You don’t salivate over it, do you?”

“I DO!!” and the rabbit got so excited that Sticky Whip shot out of his eyes. (More on Sticky Whip in a later sidebar. Don’t let me forget. See also: The Purist’s Compendium to Novelty Retinal Cremes by Jory Patrick Sobgoblin, available wherever animal attachment clips are sold.)

“Okay, you’ve hooked me. I want to hear all about it,” Fox Small declared. “Please, talk freely about the chimbly. Oh, and Dwemthy. Who is he? What makes him tick? Then maybe, if I’m still around after that, you can tell me about what makes rabbits tick, and maybe you can hold our hands through this whole missing truck ordeal. I need consolation more than anything else. I could probably use religion right now. I could use your personal bravery and this sense of accomplishment you exude. Do you smoke a pipe? Could be a handy tool to coax along the pontification we must engage in.”

And the rabbit began expounding upon Dwemthy and the legend of Dwemthy and the ways of Dwemthy. As with most stories of Dwemthy, the rabbit’s tales were mostly embellishments. Smotchkkiss, there are delicacies which I alone must address.

Please, never ask who Dwemthy is. Obviously he is a mastermind and would never disclose his location or true identity. He has sired dynasties. He has set living ogres aflame. Horses everywhere smell him at all times. Most of all, he knows carnal pleasures. And to think that this…

This is his Array.

Dwemthy’s Array

Dwemthy's Array has charmed and tormented the village folk for centuries.

You stand at the entrance of Dwemthy’s Array. You are a rabbit who is about to die. And deep at the end of the Array:

 class Dragon < Creature
   life 1340     # tough scales
   strength 451  # bristling veins
   charisma 1020 # toothy smile
   weapon 939    # fire breath
 end

A scalding SEETHING LAVA infiltrates the cacauphonous ENGORGED MINESHAFTS deep within the ageless canopy of the DWEMTHY FOREST… chalky and nocturnal screams from the belly of the RAVENOUS WILD STORKUPINE... who eats wet goslings RIGHT AFTER they’ve had a few graham crackers and a midday nap… amidst starved hippos TECHNICALLY ORPHANED but truthfully sheltered by umbrellas owned jointly by car dealership conglomerates… beneath uncapped vials of mildly pulpy BLUE ELIXIR... which shall remain… heretofore… UNDISTURBED… DWEMTHY!!!

Luck and mother nature.

If you don’t understand Dwemthy’s Array, it is Dwemthy’s fault. He designed the game to complicate our lives and were it simpler, it would not be the awe-inspiring quest we’ve come to cherish in our arms this very hour.

Dwemthy’s Array has a winding history of great depth. It is not enough to simply say, “Dwemthy’s Array,” over and over and expect to build credentials from that act alone. Come with me, I can take you back a couple years, back to the sixties where it all started with metaprogramming and the dolphins.

You might be inclined to think that metaprogramming is another hacker word and was first overheard in private phone calls between fax machines. Honest to God, I am here to tell you that it is stranger than that. Metaprogramming began with taking drugs in the company of dolphins.

In the sixties, a prolific scientist named John C. Lilly began experimenting with his own senses, to uncover the workings of his body. I can relate to this. I do this frequently when I am standing in the middle of a road holding a pie or when I am hiding inside a cathedral. I pause to examine my self. This has proven to be nigh impossible. I have filled three ruled pages with algebraic notation, none of which has explained anything. The pie, incidentally, has been very easy to express mathematically.

But the scientist Lilly went about his experiments otherwise. He ingested LSD in the company of dolphins. Often in a dark, woeful isolation tank full of warm salt water. Pretty bleak. But it was science! (Lest you think him criminal: until 1966, LSD was supplied by Sandoz Laboratories to any interested scientists, free of charge.)

Drugs, dolphins and deprivation. Which led to Lilly’s foray into things meta. He wrote books on mental programming, comparing humans and computers. You may choose to ingest any substance you want during this next quote—most likely you’re reaching for the grain of salt—but I assure you that there’s no Grateful Dead show on the lawn and no ravers in the basement.

When one learns to learn, one is making models, using symbols, analogizing, making metaphors, in short, inventing and using language, mathematics, art, politics, business, etc. At the critical brain (cortex) size, languages and its consequences appear. To avoid the necessity of repeating learning to learn, symbols, metaphors, models each time, I symbolize the underlying idea in these operations as metaprogramming.

John C. Lilly, Programming and Metaprogramming in the Human Biocomputer, New York, 1972.

We learn. But first we learn to learn. We setup programming in our mind which is the pathway to further programming. (Lilly is largely talking about programming the brain and the nervous system, which he collectively called the biocomputer.)

Lilly’s metaprogramming was more about feeding yourself imagery, reinventing yourself, all that. This sort of thinking links directly to folks out there who dabble in shamanism, wave their hands over tarot cards and wake up early for karate class. I guess you could say metaprogramming is New Age, but it’s all settled down recently into a sleeping bag with plain old nerdiness. (If you got here from a Google search for “C++ Metaprogramming”, stick around, but I only ask that you burn those neural pathways that originally invoked the search. Many thanks.)

Meta itself is spoken of no differently in your author’s present day.

All sensuous response to reality is an interpretation of it. Beetles and monkeys clearly interpret their world, and act on the basis of what they see. Our physical senses are themselves organs of interpretation. What distinguishes us from our fellow animals is that we are able in turn to interpret these interpretations. In that sense, all human language is meta-language. It is a second-order reflection on the ‘language’ of our bodies—of our sensory apparatus.

Terry Eagleton, After Theory, London, 2003, ch. 3.

To that end, you could say programming itself is a meta-language. All code speaks the language of action, of a plan which hasn’t been played yet, but shortly will. Stage directions for the players inside your machine. I’ve waxed sentimental on this before.

But now we’re advancing our study, venturing into metaprogramming, but don’t sweat it, it’s still just the Ruby you’ve seen already, which is why Dwemthy feels no qualms thrusting it at you right away. Soon enough it will be as easy to spot as addition or subtraction. At first it may seem intensely bright, like you’ve stumbled across your first firefly, which has flown up in your face. Then, it becomes just a little bobbing light which makes living in Ohio so much nicer.

Metaprogramming is writing code which writes code. But not as M.C. Escher would sketch it. The program isn’t reaching back around and overwriting itself, nor is the program jumping onto your screen and wrenching the keyboard from your hands. No, it’s much smaller than that.

Let’s say it’s more like a little orange pill you won at the circus. When you suck on it, the coating wears away and behind your teeth hatches a massive, floppy sponge brontosaurus. He slides down your tongue and leaps free, frollicking over the pastures, yelping, “Papa!” And from then on, whenever he freaks out and attacks a van, well, that van is sparkling clean afterwards.

Now, let’s say someone else puts their little orange pill under the faucet. Not on their tongue, under the faucet. And this triggers a different catalysm, which births a set of wailing sponge sextuplets. Umbilical cords and everything. Still very handy for cleaning the van. But an altogether different kind of chamois. And, one day, these eight will stir Papa to tears when they perform the violin concerto of their lives.

Metaprogramming is packing code into pill-form, such that a slender drop of water could trigger it to expand. More importantly, you can control the pill’s reaction, so that a brontosaurus is produced, scaly and lumbering. Or septulets, CERTAINLY. Or seamstresses. Or cat brains. Or dragons.

 class Dragon < Creature
   life 1340     # tough scales
   strength 451  # bristling veins
   charisma 1020 # toothy smile
   weapon 939    # fire breath
 end

This is not metaprogramming yet. Only the pill. The product of metaprogramming. We are pausing, looking at the beast itself before descending beneath its flesh with a scalpel and microscope.

The Dragon is a class. You’ve seen that many times now. The Dragon is a descendant of the Creature class.

Now, eyes up. Look at me. The Creature class contains the metaprogramming code. You can write metaprogramming code which can be used everywhere, throughout Ruby, in Creature or Dragon, in String or in Object, anywhere. Our example here, since this is the most common form of meta-code, focuses on metaprogramming inside your own classes only.

Each of the Dragon’s traits are simply class methods. You could also write this as:

 class Dragon < Creature
   life( 1340 )     # tough scales
   strength( 451 )  # bristling veins
   charisma( 1020 ) # toothy smile
   weapon( 939 )    # fire breath
 end

Removing the parens removes clutter, so let’s leave them out. Only use parens when you are using several methods together and you want to be very clear.

Creature Code

Now, with a lateral slice across the diaphragm, we expose the innards of Creature. Save this code into a file called dwemthy.rb.

 # The guts of life force within Dwemthy's Array
 class Creature

   # Get a metaclass for this class
   def self.metaclass; class << self; self; end; end

   # Advanced metaprogramming code for nice, clean traits
   def self.traits( *arr )
     return @traits if arr.empty?

     # 1. Set up accessors for each variable
     attr_accessor *arr

     # 2. Add a new class method to for each trait.
     arr.each do |a|
       metaclass.instance_eval do
         define_method( a ) do |val|
           @traits ||= {}
           @traits[a] = val
         end
       end
     end

     # 3. For each monster, the `initialize' method
     #    should use the default number for each trait.
     class_eval do
       define_method( :initialize ) do
         self.class.traits.each do |k,v|
           instance_variable_set("@#{k}", v)
         end
       end
     end

   end

   # Creature attributes are read-only
   traits :life, :strength, :charisma, :weapon
 end

Focus on the closing lines of code, specifically the line where the traits are being set up. All of the code before that line sets up the traits class method. This bears resemblance to the basic lottery tickets from the chapter previous.

 class LotteryTicket
   attr_reader :picks, :purchased
 end

Both traits and attr_reader are simply class methods. When attr_reader is used in the LotteryTicket, metaprogramming kicks in behind the scenes and starts blowing up balloons, creating reader methods for the instance variables @picks and @purchased above.

The code for the traits method is the metaprogramming I’ve been alluding to. Comments in the code reveal the three stages the method goes through when adding traits.

  1. The list of traits is passed on to attr_accessor, which builds reader and writer code for instance variables. One for each trait.
  2. Class methods are added for each trait. (A life class method is added for a :life trait.) These class methods are used in the class definition just like you would use traits or attr_accessor. This way, you can specify the trait, along with the points given for a trait to a certain creature.
  3. Add an initialize method which sets up a new monster properly, grabbing the right points and POWER UP! POWER UP! the monster is alive!

The beauty of these three steps is that you’ve taught Ruby how to code monsters for you. So when Ruby gets to the traits:

 class Creature
   traits :life, :strength, :charisma, :weapon
 end

Ruby fills in the code behind the scenes and transplants a spiny green heart and jumpstarts the body with a pullcord. Ruby will use the metaprogramming from the Creature class and build out all the various methods, expanding the traits list like this:

 class Creature

   # 1. set up reader and writer methods
   attr_accessor :life, :strength, :charisma, :weapon

   # 2. add new class methods to use in creature
   def self.life( val )
     @traits ||= {}
     @traits['life'] = val
   end

   def self.strength( val )
     @traits ||= {}
     @traits['strength'] = val
   end

   def self.charisma( val )
     @traits ||= {}
     @traits['charisma'] = val
   end

   def self.weapon( val )
     @traits ||= {}
     @traits['weapon'] = val
   end

   # 3. initialize sets the default points for
   #    each trait
   def initialize
     self.class.traits.each do |k,v|
       instance_variable_set("@#{k}", v)
     end
   end

 end

Now, Ruby will gladly accept this six-line Dragon code, short enough to look nice when printed on playing cards:

 class Dragon < Creature
   life 1340     # tough scales
   strength 451  # bristling veins
   charisma 1020 # toothy smile
   weapon 939    # fire breath
 end

Eval, the Littlest Metaprogrammer

While the metaprogramming code above is just plain Ruby, it can be difficult to follow still. I totally understand if you’ve come to this point and your eyes are spinning in their sockets and your knees have locked up. The trickiest parts of the above are the lines which call the methods instance_eval and class_eval. Just rub some tiger balm on your joints while I talk about eval.

We’ve been talking about metaprogramming. Writing code which writes code. The eval method hangs out in this alley. The vagrant eval takes code you have stored up in a string and it executes that code.

 drgn = Dragon.new
 # is identical to...
 drgn = eval( "Dragon.new" )
 # or, alternatively...
 eval( "drgn = Dragon.new" )

Here, let’s write a program which has a hole in it. Instead of writing a program which creates a new Dragon, let’s leave a hole where the Dragon would be.

 print "What monster class have you come to battle? " 
 monster_class = gets
 eval( "monster = " + monster_class + ".new" )
 p monster

The program asks for a monster. If you type in Dragon, then the monster_class variable will contain the string "Dragon". Inside the eval, a few strings get added together to make the string "monster = Dragon.new". And when the eval executes this string, the monster variable contains a Dragon object. Ready for battle.

This is great! Now we can leave it up to the player to pick a monster! Of course, we’re trusting the player to supply a real monster class. If they type in BotanicalWitch and there is no BotanicalWitch class, they’ll get an exception tossed in their face.

So, in short, eval lets you make up code as you go. Which can be useful and which can be dangerous as well.

The instance_eval and class_eval method used in the metaprogramming for the Creature class are slightly different from the normal eval. These two special methods run code just like eval does, but they duck into classes and objects and run the code there.

 # The instance_eval method runs code as if it were run inside an
 # object's instance method.
 irb> drgn = Dragon.new
 irb> drgn.instance_eval do
 irb>   @name = "Tobias" 
 irb> end

 irb> drgn.instance_variable_get( "@name" )
   => "Tobias" 

 # The class_eval method runs code is if inside a class definition.
 irb> Dragon.class_eval do
 irb>   def name; @name; end
 irb> end

 irb> drgn.name
   => "Tobias"

As you can see above, the instance_eval and class_eval methods also can take a code block instead of a string. Which is just how things are done in Dwemthy’s Array.

Enough Belittling Instruction and Sly Juxtaposition—Where Is Dwemthy’s Array??

Tread carefully—here is the other half of DWEMTHY’S ARRAY!! Add these lines to dwemthy.rb.

 class Creature

   # This method applies a hit taken during a fight.
   def hit( damage )
     p_up = rand( charisma )
     if p_up % 9 == 7
       @life += p_up / 4
       puts "[#{ self.class } magick powers up #{ p_up }!]" 
     end 
     @life -= damage
     puts "[#{ self.class } has died.]" if @life <= 0
   end

   # This method takes one turn in a fight.
   def fight( enemy, weapon )
     if life <= 0
       puts "[#{ self.class } is too dead to fight!]" 
       return
     end

     # Attack the opponent
     your_hit = rand( strength + weapon )
     puts "[You hit with #{ your_hit } points of damage!]" 
     enemy.hit( your_hit )

     # Retaliation
     p enemy
     if enemy.life > 0
       enemy_hit = rand( enemy.strength + enemy.weapon )
       puts "[Your enemy hit with #{ enemy_hit } points of damage!]" 
       self.hit( enemy_hit )
     end
   end

 end

 class DwemthysArray < Array
   alias _inspect inspect
   def inspect; "#<#{ self.class }#{ _inspect }>"; end
   def method_missing( meth, *args )
     answer = first.send( meth, *args )
     if first.life <= 0
       shift
       if empty?
         puts "[Whoa.  You decimated Dwemthy's Array!]" 
       else
         puts "[Get ready. #{ first.class } has emerged.]" 
       end
     end
     answer || 0
   end
 end

This code adds two methods to Creature. The hit method which reacts to a hit from another Creature. And the fight method which lets you place your own blows against that Creature.

When your Creature takes a hit, a bit of defense kicks in and your charisma value is used to generate a power-up. Don’t ask me to explain the secrets behind this phenomenon. A random number is picked, some simple math is done, and, if you’re lucky, you get a couple life points. @life += p_up / 4.

Then, the enemy’s blow is landed. @life -= damage. That’s how the Creature#hit method works.

The fight method checks to see if your Creature is alive. Next, a random hit is placed on your opponent. If your opponent lives through the hit, it gets a chance to strike back. Those are the workings of the Creature#fight method.

I’ll explain DwemthysArray in a second. I really will. I’m having fun doing it. Let’s stick with hitting and fighting for now.

Introducing: You.

You may certainly tinker with derivations on this rabbit. But official Dwemthy Paradigms explicitly denote the code—and the altogether character—inscribed below. Save this as rabbit.rb.

 class Rabbit < Creature
   traits :bombs

   life 10
   strength 2
   charisma 44
   weapon 4
   bombs 3

   # little boomerang
   def ^( enemy )
     fight( enemy, 13 )
   end
   # the hero's sword is unlimited!!
   def /( enemy )
     fight( enemy, rand( 4 + ( ( enemy.life % 10 ) ** 2 ) ) )
   end
   # lettuce will build your strength and extra ruffage
   # will fly in the face of your opponent!!
   def %( enemy )
     lettuce = rand( charisma )
     puts "[Healthy lettuce gives you #{ lettuce } life points!!]" 
     @life += lettuce
     fight( enemy, 0 )
   end
   # bombs, but you only have three!!
   def *( enemy )
     if @bombs.zero?
       puts "[UHN!! You're out of bombs!!]" 
       return
     end
     @bombs -= 1
     fight( enemy, 86 )
   end
 end

You have four weapons. The boomerang. The hero’s sword. The lettuce. And the bombs.

To start off, open up irb and load the libraries we’ve created above.

 irb> require 'dwemthy'
 irb> require 'rabbit'

Now, unroll yourself.

 irb> r = Rabbit.new
 irb> r.life
   => 10
 irb> r.strength
   => 2

Good, good.

Rabbit Fights ScubaArgentine!

You cannot just go rushing into Dwemthy’s Array, unseatbelted and merely perfumed!! You must advance deliberately through the demonic cotillion. Or south, through the thickets and labyrinth of coal.

For now, let’s lurk covertly through the milky residue alongside the aqueducts. And sneak up on the ScubaArgentine.

 class ScubaArgentine < Creature
   life 46
   strength 35
   charisma 91
   weapon 2
 end

To get the fight started, make sure you’ve created one of you and one of the ScubaArgentine.

 irb> r = Rabbit.new
 irb> s = ScubaArgentine.new

Now use the little boomerang!

 irb> r ^ s
 [You hit with 2 points of damage!]
 #<ScubaArgentine:0x808c864 @charisma=91, @strength=35, @life=44, @weapon=2>
 [Your enemy hit with 28 points of damage!]
 [Rabbit has died.]

For crying out loud!! Our sample rabbit died!!

Grim prospects. I can’t ask you to return to the rabbit kingdom, though. Just pretend like you didn’t die and make a whole new rabbit.

 irb> r = Rabbit.new

 # attacking with boomerang!
 irb> r ^ s

 # the hero's sword slashes!
 irb> r / s

 # eating lettuce gives you life!
 irb> r % s

 # you have three bombs!
 irb> r * s

Pretty neat looking, wouldn’t you say? The code in rabbit.rb alters a few math symbols which work only with the Rabbit. Ruby allows you to change the behavior of math operators. After all, math operators are just methods!

 # the boomerang is normally an XOR operator.
 irb> 1.^( 1 )
   => 0

 # the hero's sword normally divides numbers.
 irb> 10./( 2 )
   => 5

 # the lettuce gives the remainder of a division.
 irb> 10.%( 3 )
   => 1

 # the bomb is for multiplication.
 irb> 10.*( 3 )
   => 30

Where it makes sense, you may choose to use math operators on some of your Classes. Ruby uses these math operators on many of its own classes. Arrays, for example, have a handful of math operators which you can see in the list of instance methods when you type: ri Array.

 # the plus operator combines two arrays into a single array
 irb> ["D", "W", "E"] + ["M", "T", "H", "Y"]
   => ["D", "W", "E", "M", "T", "H", "Y"]

 # minus removes all items in the second array found in the first
 irb> ["D", "W", "E", "M", "T", "H", "Y"] - ["W", "T"]
   => ["D", "E", "M", "H", "Y"]

 # the multiplier repeats the elements of an array
 irb> ["D", "W"] * 3
   => ["D", "W", "D", "W", "D", "W"]

You may be wondering: what does this mean for math, though? What if I add the number three to an array? What if I add a string and a number? How is Ruby going to react?

Please remember these operators are just methods. But, since these operators aren’t readable words, it can be harder to tell what they do. Use ri. Often you’ll find that the operators are identical to other readable methods. You can then choose to use the operator or the method. Whichever is clearer to you.

 # divide with an operator method ...
 irb> 10 / 3
   => 3

 # ... or a readable method?
 irb> 10.div 3
   => 3

And that’s how the Rabbit’s sword divides.

The Harsh Realities of Dwemthy’s Array AWAIT YOU TO MASH YOU!!

Once you’re done playchoking the last guy with his oxygen tube, it’s time to enter The Array. I doubt you can do it. You left your hatchet at home. And I hope you didn’t use all your bombs on the easy guy.

You have six foes.

 class IndustrialRaverMonkey < Creature
   life 46
   strength 35
   charisma 91
   weapon 2
 end

 class DwarvenAngel < Creature
   life 540
   strength 6
   charisma 144
   weapon 50
 end

 class AssistantViceTentacleAndOmbudsman < Creature
   life 320
   strength 6
   charisma 144
   weapon 50
 end

 class TeethDeer < Creature
   life 655
   strength 192
   charisma 19
   weapon 109
 end

 class IntrepidDecomposedCyclist < Creature
   life 901
   strength 560
   charisma 422
   weapon 105
 end

 class Dragon < Creature
   life 1340     # tough scales
   strength 451  # bristling veins
   charisma 1020 # toothy smile
   weapon 939    # fire breath
 end

These are the living, breathing monstrosities of Dwemthy’s Array. I don’t know how they got there. No one knows. Actually, I’m guessing the IntrepidDecomposedCyclist rode his ten-speed. But the others: NO ONE knows.

If it’s really important for you to know, let’s just say the others were born there. Can we move on??

As Dwemthy’s Array gets deeper, the challenge becomes more difficult.

 dwary = DwemthysArray[IndustrialRaverMonkey.new,
                       DwarvenAngel.new,
                       AssistantViceTentacleAndOmbudsman.new,
                       TeethDeer.new,
                       IntrepidDecomposedCyclist.new,
                       Dragon.new]

Fight the Array and the monsters will appear as you go. Godspeed and may you return with harrowing tales and nary an angel talon piercing through your shoulder.

Start here:

 irb> r % dwary

Oh, and none of this “I’m too young to die” business. I’m sick of that crap. I’m not going to have you insulting our undead young people. They are our future. After our future is over, that is.

The rabbit has changed us.

The Making of Dwemthy’s Array

Fast forward to a time when the winds have calmed. The dragon is vanquished. The unwashed masses bow. We love you. We are loyal to you.

But what is this centipede nibbling in your eardrum? You dig with your finger, but you can’t get him out! Blasted! It’s that infernal Dwemthy’s Array again. Explain yourself Dwemthy!

Here, I shall unmask the Array itself for you.

 class DwemthysArray < Array
   alias _inspect inspect
   def inspect; "#<#{ self.class }#{ inspect }>"; end
   def method_missing( meth, *args )
     answer = first.send( meth, *args )
     if first.life <= 0
       shift
       if empty?
         puts "[Whoa.  You decimated Dwemthy's Array!]" 
       else
         puts "[Get ready. #{ first.class } has emerged.]" 
       end
     end
     answer || 0
   end
 end

By now, you’re probably feeling very familiar with inheritance. The DwemthysArray class inherits from Array and, thus, behaves just like one. For being such a mystery, it’s alarmingly brief, yeah?

So it’s an Array. Filled with monsters. But what does this extra code do?

Inspect

The inspect method isn’t really a necessary part of Dwemthy’s Array. It’s something Dwemthy added as a courtesy to his guests. (Many call him twisted, many call him austere, but we’d all be ignorant to go without admiring the footwork he puts in for us.)

Every object in Ruby has an inspect method. It is defined in the Object class, so it trickles down through the pedigree to every wee child object just born.

 irb> o = Object.new
   => #<Object:0x81d60c0>
 irb> o.inspect
   => "#<Object:0x81d60c0>"

Have you noticed this? Whenever we create an object in irb, this noisy #<Object> verbage stumbles out! It’s a little name badge for the object. The inspect method creates that name badge. The badge is just a string.

 irb> class Rabbit
 irb>   attr_accessor :slogan
 irb>   def initialize s; @slogan = s; end
 irb>   def inspect; "#<#{ self.class } says '#{ @slogan }'>"; end
 irb> end

 irb> class FakeRabbit < Rabbit
 irb> end

 irb> Rabbit.new "i blow'd the drgn's face off!!" 
   => #<Rabbit says 'i blow'd the drgn's face off!!'>
 irb> FakeRabbit.new "Thusly and thusly and thusly..." 
   => #<FakeRabbit says 'Thusly and thusly and thusly...'>

The thing is: irb is talking back. Every time you run some code in irb, the return value from that code is inspected. How handy. It’s a little conversation between you and irb. And irb is just reiterating what you’re saying so you can see it for your self.

You could write your own Ruby prompt very easily:

 loop do
   print ">> " 
   puts  "=> " + eval( gets ).inspect
 end

This prompt won’t let you write Ruby code longer than a single line. It’s the essence of interactive Ruby, though. How do you like that? Two of your recently learned concepts have come together in a most flavorful way. The eval takes the typed code and runs it. The response from eval is then inspected.

Now, as you are fighting monsters in irb, Dwemthy’s Array will be inspected and replying with the monsters you have left to fight.

The foxes eat out.

Method Missing

Don’t you hate it when you yell “Deirdre!” and like ten people answer? That never happens in Ruby. If you call the deirdre method, only one deirdre method answers. You can’t have two methods named the same. If you add a second deirdre method, the first one disappears.

You can, however, have a method which answers to many names.

 class NameCaller
   def method_missing( name, *args )
     puts "You're calling `" + name + "' and you say:" 
     args.each { |say| puts "  " + say }
     puts "But no one is there yet." 
   end
   def deirdre( *args )
     puts "Deirdre is right here and you say:" 
     args.each { |say| puts "  " + say }
     puts "And she loves every second of it." 
     puts "(I think she thinks you're poetic.)" 
 end

When you call the method deirdre above, I’m sure you know what will happen. Deirdre will love every second of it, you and your dazzling poetry.

But what if you call simon?

 irb> NameCaller.new.simon( 'Hello?', 'Hello? Simon?' )
 You're calling `simon' and you say:
   Hello?
   Hello? Simon?
 But no one is there yet.

Yes, method_missing is like an answering machine, which intercepts your method call. In Dwemthy’s Array we use call forwarding, so that when you attack the Array, it passes that attack on straight to the first monster in the Array.

 def method_missing( meth, *args )
   answer = first.send( meth, *args )
   # ... snipped code here ...
 end

See! See! That skinny little method_missing passes the buck!

4. So, Let's Be Clear: The Porcupine Is Now To The Sea

The porcupine and his kite.

5. Walking, Walking, Walking, Walking and So Forth

The evening grew dark around the pair of foxes. They had wound their way through alleys packed with singing possums, and streets where giraffes in rumpled sportscoats bumped past them with their briefcases. They kept walking.

And now the stores rolled shut their corrugated metal lids. Crickets crawled out from the gutters and nudged at the loose change.

Why such hard feelings?

“Anyway, you must admit he’s a terrible President,” said Fox Small. ”Why does President Marcos have a rabbit as Vice President of the Foxes.”

“The Vice President? The rabbit with the eyebrows?”

“No, the rabbit with the huge sausage lips,” said Fox Small.

But their conversation was abruptly interupted by a freckly cat head which popped from the sky just above the sidewalk.

At least they're still in the book...

What is this about?!

Will the book finish?

Oh, come on. This is rich. More meta.

I’m not going to bother illustrating this discussion Blixy had with the foxes at this point! It’s all a bunch of conjecture. HOW can they presume to know the landscape of my family drama? I love my sister. For a long time, I worshipped her. (This is my sister Quil.)

I admit that there was a pretty painful day a few months ago and I kind of freaked out. I was laid out on the long patio chair by the pool in my mom’s backyard. I had a Dr. Pepper and a bit of german chocolate cake. I was eating with a kid fork. Everything else was in the dishwasher, that’s all they had. Three prongs.

My mom started talking about Quil. All about how much money she was blowing on pants and purses. A five-hundred dollar purse. And then she said, “She’s losing it. She sounded totally high on the phone.” (She nailed it on the head, Quil was smoking dope and loving it.)

So I’d been noticing how observant my mom could be. That’s why, when she said, &#