What Readers Are Saying About Seven Languages in Seven Weeks

Knowingmultipleparadigmsgreatlyinfluencesourdesignabilities,so I’malwaysonthelookoutforgoodbooksthat’llhelpmelearnthem. Thisbooknicelybringsprominentparadigmstogether.Brucehas experiencelearningandusingmultiplelanguages.Nowyoucangain fromhisexperiencethroughthisbook.Ihighlyrecommendit. Dr. Venkat Subramaniam Award-winningauthorandfounder,AgileDeveloper,Inc. Asaprogrammer,theimportanceofbeingexposedtonewprogramminglanguages,paradigms,andtechniquescannotbeoverstated. Thisbookdoesamarvelousjobofintroducingsevenimportantand diverselanguagesinaconcise—butnontrivial—manner,revealing theirstrengthsandreasonsforbeing.Thisbookisakintoadim-sum buffetforanyprogrammerwhoisinterestedinexploringnewhorizons orevaluatingemerginglanguagesbeforecommittingtostudyingone inparticular. Antonio Cangiano Softwareengineerandtechnicalevangelist,IBM Fastenyourseatbelts,becauseyouareinforafast-pacedjourney. Thisbookispackedwithprogramming-language-learningaction. Bruceputsitallontheline,andtheresultisanengaging,rewardingbookthatpassionateprogrammerswillthoroughlyenjoy.Ifyou lovelearningnewlanguages,ifyouwanttochallengeyourmind,if youwanttotakeyourprogrammingskillstothenextlevel—thisbook isforyou.Y o uwillnotbedisappointed. Frederic Daoud Author, Stripes...andJavaW e bDevelopmentIsFunAgain GettingStartedwithApacheClick and

Doyouwantsevenkickstartsintolearningyour“languageofthe year”?Doyouwantyourthinkingchallengedaboutprogrammingin general?Looknofurtherthanthisbook.Ipersonallywastakenback intimetomyundergraduatecomputersciencedays,coastingthrough myprogramminglanguagessurveycourse.Thedifferenceisthat Brucewon’tletyoucoastthroughthiscourse!Thisisn’taleisurely read—you’llhavetoworkthisbook.Ibelieveyou’llfinditbothmindblowingandintenselypracticalatthesametime. Matt Stine Groupleader,ResearchApplicationDevelopmentatSt.Jude Children’sResearchHospital IspentmostofmytimeasacomputersciencesstudentsayingIdidn’t Seven wanttobeasoftwaredeveloperandthenbecameoneanyway. expandedmywayofthinkingaboutprobLanguagesinSevenW e e k s lemsandremindedmewhatIloveaboutprogramming. Travis Kaspar Softwareengineer,NorthropGrumman Ihavebeenprogrammingfor25yearsinavarietyofhardwareand softwarelanguages.Afterreading SevenLanguagesinSevenW e e k s amstartingtounderstandhowtoevaluatelanguagesfortheirobjectivestrengthsandweaknesses.Moreimportantly,IfeelasifIcould pickoneofthemtoactuallygetsomeworkdone. Chris Kappler Seniorscientist,RaytheonBBNTechnologies


SevenLanguagesinSevenW eeks
APragmaticGuidetoLearning ProgrammingLanguages

The Pragmatic Bookshelf
Raleigh,NorthCarolina Dallas,Texas

Many of the designations used by manufacturers and sellers to distinguish their productsareclaimedastrademarks.Wherethosedesignationsappearinthisbook,andThe Pragmatic Programmers, LLC was aware of a trademark claim, the designations have been printed in initial capital letters or in all capitals. The Pragmatic Starter Kit, The Pragmatic Programmer, Pragmatic Programming, Pragmatic Bookshelf and the linking devicearetrademarksofThePragmaticProgrammers,LLC. Every precaution was taken in the preparation of this book. However, the publisher assumes no responsibility for errors or omissions, or for damages that may result from theuseofinformation(includingprogramlistings)containedherein. Our Pragmatic courses, workshops, and other products can help you and your team create better software and have more fun. For more information, as well as the latest Pragmatictitles,pleasevisitusat http://www.pragprog.com. Theteamthatproducedthisbookincludes: Editor: Indexing: Copyedit: Layout: Production: Customersupport: International: JackieCarter PotomacIndexing,LLC KimW m ip s e t StevePeter JanetFurlow EllieCallahan JulietBenda


Copyright © 2010PragmaticProgrammers,LLC. Allrightsreserved. Nopartofthispublicationmaybereproduced,storedinaretrievalsystem,ortransmitted, in any form, or by any means, electronic, mechanical, photocopying, recording, or otherwise,withoutthepriorconsentofthepublisher. PrintedintheUnitedStatesofAmerica. ISBN-10:1-934356-59-X ISBN-13:978-1-934356-59-3 Printedonacid-freepaper. P1.0printing,October2010 V e r s o in :2010-10-28

. . . 1.3 BuyThisBook . . . .. . .2 3. . . . . . . . . . .. . . . . .. . Day3:SeriousChange ..... . . . .. . . .. . . . . . . . . .. . .2 Day1:AnExcellentDriver. ... . ... . . . . . . . . . .. .. . . .3 2. . . . .. . . .. .. . . . . . Day1:FindingaNanny . . . . .. . Ruby 2. . . . .. 1. . .. 1.. . . 4.HangingOut . .. .. . . . . . . . . .. . . . .. . . . . . . . . .. . .5 W r a p p n igUpProlog. .. .. . ..4 Day3:BlowingUpV e g a s . ... . . . .4 Don’tBuyThisBook . . . .. . . . . .. .1 2. . .. . . . . . .. .Contents Dedication Acknowledgments Foreword 1 Introduction 1.5 AFinalCharge.. . . .. .. . .. . . . Day1:SkippingSchool. . . . . . . .. . . . .2 TheLanguages ... . . Day2:FloatingDownfromtheSky . .5 Io 3. .. . .. .4 2. .1 AboutProlog . .. 4.. . Day3:TheParadeandOtherStrangePlaces . . . . .. . . . . . . . . . . 4. .. . . . . 1. .. . . . . . . . . . . . .. . .. . . W r a p p n igUpRuby .. . .. 4 Prolog 4. .. . .2 2. . . .. . .5 9 11 14 17 17 19 21 22 24 25 26 28 35 48 56 60 60 61 74 83 92 95 96 97 109 120 132 2 QuickHistory . .4 3. .. . . Day2:TheSausageKing ... . .. . .. . . 4. . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . .. . .1 3. .1 MethodtotheMadness . . . .. . .. . . . . . . W r a p p n igUpIo . . . . . 3 IntroducingIo .. . .3 Day2:FifteenMinutestoW a p n e r . . . . ... ... . . . . .3 3. .

. . . . . . . . . . . . . . . .. . . . . . 8. . . . Day3:CuttingThroughtheFluff . . . . . . .3 ProgrammingConstructs . . . .3 Day2:ChangingForms .3 Day2:Y o d aandtheForce . Bibliography Index 7 8 9 A Reporterratum thiscopyis (P1. . . . . . . . . . . . . . . . . . . . . . . . . . . Clojure 7. . . . . . . .4 Day3:TheMindMeld . . . Day2:ClippingBushesandOtherNewTricks . . . .. . . . .4 5. . . . ... . .CONTENTS 8 5 Scala 5. . . . . . . . . . . . 7. .. . . . 6. . . .2 Day1:Training Luke . . . . .3 5. . . . . . . . . . . . .. . . . . . . . . . . . . . . . .1 IntroducingHaskell. . . . . . . . . . . . . . . . . . . . .2 5. . . . 8. . . . . . . 9. . . . . W r a p p n igUpScala .. . . . . . . . . .. . . 7. .0printing. . . 135 135 139 153 167 176 181 181 185 195 207 219 223 224 225 243 256 264 268 268 269 285 294 309 313 313 317 319 321 322 323 6 Erlang 6. . . . . . . . . . . . . . . . . Day1:TheCastleontheHill .5 W r a p p n igUpErlang . . . . .1 5. . . . . . . . . . .. . . .. . 6. . . . . . 6. . . . . . . . . . . . . . . 8.. . . . . . . . . . . . . .2 Day1:Logical . . . . . . . . Haskell 8. . . . . .. 9. . . . . . . . . . . . . .. . . . .1 IntroducingClojure . . . . .. .1 IntroducingErlang . . . . .4 Day3:AnEyeforEvil . . . . . . . . . . .5 W r a p p n igUpClojure . 7. . . . . . . . . 6. . . Wrap-Up 9. . .. . . . .. . ... . . . . . .2 Day1:AppearingHuman . .1 ProgrammingModels . . . . . . . . .5 W r a p p n igUpHaskell . . . . . . . . . . .5 AboutScala . . . 8. 7. . . . . . . . . . . . . . . .. . . . . .4 FindingY o u rV o c ie . .October2010) . . . . . . . . . . . . . . . . . .2 Concurrency . . . . . . . . .3 Day2:Spock’sGreatStrength . . . . . . . . . . . . . . . . .4 Day3:TheRedPill . . . .. . . . . . . . 9. .

)InlateMarch. Mom looked over my shoulder and told me what she saw.shewasgone.Afewshortweekslater. No one had any clue that anything was wrong at all.Ihadtheopportunitytotakeafew lessonsfromher. After a few flicks of her talented wrist added darks to accentuatedepthandhighlightstoaddclarityanddetail. ThebiggestshockofallcameinearlyMarch. I am left to struggle with the grief of a jarring and unexpected loss because of a brutally efficient disease.Forsomeonefromatechnicalprofession.notyet47yearsold.Iwouldvisualizethemasterpiece onmyblankcanvas.BeforeIlefthome.Mybrother. I would not be human otherwise. this experience has not been an entirely negative one.Astheactualimagetookshape. and she was exactly where she wanted to be with her faith.Dedication ThefivemonthsfromDecember2009throughApril2010were among themostdifficultofmylife.hademergency bypass surgery.mysisterwasdiagnosedwithbreastcancer.Iwouldthrow myexcitedarmsupinvictoryandtelleveryoneintheclassaboutthis thingIhadcreated.Mymotherwasdiagnosed withterminalcancer.notyetrealizingthateachmemberoftheclasswas goingthroughtheirownprivateburstofjoy.WhenIdespairedthatthingswere beyond my ability to fix. But strangely. As you would expect. Lynda Lyle Tateputhercreativeenergyintopaintingwithwatercolors.Then.theexperiencewasalwaysalittledisorienting.itdriftedfurther andfurtherfrommyoriginalvision.herrelationshipswithherfamilywerestrong and fulfilling. my mother was at peace with the remarkablelifeshelived. She shared her art primarily through her Madison Avenue Art Gallery andherclasses.Itjusttookagiftedtouchto bringbackmycreationfromthebrinkofdisaster. (He came through the surgery without further incident and is doingwell.IwouldrealizethatIhadnotbeentoofarastrayatall. . Y o u see.

When I told my mother that I would dedicate this book to her. Reporterratum thiscopyis (P1.0printing.D EDICATION 10 Afteralittlewhile.Encounteringalostspousehereoratroubledmarriage there. ThisbookisdedicatedwithlovetoLynda Lyle Tate. comforting those who came to comfort her.too. and your enthusiasm and love of life guide me even now.yourloveofcreativity shaped me. But Mom. but she had nothing to do with computers. Through her church and through her profession.Thatistrueenough. As we spent our last week together.amacanvasshapedbythemaster. she’d find brokenpeople.1936–2010. As I think about these experiences.TheverythoughtofW n id o w swouldleave her helpless. person after person would come throughherroomdevastatedatthethoughtoflosingtheirteacher.October2010) .mymotherwouldbringthemintoclasswhereshewouldusethe paint and paper to slightly open a door that had been slammed shut. you have had everything to do with o u r me. she said that she would like that.IlearnedthatMomwasworkingonanothercanvas as well.but Mom would tell the perfect joke or offer the right word of kindness. Y well-timedwordsofencouragementinspiredme. I got to meet the human canvaseswhohadbeenputrightbythemasterandgoneontodogreat things. I can’t help but feel a little better andalittlestrongerbecauseI.Itwasahumblingexperience.

I can definitely appreciate how much of this language feels right.ToCharlesNutter. Y o u invited me to Japan to visit the place where Ruby was born. Thanksalsoforcontributing . thanks for the conversations about topics in this book that must have seemed tiresome but helped me refine and shape the message. Kayla and Julia. and that experience inspired me muchmorethanyouwilleverknow. Thanks also for your thoughtful reviews and your interview that helped me capture the essence of Io. thanks to Brian Tarbox for sharing your remarkableexperiencewithmyreaders. Thanks first and foremost to my family.featured on Nova.youaremyjoyandinspiration.It’salsothemost rewarding. The people who have offered to help in various ways have made it so. In the Prolog community. In the Io community. They were timely and helped build a much stronger chapter. your writing amazes me. Y o u can’t yet imagine what you can accomplish.Y o u rreviews were among the best. certainly add a dramatic flair to the Prolog chapter. Y o u captured the imagination of the beta readers and createdthefavoritelanguageofmanyofthem.ThanksalsotoMatzforyourfriendshipandyouroffer to share your thoughts with my readers. Steve Dekorte.Maggie. whether or not the marketplace ever recognizes it as so. Special thanks go to Joe Armstrong. and the language has intrinsic beauty. thanks to Jeremy Tregunna for helping me get pluggedinandsharingsomecoolexamplesforthebook. and Tim Bray. The concurrency features rock. Y o u can see how much your feedback shaped the chapter andthe overallbook. In the Ruby community.Acknowledgments ThisisthemostdemandingbookIhaveeverwritten. thanks to Dave Thomas for turning me on to the language that turned my career upside down and helped me havefunagain. Thanks for helping this neophyte debug his installation.EvanPhoenix.Thedolphinprojects. you’ve created something special.

Y o u r approach in your consulting practiceisgreatlyappreciated. In the Clojure community.Y o u rbookwasalsohugelyinfluential in the Clojure chapter and actually changed the way I attacked some problems in other chapters as well.October2010) . I enjoyed working through your interview. Y o u r Scala book is both rich and understandable. W e share a passion for teaching. thanks to Phillip W a d e lr for the opportunity to look inside the process that created Haskell.Ivanovic.FredDaoud.Y o u r ’ebringingmuch-neededsimplicity and productivity to this industry. Y o u formed the most effective review team I’ve ever worked with. The book is much Reporterratum thiscopyis (P1.0printing.Y o u v ’efoundawaytomakeLisprevolutionary. Thanks also to Rich Hickey for your thoughtful ideas onthe creation ofthe language and what it means to be a Lisp dialect. Scala takes a unique and brave approach to integrating functional programming paradigms with object-oriented paradigms. Antonio Cangiano. ThanksalsotoMartinOderskyforhelpingthisstrangerbysharingyour thoughts with my readers. Thanks also to Simon Peyton-Jones. They were the rightexamplesdeliveredattherighttime. Erlang’s “Let it crash” philosophy makes sense to me. The reviewers did an outstanding job with this book. thanks to my good friend V e n k a t Subramaniam. Y o u r insights into Clojure and your instincts helped me understandwhatwasimportant.Y o u rkindness and energy have helped me form the ideas in this book. the insights youadded. Some ideas in Clojure are intensely radical and yet sopractical.Again. Y o u r tireless promotionofthewaydistributed. I hope to seethoseideasmorebroadlyadopted. I greatly appreciate your review and the little bits of help that you offered along the way. IntheErlangcommunity. Thanks to VladimirG.Y o u reffortsaregreatlyappreciated. More than any other idea in any other language in this book.IagainthankJoeArmstrong.fault-tolerantsystemsshouldbebuilt is working. In the Scala community. and you’re very good at it. I leaned on it heavily.A CKNOWLEDGMENTS 12 your map-coloring example and your ideas for Append.andtheuniqueperspectiveyoubroughttothesereaders.PaulButcher. In the Haskell community. David Eisinger. and Brian Tarbox. thanks to Stuart Halloway for your reviews and ideas that forced me to work harder to bring a better book to my readers. Those little bits of your time saved me tremendous anguish and let me focus on the task of teaching.AaronBedra.Congratulations.CraigRiecke.

andIanW a r s h a kmadesignificantcontributions.October2010) . I think that real hard-copy books havevalue.the indexer.DaveThomasandAndyHunt. Finally.youhavehadanincalculable impact on my career as a programmer and again as an author. As always. I know that reviewing a book at this level of detail is thankless. ThesekindsofconversationsmademelooksmarterthanIreallyam. and Janet Furlow.includingKimW m ip s e t .Anyoversight wasnotintentional. Ialsowanttothankthoseofyouwhosharedyourideasaboutlanguage choiceandprogrammingphilosophy.SethMaislin.MikePerham. demanding work.andIcanfollowmypassionandwritebecauseyoudo. Y o u rcommentshaveshownmethatagoodnumberofyouareworking throughthelanguagesratherthancasuallyskimming.thankyouforreadingthebookandkeepingmeworking. Betareaders. Steve Peter. Thisbookwouldnotbewhatitiswithoutyou. Specifically. the producer.John Heintz. your gentle hand and guidance were what this book needed. Finally.A CKNOWLEDGMENTS 13 stronger for it. Thanks to all the members of the publishing team. BruceTate Reporterratum thiscopyis (P1. Those of us who still like technical books thankyou.NealFord. I offer my sincerest gratitude.0printing.thecopyeditor.too. thanks to all of my readers. I want to thank the team thatlaboredsohardtomakethisbooklookgoodandcorrectallofmy badhabits. Thanks to those who labored in my shadow to make this book the best it could be. ForthoseofyouImissed.I’vechangedthe bookbasedonhundredsofcommentssofarandexpecttodoevenmore throughoutthelifeofthebook. and I hope you enjoyed our conversations as much as I did.W e cantake abooklikethisonethatmightnotbeasattractivetothemassmarket and make it financially worthwhile.Atvarioustimes.Thepublishingbusinesscouldnotexistwithoutyou. the typesetter. mistakes that slipped through this fine team are all mine. This publishingplatformhasmadewritingviableagainforme. Jackie Carter. to the team at the Pragmatic Bookshelf.Ioffermysincerestapologies.

” Learning to program is like learning to swim.but whenyoubobtothesurfaceandgulpinsomeair.” “Willitmakethembetteratpunctuationandmakethemgettheirquotes right?” “Notnecessarily. Bruce Tate is such a teacher.“thesignofanilliterateprogrammeranda decadentculture.CreatorofErlang “TheGmaileditorcannotgettypographicquotesright..”Atleastthat’showIfeltwhenIlearned toswim. gettingstarted.namely. andyouneedagoodteachertoencourageyoutojumpintothewater.”saidMargery. .Y o u thinktoyourself.butitwillmakethemabetterprogrammer.Thefirsttimeyousinkunderthewater..It’saZen thing. The first steps are the most difficult.“Icanswim. No amount of theory is a substitute for diving into the pool and flailing around in the water gaspingforair.youpanic. This book gives you the opportunity to startwithwhatisthemostdifficultpartoflearningtoprogram..youfeelelated.”’ “Allsevenvolumes?” “Allsevenvolumes. It’s the same with programming.Foreword From the yet to be written “How Proust Can Make You a Better Programmer” byJoeArmstrong .” “Whatshouldwedoaboutit?” “Wemustinsistthatthenextprogrammerwehirehasreadallof‘Ala recherchedutempsperdu.” “Disgraceful.

Ioften find that I need to understand a bit of Python or Ruby to solve a particular problem. you can sit back and relax. Just type in the programs and program fragments in this book to see whether you can reproduce his results. you will be able to see which language is best suited to the kinds of problems thatinterestyoumost.F OREWORD 15 Let’s assume that you’ve actually managed the difficult task of downloading and installing the interpreter or compiler for the language you are interested in. Onceyou’vegottenthroughthemechanicsofenteringandrunningprograms. By learning several different programming languages. you willbeabletotackleyourownprogrammingprojects. its strengths. Reporterratum thiscopyis (P1. The programs I download from the Internet are often writteninavarietyoflanguagesandneedalittletweakingbeforeIcan usethem. Getting started with programming in a new language is not so much a deep exercise in understanding the underlying principles that a language embodies.October2010) . Each language has its own set of idioms. Thefirststepinacquiringanynewskillisnotbeingabletodoyourown thing but being able to reproduce what other people have done before you. What should you do next? What will be your first program? Bruce neatly answers this question.0printing. Don’t think about writing your own programs yet—just try to reproduce the examples in the book. As you grow in confidence. your subconscious is figuring out the deep meaning that lies underneath the surface structures. Knowingasmallamountaboutmanylanguagesisausefulskill.Itisnotuntil yougetbeyondthemessybusinessofenteringaprogramandgettingit throughthecompilerthatyoucanevenstarttothinkaboutthemeaningofthedifferentlanguageconstructs. Then you’ll wake up one day suddenly understandingthedeepermeaningofalogicprogramorwhyaparticularlanguagehadaparticularconstruct. and its weaknesses. Whileyourconsciousbrainisfiguringoutwheretoputthesemicolons. it is rather a matter of getting the semicolons and commas in the right places and understanding the weird error messagesthatthesystemspitsoutwhenyoumakeanerror. Y o u r subconscious does the rest.Thisisthequickestwaytomasteringaskill.

F OREWORD 16 I’mpleasedtoseethatBruce’stasteinprogramminglanguagesiseclectic. but actually trying it out was virtually impossible.TobebetteratFP. but we can try them in practice. not only can we read about the ideas. I warmly recommend this book and hope that you enjoy reading it as muchasIhave. Books on comparative programming languages were popular when I grewupasaprogrammer.Tobetterunderstand the essence of OO programming.October2010) .youshouldstudyAssembler.andunderstandingisaboutideas.0printing.butmostofthesewereacademictomesthat gave little practical guidance to how to actually go about using a language.Hecoversnotonlythewell-establishedlanguagessuchasRubybut alsoless-well-appreciatedlanguageslikeIo. Today.creatorofErlang 2March2010 Stockholm Reporterratum thiscopyis (P1. JoeArmstrong.programmingis aboutunderstanding.Thusitiswithprogramming. This reflected the technology of the age. This makes the difference between standing on the poolside wonderingwhetheritwouldbenicetoswimanddivinginandenjoying thewater.exposure to new ideas is essential to a deeper understanding of what programmingisallabout. A Zen master might tell you that to be better at mathematics you’d betterstudyLatin.So. you should study logic or functional programming(FP). Y o u could read about the ideas in a language.Ultimately.

I’ll look for a quick interactive tutorial. fast dive. My goal is to experience the language in a controlled environment. But sometimes you decidetoconqueranewlanguagenotbecauseyouhavetobutbecause you want to learn. Y o u learned your firstlanguagetolive.Ifyoulearnedasecondlanguage. a short tutorial is never going to work.Mygoalisnottomakeamotherlydemand likeyourmorningspoonfulofcodliveroil.Y o umayevenseekenlightenment.Iwillintroduceyou tosevendifferentlanguages.Iwanttoguideyouthrough a journey that will enlighten you and change the way you look at programming. Soitiswithprogramminglanguages. But usually. I need a deep. you might have to learn a second language to further your career or adapt to a changing environment. If I want to get the true flavorofalanguagethatismorethanasubtleextensionofoneIalready know. .thereasonscouldbeverydifferent. I can go off scriptandexplore. If I want.Inthisbook. Sometimes. but I’ll teach you more than “Hello.andcoreconcepts.W o r d l” .1 MethodtotheMadness Most of the time. A second language can help you encounter new worlds.butI’mbasicallylookingforaquickjoltofcaffeine.knowingeverynewlanguage canshapethewayyouthink. asnapshotofsyntacticsugar. 1. I won’t make you an expert. the experience is not fulfilling.Chapter 1 Introduction People learn spoken languages for different reasons.Itgaveyouthetoolstogetthroughyoureveryday life. when I’m learning a new programming language or framework.

Y o uwillfindalogic-based programming language (Prolog). defining theuser’sexperiencebytheirabsenceandlackofcohesion. like C++ and Java.you’llneedasoundunderstandingofthecollections.October2010) . W e won’tattacklargeenoughprojectstofullydiveintopackaging models.Collectionsplayavitalrolein justaboutanylanguage. The typing model will shape the way you attack a problem and control the way the language works. but you’ll encounter a broad mix of static and dynamic. The languages in this book lean on the strong typing end of the spectrum.I’llbegintoexplorewithaninteractiveshell.Clojure. Several of the languages are multiparadigm languages.Learningnewprogrammingparadigmsisoneofthemostimportantconceptsinthisbook. static (Java) or dynamic (Ruby).Scala). • Whatarethecorefeaturesthatmakethelanguageunique? Some of the languages will support advanced features for concurrent programming.Either way. or some type of hybrid? This book has languages spanning four different programming models and.fourlanguagesthatare functionalinnature(Scala.Y o u l’seepatternmatching inErlangandunificationinProlog.Inthis book. Others provide unique high-level constructs such asClojure’smacrosorIo’smessageinterpretation.0printing. functional. like Scala. I will move on to files when it’s time to attack bigger projects.andsomehavevirtualmachineswhileothersdon’t.combinationsofmorethanone. thecollectionsaredefiningcharacteristicsofthelanguage.andoneprototype language (Io). Every languageinthisbookhasitsowntypingidiosyncrasies. • How will you interact with it? Languages are compiled or interpreted. Clojure’s multimethods will even let you implementyourownparadigm. two languages with full support forobject-orientedconcepts(Ruby. sometimes. Y o u will find how the tradeoffs impact a developer. Y o u l’findanswerstothefollowingquestions: • What is the typing model? Typing is strong (Java) or weak (C). • What are the decision constructs and core data structures? Y o u d ’ besurprisedhowmanylanguagescanmakedecisionswiththings otherthanvariationsof ifsand whiles.M ETHOD TO THE M ADNESS 18 This book will give you such an experience not once but seven times. • What is the programming model? Is it object-oriented (OO). procedural.Haskell).ifthereisone.Erlang.InlanguagessuchasSmalltalkandLisp.Otherswillgive Reporterratum thiscopyis (P1.Inothers. collections are all over the place.

Io is the most controversial language I included. This object-oriented language gets high marks for ease of useandreadability.wehadeightpotentialcandidates. Along with Prolog.October2010) . I’ve worked hard to solve some difficult problems in Java or C Reporterratum thiscopyis (P1. Some languages support programming models that are laser-focused on a particularproblem.T HE L ANGUAGES 19 youasuperchargedvirtualmachine.Prolog. • Prolog. When we rolled up all the data.isaprototypelanguagelikeJavaScript. but I found myself wanting to compare thedifferentprogrammingparadigmstoobject-orientedprogramming (OOP). I simply asked potential readers. Io.2 TheLanguages Choosing the languages in this book was much easier than you might imagine.Iohasasmallfootprint.Iknowit’sold. I decided to take a dive into Ruby metaprogramming.Ibrieflyconsiderednotincludinganyobjectoriented language at all. When you’re through.butyou will knowwhateachuniquelyhastooffer.whichwasatop-tenlanguage on the list. and Ruby was higher on the list. That made roomforasurprisingcandidate. It is not commercially successful.Let’sgetto thelanguages. but the concurrency constructswiththesimplicityanduniformityofsyntaxareimportantconcepts.I’mquitehappywiththeresult.Solving a Sudoku in Prolog was an eye-opening experience for me. These are the languages that did make the cut and the reasonsIpickedthem: • Ruby. allowing me to extend the syntax of the language. I also struck Python because I wanted no more thanone object-oriented language. you will not be an expert in any of these languages.andthesimilarities toLisparesometimesstriking.Because of it.0printing.suchasusinglogictosolveconstraints. 1. Erlang will let you build fault-tolerant distributed systems much more quickly than you can in other languages. Y e s . • Io. so including at least one OOP language was important. I also wanted to push Ruby a little harder than most programmers do and give readers a flavor for the core decisions that shaped the design of Ruby.IstruckJavaScriptbecauseit was too popular and replaced it with the next most popular prototype language.Theminimalsyntaxispowerful.butitisalsoextremelypowerful.likeErlang’sBEAM.andhasauniquemessagedispatch mechanismthatIthinkyou’llfindinteresting.

whichwasinstrumentaltobridgingproceduralprogrammingandOOP. Like Prolog. That means you won’t find mutable state anywhere.Scalahasbroughtstrongfunctionalconceptstothe Javaecosystem. supporting perhaps the most flexible programming model in the book. helped me gain a deeper appreciation of this language thatstronglyinfluencedErlang. distribution. including a huge Java library and widelyavailabledeploymentplatforms. One of a new generation of languages on the Java virtualmachine. The same function with the same input parameters will give you the same output.buttheresultswill beworthit.October2010) .T HE L ANGUAGES 20 that would have been effortless in Prolog.AsyoudiveintotheScalacommunity.thisLisp-dialectmakessomeradical changes in the way we thinkaboutconcurrencyonthe JVM. the parentheses are greatly reduced.Ifyou’veneverhadanoccasionto useit. you’ll see why. But unlike other Lisp dialects.Erlangisgathering steam as a functional language that gets concurrency. Reporterratum thiscopyis (P1. W e included several dozen languages in the survey mentioned earlier. • Haskell.Lookingback. Of all the strongly typed languages. • Scala. every time.IseeastrikingsimilaritytoC++.Believeme.oneof theemergingcloud-baseddatabases. This language is the only pure functional language in the book. Haskell supports the most widely respected typing model. Oneoftheoldestlanguagesonthislist. • Erlang.Ithinkyouwillbepleasantlysurprised. you’ll see why Scala represents pure heresy to pure functional programmersandpureblisstoJavadevelopers. As a Lisp dialect.Afterspendingalittletimewiththisdistributedlanguage.ThecreatorsofCouchDB.0printing. I’msorryifyourfavoritelanguagedidn’tmakethelist. Joe Armstrong.ItalsoembracesOOP. and you have a huge ecosystem to lean on. Erlang makes designing concurrent. Clojure packs plenty of punch. It is the only language in this book that uses the same strategy in versioned databases to manage concurrency. • Clojure.choseErlangandhavenever lookedback.andfaulttoleranceright. fault-tolerant applications much easier than you could haveeverthoughtpossible. distributed. creator of Erlang. AnotherJVMlanguage.I’ve already gotten hate mail from more than a few language enthusiasts.itwilltakealittlewhiletounderstand.

butindulgeme.IalsousesometechniquesthatareunconventionalintheRubycommunity.andthe new paradigm stuck. Helpo f rDangerousTimes Many of the readers of this book won’t be old enough to remember thelasttimeourindustryswitchedprogrammingparadigms. That claim mightseemalittlenebulous. 1. After a couple of successful side projects.October2010) . As the Java language became more limiting forme. Many developers got caught with old skills and hadtocompletelyretoolthewaytheythought.thetoolstheyused. I reach for mutable variables less and do a better job with code blocks andhigher-orderfunctions.3 BuyThisBook . Atworst. but each oneisunique. I pushed mycareerhardinthatdirectionandhaveneverlookedback.Hehas challenged thousands of students to learn a new language every year.withsomethingimportanttoteachyou.and thewaytheydesignedapplications.bylearninglanguages.MyRuby careerstartedwithbasicexperimentationandgrewintomore..newcomputerdesignswillbethedriver. W r t i n g this book has had a profound impact on the Ruby code that I write.ThesuccessfulJava programminglanguagegaveusahardshoveinthatdirection.buttheymakemycodemoreconcise andreadable.if you are a competent programmer who wants to grow.IexperimentedwithRubytobetterunderstanditsapproachto web development.0printing.youcouldlaunchanewcareer. but the oldstructuralprogrammingparadigmwassimplyunabletohandlethe complexity requiredformodernweb applications. LearningtoLearn DaveThomasisoneofthefoundersofthispublishingcompany.you’lllearntofoldnewconceptsback intothecodethatyouwriteinyourchosenlanguage.programming paradigms change. It is more functional and is easier to read with less repetition.Everytenyearsorso.Thistime.Fiveofthesevenlanguagesinthisbook Reporterratum thiscopyis (P1. Atbest.Ourshift to object-oriented programming had a couple of false starts.B UY T HIS B OOK 21 Those languages that I picked are not necessarily the best. W e maybeinthemidstofanothertransformation..

In Ruby.0printing. I’m going to go out on a limb and say that the languages in this book havesomecompellinganswerstooffer. Erlang. As a reader..D ON ’ T B UY T HIS B OOK 22 have compelling concurrencymodels. you’llsolveafullSudoku.orErlang’s“Letitcrash”philosophy. To successfully cover themostimportantdetailsofeachlanguage.you’regoingtohave to be willing to go beyond the basic syntax. fourdecadesworthoflanguagedevelopment.W o r d l”orevenaFibonacci series. Y o u can also find insight in surprising places.)Whetherornotyourprogramminglanguagechangesrightaway.Ineedtomakesomesimplifyingassumptions. In Prolog.CheckoutIo’simplementation offutures. 1. I have to cover an enormously broad set of topics for you. Joe Armstrong started that language from a Prolog foundation.until you’ve read this section and agree. is a great example.AndinErlang. the language behind the scenes for several of the cloud-style databases. (Ruby and Prolog are the exceptions. My part of the deal is to teach you more in a shorter time.you’llwriteamonitorthatcan detect the death of another process and launch another one or inform theuser. but when you’re through the book. I am going to make a deal withyou. Dr. Y o u l’have to Google a little more.Asanauthor.Understand how Haskell programmers leave mutable state behind or how Clojureusesversioningtosolvesomeofthemostdifficultconcurrency problems.4 Don’tBuyThisBook .Scala’sactors. Reporterratum thiscopyis (P1. you’llknowmuchmorebecauseI’llbeabletodivedeeper. Pleaserecognizethatsevenlanguagesisanambitiousundertakingfor both of us.Y o uagreetoletmefocusontheprogramminglanguagerather than installation details.. you will get to do some metaprogramming. IWillT a k e You BeyondSyntax Toreallygetintotheheadofalanguagedesigner. you’re going to have to stretch your brain around seven different syntax styles. four programming paradigms.andmore. and you can’t rely on me to support your installation. I learned several of these languages to support this book. That means you’ll have to codesomethingmorethanthetypical“Hello.October2010) .

Icannotsupportyourinstallations. and at least five different Unix versions. you’ll be working from up-to-date instructions from thesamelistaseveryoneelse. Knowing a language as a tourist passing through is far different from beinganativespeaker. C. And the compromise: I won’t be able to cover some basics that you’d expect to find in dedicated language books. I speak dozens of others haltingly. please understand that I cannotpossiblyfullysupportyourendeavorsineachlanguage. I suspect that you’re not remotely interested in reading another outdated installation guide.Ican’tsupportinstallationforsevenlanguages.Imadeacommitment to you and a compromise. C++. Java. OS X.Sevenlanguagesonsevenplatforms is an insurmountable topic for a single author and probably for amultiauthorbook.I’mconfidentthatthismaterialwillcapturethe spiritofeachprogramminglanguageprettywellbythetimeithasgone through the entire review process. I speak Basic. Insomecases. I asked to find a restroom in Italy. IW o n ’ tBeY our InstallationGuide Oneofmybiggestchallengesistheplatform. and a few others fluently. C#. including the languages in this book. except where it’s a fundamental feature of the language. I’m not qualified to support six Reporterratum thiscopyis (P1.October2010) . JavaScript. That said. That way.IorderedfishinJapan.Ihavehaddirectcontact fromreadersofvariousbooksusingthreedifferentW n id o w splatforms. Iknowafewphrasesinthreeotherlanguages. I will not go into packaging models in detail because we’ll be dealing with small projects that do not require them.IspeakEnglishfluentlyandSpanishhaltingly. I’ll tell you where to go to install the language. Ruby. From the programming side.0printing. Languages and platforms change.so I’mnotgoingtotry. But I know my limitations. I’ve seen comments on variousmessageboardsofmanymore. I will rarely go through exception processing. The commitment: I won’t settle for a superficial treatment.D ON ’ T B UY T HIS B OOK 23 ThesecondthatIdecidedtogodeeperthanthebasics.Iwould liketomakeacomparisontospokenlanguages.weareluckyenoughtogetareviewfromthepersonwho designedthelanguage.Iwillnotgooverprimitivesthatwedon’tneedtosolvethebasic problemsIlayoutforyou. and I’ll tell you what version I’m using. IW o n ’ tBeY our ProgrammingReference W e v ’e tried hard to get you strong programming reviews for this book.

Ineachoftheexercises.A F INAL C HARGE 24 of the languages on this list.0printing.Y o uwon’tbehappy with me. If you find yourself nervous after reading this description. IAmGoingtoPushY ou Hard This book is going to take you one step beyond your twenty-minute tutorial.Iwillwalkyouthroughexamples ineachlanguages. 1.andyou’llseeexamplesofthoseprograms.butitwillbeinformativeandfun.October2010) . IwouldfailbadlyifItriedtoprovideanexhaustivereferenceforeachof these languages. I could make a programming guide that’s at least as long as this book on any of the separate languages in here. and you’ll be able to find one of those simple primers for every language on this list. Itwillmakeyouself-reliant. Havefun. If you simply read this book.motivationalwordsto say. Learning syntax is alwayseasierthanlearningtoreason. The languages on this list all have exceptional support communities.Y o uwillwanttotrytheexercisesfirst. Reporterratum thiscopyis (P1.ButIcouldn’t supportyourprogrammingeffortsevenifIwanted.let’spushon. It’s not going to beeasy. I write Ruby full-time and have for five years now. I suggest thatyouputdownthisbookandpickupanother. Y o u l’ also get some small programming challenges and one programming project every week.you’llfail. fully recognizing that you’ll fail at a few of them.Iwilldo mybesttocompileeverythingandmakesureitallruns. I will give youenoughinformationtogetstarted. Y o u know Google as well as I do. you’ll experience the flavor of the syntax and no more. If you look online for the answers before trying to code theexercisesyourself.Itryto haveasectionthatasksyoutofindresources.Iexpectedtohavesomesweeping.butitallseemedtoboildowntotwowords. Y o u would probably be better served by seven different programmingbooks. I will give you a quick interactive tour. But I couldn’t tell you how to write a web server in Io or a databaseinErlang.Butifyoufindyourselfexcitedabouttheprospectof codingbetterquickly. That’spartofthereasonIpickedthem.Thisideaisintentional.5 AFinalCharge Atthispoint.

learning a language is like learning a character. At the time. Throughout the book. Like any person. the British nanny.DVD.butshe’salwaysgoodforahaircutandtremendously fun to talk to. He was fun when he was younger. doesn’t worry 1. . everything changed. V s iu a l Basic was like that bleached-blond cosmetologist. Syntactic sugar describes a language feature that makes code easier to read and write. Throughout my career. MeetRuby. 2.DirectedbyRobertStevenson.She’ssometimesquirky.andabsolutelymagical. I’ve experienced scores of languages firsthand. Matz. I will compare the languages you will encountertopopularcharacters.Javawaslikehavingarichlawyer as a brother.CA:W neyV d ie o . W t i h a spoonful of sugar.alwaysbeautiful.Rubydoesthesamethingandwithmore syntactic sugar 2 than a spoonful. Ruby’s creator. She’s not going to solve globalwarming. 1 a t l DisMaryPoppins . MaryPoppins Chapter 2 Ruby If you are sampling this book.thoughtherearealternativewaystoexpressthesamecode.Aspoonfulofsugarmakesthemedicinegodown.1964. most nannies were like most of the C family of languages—draconian beasts who were mercilessly efficient but about as fun as taking that shot of cod liver oil every night. chances are we have something in common: learning programming languages intrigues us. each languagetookonadistinctpersonality.LosAngeles. To me. but now he’s a black hole that sucks away all the joy in a 100-mile radius.alittlemysterious.2004.ThinkMaryPoppins. Mary Poppins made the household more efficient by making it fun and coaxing every last bit ofpassionfromhercharges.Ihopethecomparisonswill help you unlock a little bit about the character that makes each language special.oneofmyfavorites.

0printing. and polymorphism(objectscantakemanyforms).andheagreedtoanswersomequestionsforthisbook.Rubypatientlywaitedforthe right moment and then burst onto the scene around 2006 with the emergenceoftheRailsframework. As a language.thetrade-offfor such a strategy is flexibility versus execution safety. They are the means of programming but also enhancers for your mind that shape the way you think about programming. 2.Dynamicallytypedmeansthattypesarebound atexecutiontimeratherthancompiletime. but it makes programmers very productive.Ievenimplementedseveraltoylanguagesbutnor e a lones.InterpretedmeansthatRubycodeisexecutedbyaninterpreter ratherthanacompiler.1 QuickHistory Y u k h ir io Matsumoto created Ruby in about 1993.Q UICK H ISTORY 26 about the efficiency of the language. Smalltalk. Japan. object-oriented. He optimizes the efficiency of the programmers.Itwasmerehobbyatthebeginning. for a hobby.whenIsawPerl.Iwassomehowinspiredthatanobject-oriented language that combines characteristics from Lisp.W e hadthechancetohavesomeconversationsaboutthefoundationsofRuby.otherprogrammersallover Reporterratum thiscopyis (P1. inheritance through classes (object types are organized in a class tree). InterviewwithY u k h ir o i (Matz)Matsumoto I had the pleasure to travel to Matsumotosan’s hometown of Matsue. In1993.Afterwanderingfortenyearsinthe enterprise jungles. I studied a lot of programming languages.October2010) .Ingeneral. but we’ll get into that a little more later. and Perl would be a great language to enhance our productivity. Object-oriented means the language supports encapsulation (data and behavior are packaged together). Most people just call him Matz. Ruby is not hugely efficient in terms of execution speed. programming was fun again.Somehow. I got interested in programming languages. I started developing such a language and named it Ruby. Bruce: WhydidyouwriteRuby? Matz: Right after I started playing with computers. The primary motivationwastoamusemyself. So for a long time.tryingto createalanguagethatfitmytaste. Ruby is an interpreted. dynamically typed language from a family of so-called scripting languages. So.

'productive' .October2010) . 'ducktyped' . try to keep an eye out for trade-offs that Matz made along the way.thoselittlefeaturesthatbreakthebasic rules of the language to give programmers a little friendlier experience andmakethecodealittleeasiertounderstand.Rubyhasamarveloussupportcommunity.especiallyintheareaofwebdevelopment. Let’sgetstarted.Theimplementations areallopensource. whether or not you already know Ruby. Rubyisfun. and that has insulated Ruby from some of the over-reaching frameworks that plague some other kingdoms. "productive" . "fun" ] >>properties. Bruce: Whatisthethingyoulikeaboutitthemost? Matz: I like the way it makes my programming enjoyable. As you read through this chapter. =>[ "objectoriented" .ifyoucouldgo backintime? Matz: I would r e m o v e the thread and add actors or some other more advancedconcurrencyfeatures. I like blocks most.each{|property|puts "Rubyis#{property}.Q UICK H ISTORY 27 theworldhavefeltsympathyforthatlanguageandthepolicybehindit. They are tamed higher-order functions but open up great possibilities in DSL and other features as well. "fun" ] Ruby is the language that taught me to smile again. "ducktyped" .FindplaceswhereMatz usedcodeblocksformarvelouseffectincollectionsandelsewhere. "ducktyped" ." } Rubyisobjectoriented.Mostcommercialsupportcomesfromsmallercompanies. Rubyisducktyped.TakeapeekatsomeRubycode: >>properties=[ 'objectoriented' . Ruby has been slow to catch on in the enterprise. "productive" . Rubyisproductive.0printing. As a particular technical issue. Anditbecameverypopular. Reporterratum thiscopyis (P1. but it’s taking hold now on the strength of itsproductivity. Dynamic to the core. Bruce: Whatisafeaturethatyouwouldliketochange.Lookforsyntacticsugar.And try to understand the trade-offs that he made along the way between simplicityandsafetyandbetweenproductivityandperformance. 'fun' ] =>[ "objectoriented" .farbeyondmyexpectation.

IamrunningRubyversion1. I didn’t declare any variables.type o ushouldseeRuby’sinteractiveconsole. UsingRubywiththeConsole irb.MaryPoppinsisfirstandforemostagreatnanny.thoughsomedevelopersareworking onvirtualmachinesthatcompileRubytobytecodeasitgetsexecuted. installationprocess. your job is to learn how to use it to do the jobs you already know how to do. don’t be shy.Googlewillshowtheway. V e r y fewinstallationproblemsareunique.0printing. and if you’re on OS X Leopard or greater.7forthischapter.world' hello. irb. Y o u know that Ruby can be interpreted.Givetheseatry: >>puts'hello. If you do.6 ornewer.9 will have some slight differences.October2010) .Ifyoudon’tseeanyerrors. even Reporterratum thiscopyis (P1.Justgoto ruby-lang. Treat this first conversation with Ruby as a dialogue.thisbriefexamplegivesyoumanyclues about the language. or is it unnecessarily awkward? What’s the core programming model? How does it treattypes?Let’sstartdiggingforsomeanswers. there’s a one-click installer that will work.2 Day1:FindingaNanny Allmagicaside.myRuby =>nil Ifyoudon’talreadyknowRuby.butinstallingRubyisasnap.org/en/downloads/. If you’re on W n id o w s .justtype ready to handle the rest of this chapter.8.andversion 1. Rubyisalmostalwaysinterpreted.I’mnotgoingtotakeyouthroughanexhaustiveoutdated http://www. LightningT o u r Aspromised.8.world =>nil >>language='Ruby' =>"Ruby" >>puts"hello.When you first learn a language.RubycomeswiththeXcodedisks.D AY 1: F INDING A N ANNY 28 2. find your platform. In fact. and install Ruby 1.Y Ifyouhaven’tdoneso.#{language}" hello.#{language}" hello.Y o u l’typeacommandandgetaresponse. Everything I did returned a value. Does the conversation flow freely.Ruby =>nil >>language='myRuby' =>"myRuby" >>puts"hello.you’re Totestyourinstallation.

and the number.“What is the programming model?” It’s not always a simple answer. There are dozens of other programming models as well.nottheclass.butyougetthepicture.Rubysubstitutedthevalue returnedbythecode language intothestring.OneofthethingsthattheRubyinterpreterevaluatesisstringsubstitution. Logic-based languages such as Prolog build around rules.asthebasisforobjectdefinitionandeven inheritance. Y o u v ’e probablybeenexposedtoprocedurallanguagessuchasC. "*". Rubyisapureobject-orientedlanguage.Infact..class =>Fixnum >>4+4 =>8 >>4. Stackbased languages such as PostScript or Forth use one or more stacks as a central feature of the language. Some of those languages such as Scala mix programming models by throwing in object-oriented concepts.0printing. Just about everything in Ruby is an object. every piece of code inRubyreturnssomething.. Reporterratum thiscopyis (P1."to_i"."%". Lua. A number is an object that has a class called method called methods returns an array of methods (Ruby represents arraysinsquarebrackets). in Java is not an object. TheProgrammingModel Oneofthefirstquestionsaboutalanguageyoushouldansweris. One quote around a string means the string should be interpreted literally."numerator"..Inthischapter.youcancallanymethodonanobject withthedotoperator.October2010) . Y o u may have picked up this book to explore functional programming languages. and two quotes leads tostringevaluation. ] 4 I’veomittedsomeofthemethodsfromthislist.Inthisexample.D AY 1: F INDING A N ANNY 29 when I didn’t ask Ruby to return anything.Let’skeepgoing.methods =>["inspect".you’llseejust howfarRubytakesthisconcept. In fact."methods". Prototype languages like Io.Let’slookatsomebasicobjects: >>4 =>4 >>4."+".Fortran."<<". Y o u also saw at least two types of strings. but manyofthoselanguageshaveproceduralelementstoo.."singleton_method_added". and Self usetheobject...Forexample. down to each individual Fixnum. Most of us are using object-oriented languages right now.or Pascal.

'ifnottrue =>nil >>puts'Thisappearstobetrue. Ruby has expressions that evaluate to true and a fs le arealsofirst-classobjects.soitstandstoreasonthatthewaya languagemakesdecisionsisacentralconceptthatshapesthewayyou code. To some. end)orone-lineforms( stateif or unless.' >>else ?> puts'Thisappearstobetrue. statements.class =>TrueClass true or a fs le . =>nil >>unlessx==4 >> puts'Thisappearstobefalse.Checkouttheseexpressions: >>x=4 =>4 >>x<5 =>true >>x<=4 =>true >>x>4 =>false >>false.class =>FalseClass >>true.' >>end Thisappearstobetrue. True to form. So. =>nil >>puts'Thisappearstobetrue.0printing.' >>end Thisappearstobetrue. =>nil >>ifx==4 >> puts'Thisappearstobetrue.'unlessx==4 =>nil >>puts'Thisappearstobetrue.'ifx==4 Thisappearstobetrue.inagivenlanguage.Y o ucanconditionallyexecute codewiththem: >>x=4 =>4 >>puts'Thisappearstobefalse.andthink. Y o u can use bothblockforms( if condition.'if!true =>nil I really like Ruby’s design choice for simple conditionals.D AY 1: F INDING A N ANNY 30 Decisions Programsexisttomakedecisions.October2010) . the ment if condition ) when you’re working with Reporterratum thiscopyis (P1.Rubyislikemostobject-oriented andprocedurallanguagesinmanyways.

D AY 1: F INDING A N ANNY 31 one-lineversionofthe if isoff-putting. Y of a burden. while and until aresimilar: >>x=x+1whilex<10 =>nil >>x =>10 >>x=x-1untilx==1 =>nil >>x =>1 >>whilex<10 >> x=x+1 >> putsx >>end 2 3 4 5 6 7 8 9 10 =>nil Noticethat = isforassignmentand == testsforequality. =>nil >>puts'Thisappearstobetrue.each objectwillhaveitsnotionofequality.InRuby.butyouwouldaddadditional noise to what should be a single.0printing.'if1 Thisappearstobetrue.nil ? Sure.October2010) . When you candistillasimpleideaintooneline.but unless expressestheideamuchbetter. I also like the idea of o u could express the same ideawith not or !.'if0 Thisappearstobetrue.calculate_taxunlessorder.itallowsyoutoexpressa singlethoughtinalineofcode: order.youmakereadingyourcodeless unless. coherent thought.youcanexpressthepreviousinablock.'if'randomstring' (irb):31:warning:stringliteralincondition Thisappearstobetrue. =>nil Reporterratum thiscopyis (P1. =>nil >>puts'Thisappearstobetrue.Tome.Numbersareequaliftheirvalues areequal. Y o ucanusevaluesotherthan true and a fs le asexpressionstoo: >>puts'Thisappearstobetrue.

'iffalse =>nil >>puts'Thisappearstobetrue. 0 is true! evaluateto true. DuckTyping Let’s get into Ruby’s typing model a little.W e r ’e talkingabouttypesafety. and (alternatively &&) is a logical and. natively ||) is a logical or.October2010) . with a or (alterfew minor exceptions.CandC++programmers.D AY 1: F INDING A N ANNY >>puts'Thisappearstobetrue.Use&or | tocomparewhile executingthewholeexpression. Logical operators work like they do in C.'ifnil =>nil 32 fs le So.Stronglytypedlan- Reporterratum thiscopyis (P1. =>nil >>puts'Thisappearstobetrue.'iftrue Thisappearstobetrue. The first thing you need to know is how much protection Ruby will give you when you make a mistakewithtypes. and Java.everythingbut nil and a takenote. the interpreter will execute codeonlyuntilthevalueofthetestisclear.Herearetheseconceptsinaction: >>trueandfalse =>false >>trueorfalse =>true >>false&&false =>false >>true&&this_will_cause_an_error NameError:undefinedlocalvariableormethod`this_will_cause_an_error' formain:Object from(irb):59 >>false&&this_will_not_cause_an_error =>false >>trueorthis_will_not_cause_an_error =>true >>true||this_will_not_cause_an_error =>true >>true|this_will_cause_an_error NameError:undefinedlocalvariableormethod`this_will_cause_an_error' formain:Object from(irb):2 from:0 >>true|false =>true There’s no magic here.0printing. C++. Y o u l’normally use the short-circuit version of thesecommands. C#. W t i h these tests.

you’ll see me changeanexistingclassatruntime. Ruby does not do type checking until you actually try to execute code.class =>Float >>4+4.Thekeyword executeit. Ruby is not strongly typed.0printing.ausercanchangeaclassbeyondall recognition and defeat type safety.Checkout thiscode: >>4+'four' TypeError:Stringcan'tbecoercedintoFixnum from(irb):51:in`+' from(irb):51 >>4. But Ruby’s type system also has several potential advantages.class =>Fixnum >>(4. but only a little. Ruby makes these type checks at run time. 3 meaning you’ll get an error when types collide. Reporterratum thiscopyis (P1.0). Ruby is strongly typed. This concept is called dynamic typing . I’m lying to you a little. not compile time.October2010) .Thischeckcanhappenwhenyoupresentthe codetoaninterpreteroracompilerorwhenyouexecuteit. Butforthemostpart.Rubybehaveslikeastronglytypedlanguagemostofthetime.D AY 1: F INDING A N ANNY 33 guages check types for certain operations and check the types before youcandoanydamage. so in the strictest sense.0 So. Y o u r classes don’t have to inherit from the same parent to be used inthesameway: >>i=0 =>0 3.Enterthiscode: >>defadd_them_up >> 4+'four' >>end =>nil >>add_them_up TypeError:Stringcan'tbecoercedintoFixnum from(irb):56:in`+' from(irb):56:in`add_them_up' from(irb):58 So.0 =>8.Theoretically. There are disadvantages: you can’t catch as many errors as you can with static typing because compilers and tools can catch more errors with a statically typed system. Two examples from here. I’mgoingtoshowyouhowtodefineafunctionalittlebeforeInormally def definesafunctionbutdoesn’t wouldtoprovethepoint.

Now.it’stimetowritealittle code. it’s a duck.Ifyou’reusingducktyping. Just about everything is an object.100. WhatW eLearnedinDay1 Sofar.though some academics would argue with that distinction. In this case.Instead.Ducktypingdoesn’tcarewhattheunderlyingtypemight be. Find: • TheRubyAPI • The free online version of Programming Ruby: The Pragmatic Programmer’sGuide [TFH08] Reporterratum thiscopyis (P1. you’ll use irb to execute a few Ruby snippets.youcan’t. If it doesn’t. you can treat it like a stack. Duck typing is extremely important when it comes to clean objectoriented design.andRubybehavesmostlylikeastronglytypedlanguage.likethemethodsandtheclass.October2010) .you’vehadyourfirstdatewithRuby. this philosophy is easy to support with very little added ceremony.the quack methodis to_i. you can find theanswersinthebackofthebook. If an object has push and pop methods.you’renotgoingtowritewholeprograms. and it’s easy to getatanyobject’sparts.0printing. An important tenet of design philosophy is to code tointerfacesratherthanimplementations.to_i >> i=i+1 >>end 100 100 34 Y o u just saw duck typing in action. The same code converts each to an a String.Nowletmeturnyoulooseforalittle self-study.100.Rubyisduck typed. If it walks like a duck and quacks like a duck.0] >>whilei<2 >> putsa[i]. including changing coreclasseslike NilClass and String.It’saninterpretedobjectoriented language. It’s a free-spirited language that will let you do just about anything.Inthissession. As always.D AY 1: F INDING A N ANNY >>a=['100'. Day1Self-Study So. The first element of the array is Float.0] =>['100'.you’vejustwadedthroughthebasics. and the second is a integervia to_i.



• Amethodthatsubstitutespartofastring • InformationaboutRuby’sregularexpressions • InformationaboutRuby’sranges Do: • Printthestring“Hello,world.” • Forthestring“Hello,Ruby,”findtheindexoftheword“Ruby.” • Printyournametentimes. • Printthestring“Thisissentencenumber1,”wherethenumber1 changesfrom1to10. • RunaRubyprogramfromafile. • Bonus problem: If you’re feeling the need for a little more, write a program that picks a random number. Let a player guess the number,tellingtheplayerwhethertheguessistoolowortoohigh.
a n d ( 1 0 ) (Hint: r will generate a random number from 0 to 9, and gets willreadastringfromthekeyboardthatyoucantranslateto aninteger.)

2.3 Day2:FloatingDownfromtheSky
At the time, one of the most striking scenes in Mary Poppins was her entrance. She floated into town on her umbrella. My kids will never understandwhythatentrancewasgroundbreakingstuff.Today, you’re going to experience a little bit of the magic that makes Ruby click. Y o u l’learntousethebasicbuildingblocksofobjects,collections,and classes. Y o u l’ also learn the basics of the code block. Open up your mindtoalittlemagic.

Unlike Java and C#. you don’t have to build a whole class to define a function.Y o ucandefineafunctionrightintheconsole:
>>deftell_the_truth >> true >>end

Every function returns something. If you do not specify an explicit return, the function will return the value of the last expression that’s processedbeforeexiting.Likeeverythingelse,thisfunctionisanobject.
Reporterratum thiscopyis (P1.0printing,October2010)



Later,we’llworkonstrategiestopassfunctionsasparameterstoother functions.

Arrays are Ruby’s workhorse ordered collection. Ruby 1.9 introduces ordered hashestoo,but in general, arrays are Ruby’s primary ordered collection.Takealook:
>>animals=['lions','tigers','bears'] =>["lions","tigers","bears"] >>putsanimals lions tigers bears =>nil >>animals[0] =>"lions" >>animals[2] =>"bears" >>animals[10] =>nil >>animals[-1] =>"bears" >>animals[-2] =>"tigers" >>animals[0..1] =>['lions','tigers'] >>(0..1).class =>Range

Y o u can see that Ruby collections will give you some freedom. If you nil. Y access any undefined array element, Ruby will simply return o u will also find some features that don’t make arrays more powerful but animals[-1] returned the first element just make them easier to use. from the end, animals[-2] returned the second, and so on. These featuresarecalled syntacticsugar ,anaddedfeatureforconvenience.The animals[0..1] expression might look like syntactic sugar, but it’s not. 0..1 isactuallya Range,meaningallnumbersfrom0to1,inclusive. Arrayscanholdothertypesaswell:
>>a[0]=0 NameError:undefinedlocalvariableormethod`a'formain:Object from(irb):23 >>a=[] =>[]

Reporterratum thiscopyis (P1.0printing,October2010)



Oops.Itriedtouseanarraybeforeitwasanarray.Thaterrorgivesyou acluetothewayRubyarraysandhasheswork. [ ] isactuallyamethod on Array:
>>[1].class =>Array >>[1].methods.include?('[]') =>true >>#use[1].methods.include?(:[])onruby1.9

So, [ ] and [ ]= arejustsyntacticsugartoallowaccesstoanarray.Todo thisright,Ineedtoputanemptyarrayintoitfirst,andthenIcanplay aroundwithitsome:
>>a[0]='zero' =>"zero" >>a[1]=1 =>1 >>a[2]=['two','things'] =>["two","things"] >>a =>["zero",1,["two","things"]]

>>a=[[1,2,3],[10,20,30],[40,50,60]] =>[[1,2,3],[10,20,30],[40,50,60]] >>a[0][0] =>1 >>a[1][2] =>30

>>a=[1] =>[1] >>a.push(1) =>[1,1] >>a=[1] =>[1] >>a.push(2) =>[1,2] >>a.pop =>2 >>a.pop =>1

Arrays have an incredibly rich API. Y o u can use an array as a queue, alinkedlist,astack,oraset.Now,let’stakealookattheothermajor collectioninRuby,thehash.

Reporterratum thiscopyis (P1.0printing,October2010)



Rememberthatcollectionsarebucketsforobjects.Inthehashbucket, everyobjecthasalabel.Thelabelisthekey,andtheobjectisthevalue. Ahashisabunchofkey-valuepairs:
>>numbers={1=>'one',2=>'two'} =>{1=>"one",2=>"two"} >>numbers[1] =>"one" >>numbers[2] =>"two" >>stuff={:array=>[1,2,3],:string=>'Hi,mom!'} =>{:array=>[1,2,3],:string=>"Hi,mom!"} >>stuff[:string] =>"Hi,mom!"

Thisisnottoocomplicated.Ahashworksalotlikeanarray,butinstead ofanintegerindex,thehashcanhaveanyarbitrarykey.Thelasthash is interesting because I’m introducing a symbol for the first time. A :symbol.Symbolsare symbolisanidentifierprecededwithacolon,like great for naming things or ideas. Although two strings with the same valuecanbedifferentphysicalstrings,identicalsymbolsarethesame physical object. Y o u can tell by getting the unique object identifier of thesymbolseveraltimes,likeso:
>>'string'.object_id =>3092010 >>'string'.object_id =>3089690 >>:string.object_id =>69618 >>:string.object_id =>69618

Hashes sometimes show up in unusual circumstances. For example, Rubydoesnotsupportnamedparameters,butyoucansimulatethem with a hash. Throw in a little syntactic sugar, and you can get some interestingbehavior:
>>deftell_the_truth(options={}) >> ifoptions[:profession]==:lawyer >> 'itcouldbebelievedthatthisisalmostcertainlynotfalse.' >> else >> true >> end >>end =>nil >>tell_the_truth =>true

Reporterratum thiscopyis (P1.0printing,October2010)

>>tell_the_truth:profession=>:lawyer =>"itcouldbebelievedthatthisisalmostcertainlynotfalse."


Thismethodtakesasingleoptionalparameter.Ifyoupassnothingin, options willbesettoanemptyhash.Ifyoupassina :profession of :lawyer, you will get something different. The result is not fully true, but it is true. Notice almostjust asgood,becausethesystemwill evaluateit as that you didn’t have to type in the braces. These braces are optional for the last parameter of a function. Since array elements, hash keys, andhashvaluescanbealmostanything,youcanbuildsomeincredibly sophisticateddatastructuresinRuby,buttherealpowercomeswhen youstarttogetintocodeblocks.

Acodeblockisafunctionwithoutaname.Y o ucanpassitasaparametertoafunctionoramethod.Forexample:
>>3.times{puts'hiyathere,kiddo'} hiyathere,kiddo hiyathere,kiddo hiyathere,kiddo

The code between braces is called a code block . times is a method on Fixnum that simply does something some number of times, where somenumber is the value of the Fixnum. Y thing is a code block and o u can specify code blocks with {/} or do/end. The typical Ruby convention is do/end to use braces when your code block is on one line and use the form when the code blocks span more than one line. Code blocks can takeoneormoreparameters:
>>animals=['lionsand','tigersand','bears','ohmy'] =>["lionsand","tigersand","bears","ohmy"] >>animals.each{|a|putsa} lionsand tigersand bears ohmy

Thiscodebeginstodisplaythepowerofthecodeblock.Thatcodetold Ruby what to do for every item in the collection. W t i h a fraction of the syntax, Ruby iterated overeach ofthe elements, printing each one.To reallygetafeelforwhat’sgoingon,here’sacustomimplementationof the times method:
>>classFixnum >> defmy_times >> i=self

Reporterratum thiscopyis (P1.0printing,October2010)

>> whilei>0 >> i=i-1 >> yield >> end >> end >>end =>nil >>3.my_times{puts'mangymoose'} mangymoose mangymoose mangymoose


Thiscodeopensupanexisting class andaddsamethod.Inthiscase, y _ m t ie s the method called m loops a set number of times, invoking the codeblockwith yield.Blockscanalsobefirst-classparameters.Check outthisexample:
>>defcall_block(&block) >> block.call >>end =>nil >>defpass_block(&block) >> call_block(&block) >>end =>nil >>pass_block{puts'Hello,block'} Hello,block

Thistechniquewillletyoupassaroundexecutablecode.Blocksaren’t justforiteration.InRuby,you’lluseblockstodelayexecution...

...somecode... in_case_of_emergencydo use_credit_card panic end defin_case_of_emergency yieldifemergency? end ...morecode...

within_a_transactiondo things_that must_happen_together end

Reporterratum thiscopyis (P1.0printing,October2010)

class. but you’ll primarily put your code into files.class =>Fixnum >>4. C#.superclass.world' Saveittoyourcurrentdirectory.Toseeitallinaction.superclass =>Numeric >>4.rb. Y o u l’ use the console to explore short bits of code.superclass.anddo complexoperationsovercollections.doworkwithinanHTTPtransaction. Y o u l’ see Ruby libraries that use blocks to processeachlineofafile. Ruby supports inheritance.butmanyarehappytouseasimpleeditorwithfiles.D AY 2: F LOATING D OWN FROM THE S KY defwithin_a_transaction begin_transaction yield end_transaction end 41 and many other places.emacs.October2010) .superclass =>Object >>4.class. so working from the interactive console isn’t all that convenient anymore. Ruby has classes and objects.superclass =>Integer >>4.fromtheconsole.Myfavorite isTextMate.calleda superclass. Y Rubycodethatyou’dlike: puts 'hello.superclass =>nil Reporterratum thiscopyis (P1.wecanmoveon tothereusablebuildingblocksofRubyprograms.andthenexecuteitfromthecommand line: batate$rubyhello.andmanyotherpopulareditorshaveRuby plug-ins.world AfewpeopleareusingRubyfromfullintegrateddevelopmentenvironments.superclass.class. RunningRubyfromaFile The code examples are getting a little more complicated. Think cookie cutter and cookie—classes are templates for objects.Rubyisablockparty.butvi. Of course.W t i hthisunderstandinginourbackpocket.class.superclass. DefiningClasses Like Java.superclass.rb hello.0printing. and C++. typethefollowing: >>4. Create a file called o u can include any hello.superclass. a Ruby class can inherit from only oneparent. Unlike C++.

class. it really gets So. Each of these classes is also an object: >>4.sogood.0printing.superclass. From there.everythinginRubyhasacommonancestor.andultimately Object.Objectsarederivedfromaclass.superclass =>Object Class. Object. In our case.superclass =>Module >>4.class =>Class >>4. whichinheritsfrom Integer.class. Numeric.1:Rubymetamodel Sofar. Check out Figure 2. Everything eventually inherits from Object.The 4’sclassis Fixnum.class.Classinheritsfrom Module.class. Instances of Class Fixnum is an instance of a serve as templates for objects.October2010) . A Class is also a Module. Whenallissaidanddone. and 4 is an instance of Fixnum.1 to see how things fit together.and Module inheritsfrom Object. Fixnum is derived from the class confusing.class.class. Reporterratum thiscopyis (P1.D AY 2: F LOATING D OWN FROM THE S KY 42 Object Module Class Numeric Integer Fixnum 4 Figure2.

Ishould pointoutafewconventions andrules for Ruby. methodsthattesttypicallyuseaquestionmark( The attr keyword defines an instance variable.October2010) . Several versions exist.new("MacRuby" )]) puts "Visitinganode" ruby_tree.node_name} puts puts "visitingentiretree" ruby_tree. and two instance variables.0printing. [Tree. visit.children=[]) @children=children @node_name=name end defvisit_all(&block) visit&block children. andmethodnamesbeginwithlowercaselettersinthe Constants are in ALL_CAPS.Instancevariables underscore_style. Each tree has two instance variables: @children and @node_name. This code defines a tree class.callself end end ruby_tree=Tree.new("Reia" ).new( "Ruby" .visit_all&block} end defvisit(&block) block. It has three children methods.:node_name definitialize(name.visit{|node|putsnode.visit_all{|node|putsnode.Rubywillcallitwhenthe classinstantiatesanewobject.D AY 2: F LOATING D OWN FROM THE S KY 43 Download ruby/tree. Themostcommonare attr (defininganinstancevariableandamethod Reporterratum thiscopyis (P1. initialize hasspecialmeaning. Functions and iftest? ). and node_name.rb classTree attr_accessor:children.Classesstart CamelCase to denote capitalizawith capital letters and typically use tion. Tree.each{|c|c. and visit_all. initialize.node_name} This power-packed class implements a very simple tree. Y o u must prepend instance variables (one value per object) with @ andclassvariables(onevalueperclass)with @@.

Java uses interfaces module is a collection of to solve this problem. WritingaMixin Object-oriented languages use inheritance to propagate behavior to similar objects. Experience has shown that multiple inheritance is complicated and problematic. thosebehaviorsandconstantsbecomepartoftheclass. A functionsandconstants.October2010) .object_id}. defining an instance Our dense program packs a punch. It uses blocks and recursion to T r e e has allow any user to visit all nodes in a tree. The visit_all method calls visit for the node and then recursively calls visit_all foreachofthechildren.anaccessor.Let’sgobackandtakeacloserlook.Runningitproducesthisoutput: Visitinganode Ruby visitingentiretree Ruby Reia MacRuby Classes are only part of the equation. Ruby uses modules.whichaddsa Download ruby/to_file.Itdefinesatree.andasetter.and thenvisitsallnodes. The visit method calls the inbound code block.rb to_f methodtoanarbitraryclass: moduleToFile deffilename "object_#{self. TheremainingcodeusestheAPI.txt" end defto_f File.write(to_s)} end end Reporterratum thiscopyis (P1.open(filename.The children and node_name.D AY 2: F LOATING D OWN FROM THE S KY 44 of the same name to access it) and variable.visitsonenode. Y o u v ’e briefly seen modules in thecodeonpage42. either you can allow inheritance from more than one class (multiple inheritance) or you can look to another solution. Takethisclass.0printing. attr_accessor. When the behaviors are not similar. 'w' ){|f|f. Each instance of initialize methodprovidesthestartingvaluesfor onenodeofatree.Whenyouincludeamoduleaspartofaclass.

W t i h Ruby.Theabilitytowritetoafile P e r s o n .October2010) .0printing.andthat’sthepoint. The to_f method writes the output of the to_s method to a file with a filename supplied by the filename method.The e r s o n P e r s o n includesthemodule.andwe’redone. this contract is implicit.Enumerable. and each subclass will can add new mixins and subclasses to have the capabilities of all the mixins without having to know about the mixin’s implementation.iscalleda mixin.W hasnothingtodowithwhetheraclassisactuallya e addthe capability to add the contents to a file by mixing in the capability. A class wanting to be enumerable must implement each. this contract is explicit: the class will implement a formal interface. Modules.Themoduleinteractswiththeincluding classatanintimatelevel. introduced in Flavors and used in many languages from Smalltalk to Python.andSets A couple of the most critical mixins in Ruby are the enumerable and comparable mixins. W e P e r s o n .to_f 45 Start with the module definition.new('matz' ).butthepremiseisclear. What’s interesting here is that to_s is used in the module but implemented in the class! The class hasnotevenbeendefinedyet.D AY 2: F LOATING D OWN FROM THE S KY classPerson includeToFile attr_accessor:name definitialize(name) @name=name end defto_s name end end Person.Thisstyleofprogramming. When all is said and done. W t i h Java. <=> is a simple comparison that returns -1 if Reporterratum thiscopyis (P1.andaclasswantingtobe comparable mustimplement <=>. through duck typing. This module has two methods. you can use a simplified single inheritance to define the essence of a class and then attachadditionalcapabilitieswithmodules.Called the spaceship operator.Themodulewilloftendependonseveralclass methods.Thevehiclethatcarriesthemixinisnotalways calledamodule. Thedetailsof P arenotatallinteresting.Singleinheritanceplusmixins allowforanicepackagingofbehavior.

4.3.inject(0){|sum.5] >>a.4. Since the spaceFixnum. enumerable and comparable providemanyconveniencemethodsforcollections.4. select and find_all return oneelementmatchingthecondition.1] >>a. 1 if a is greater.member?(2) =>false any? returns true if the condition is true for any of the elements.inject{|sum.8.all?{|i|i>0} =>true >>a.Crackopentheconsole: >> 'begin'<=>'end' =>-1 >>'same'<=>'same' =>0 >>a=[5.1] >>a.6.collect{|i|i * 2} =>[10.any?{|i|i>4} =>true >>a.i|sum+i} =>13 >>a.inject{|product.all?{|i|i>4} =>false >>a.1] =>[5.sort =>[1.youcan sort and shipisimplementedontheseintegersthrough a x .max =>5 >>a.any?{|i|i>6} =>false >>a.4.1] >>a.select{|i|i%2==1}#odd =>[5. computethe min or m collect and m a p applyafunction Y o ucanalsodoset-basedoperations.3.i|sum+i} =>13 >>a.i|product =>60 * i} Reporterratum thiscopyis (P1.3.October2010) . In exchange for imple- 46 mentingthesemethods. find finds to each of the elements and return an array of the results. all? returns true if the condition is true for all elements.0printing.select{|i|i%2==0}#even =>[4] >>a.D AY 2: F LOATING D OWN FROM THE S KY b is greater.andboth allelementsmatchingacondition.3.3.Y o ucanalsocomputethetotalofa inject: listortheproductwith >>a =>[5.2] >>a. and 0 otherwise.

Thislevelofabstractiongivesyou a marginally better programming language. The enumerable module gives you a flavor of just howwell-designedRubycanbe. but it’s not too complicated.Thesingle-inheritanceobject-oriented structure certainly isn’t novel.October2010) . Find: • Find out how to access files with and without code blocks. It takes a code block 47 withtwoargumentsandanexpression.inject(0)do|sum. WhatW eLearnedinDay2 ThisisyourfirstchancetoseesomeofRuby’ssugarandalsoalittleof the magic.with block as the second argument. you can compute the word count passed to the next line. The collectionsaredeadsimple:twocollectionswithmultipleAPIslayeredontop.0printing. Day2Self-Study These problems will be a little more demanding.youjustpasstheinitialvalue inject will use as the argument to inject. Y o u r ’e starting to see how flexible Ruby can be. but serious mojo is on theway. What isthebenefitofthecodeblock? Reporterratum thiscopyis (P1. the result of the previous line is always the first value inject. Using of many sentences.withalittlehelp: >>a.)Takeasecondlook.D AY 2: F LOATING D OWN FROM THE S KY inject seems tricky. but the implementation is packed with intuitivedesignandusefulfeatures.i| ?> puts"sum:#{sum} i:#{i} ?> sum+i ?>end sum:0 i:5 sum+i:5 sum:5 i:3 sum+i:8 sum:8 i:4 sum+i:12 sum:12 i:1 sum+i:13 sum+i:#{sum+i}" As expected. (If you don’t specify a value.Thecodeblockwillbeexecuted inject passingeachlistelementtothecode foreachiteminthelist. find the largest word in a paragraph of lines. thefirstvalueinthecollection. Y o u v ’e used Ruby a littlelonger. The first argument is the result of the previousexecutionofthecodeblock.Theseexampleswillforceyoutodoa littlemoreanalyticalthinking.Sincetheresultwon’thaveavalue thefirsttimethecodeblockisexecuted. and domuchmore. Application performance is secondary. Ruby is about the performance of the programmer.sotheglovesareoff.

Let the initializer accept a nested structure with hashes and arrays. What other common data structuresdoarrayssupport? Do: • Print the contents of an array of sixteen numbers. but it did not allow you to specify • The T a new tree with a clean user interface.’uncle’=>{’child3’=>{}. Y o u could back off a little and play it safe. In thisbook.4 Day3:SeriousChange ThewholepointofMaryPoppinsisthatshemadethehouseholdbetter as a whole by making it fun and changing the hearts of the people in it with passion and imagination. •W r t i e a simple grep that will print the lines of a file having any occurrencesofaphraseanywhereinthatline.InRuby. do the same with each_slice in at a time. ’child specify a tree like this: 2’=>{}}. r e e class was interesting. Metaprogramming means writing programs that write programs. using just Enumerable.October2010) .includelinenumbers.thatmeansmetaprogramming.(This issurprisinglysimpleinRuby. four numbers each.’child4’=>{}}}}.eachchapterwillshowyousomenontrivialproblemthatthe languagesolveswell. An ActiveRecord class for a looklikethis: classDepartment<ActiveRecord::Base has_many:employees has_one:manager end Reporterratum thiscopyis (P1.Y o uwillneedtodo asimpleregularexpressionmatchandreadlinesfromafile. But when you change the way a language looks and works. using Ruby to do the same things you already know how to do in other languages.0printing.)Ifyouwant.D AY 3: S ERIOUS C HANGE 48 • How would you translate a hash to an array? Can you translate arraystohashes? • Canyouiteratethroughahash? •Y o u can use Ruby arrays as stacks. Y o u should be able to {’grandpa’ => { ’ dad’ => {’child 1’ => {}. The ActiveRecord framework that’s the centerpiece of Rails uses metaprogramming to implement a friendly language for building classes that Department might link to database tables. Now. you can capture magic that makes programming fun. 2.

and Ruby will gladly give it to you.D AY 3: S ERIOUS C HANGE has_many and has_one areRubymethodsthataddalltheinstancevari- 49 ables and methods needed to establish a has_many relationship.rb classNilClass defblank? true end end classString defblank? self. because blank? will return true.usuallytoaddbehavior.beempty.andbepossibly idiom lets me quickly check for the two empty cases at once.Ioftenwanttoseewhetheritisblank. It’s possible to completely disable Ruby by redefining. If it walks like a duck and quacks like a duck. I don’t need to draw blood to check thetype.blank? end The first invocation of class defines a class. Let’s look atsomedifferenttoolsyoucanuseformetaprogramming. W a t c hwhat’sgoingonhere. nil. Class. When I checkthestatusofagivenstring. The trade-off is freedom.eliminatingallthenoiseandbaggage that you usually find with other database frameworks. It doesn’t matter which class String points to. Reporterratum thiscopyis (P1. subsequent invocations modify that class.Y o u r ’easkingforaverysharpscalpel. OpenClasses Y o u v ’ealreadyhadabriefintroductiontoopenclasses. you can build some amazinglyreadablecode. it will work.eachdo|element| putselementunlesselement.Here’sa NilClass: greatexamplefromtheRailsframeworkthataddsamethodto Download ruby/blank. This classspecificationreadslikeEnglish. Y o u r open classes have redefined both String and Nil. once a class is already defined.new. W t i h the kind of freedom that lets you redefine any class or object at any time.0printing. say.October2010) .W t i hfreedomandpowercomeresponsibility.Y o ucanchange thedefinitionofanyclassatanytime. This code adds a method called blank? to two existing classes: NilClass and String. it is a duck. "person" .nil].Thislittle Moststringscanhaveavalue.size==0 end end ["" . If it supports the blank? method.

But sometimes.D AY 3: S ERIOUS C HANGE 50 Openclassesareusefulwhenyou’rebuildinglanguagestoencodeyour owndomain. you can take advantage of this language feature to build some unexpectedly rich behavior.forward Theopenclassesmakethiskindofsupportpossiblewithminimalsyntax.miles.0printing. V a i method_missing Ruby calls a special debugging method each time a method is missinginordertoprintsomediagnosticinformation.consideranAPIthatexpresses alldistanceasinches: Download ruby/units.back puts2.that’snottoo Reporterratum thiscopyis (P1.Intruth.rb classNumeric definches self end deffeet self * 12.feet end defback self * -1 end defforward self end end puts10. Y o u could do it easily enough with a method call.inches end defyards self * 3.number_for"ii" .October2010) .It’softenusefultoexpressunitsinalanguagethatworks foryourbusinessdomain.ButothertechniquescanstretchRubyevenfurther.feet end defmiles self * 5280.feet.ConsideranAPItorepresent youneedtodoisoverride Roman numerals. All method_missing.Thisbehaviormakes the language easier to debug. withanAPIsomethinglike Roman.Forexample.

it’sanotherscalpelforthetoolbag.Thecodeis Thiscodeisabeautifulexampleof clearandsimple.October2010) . Then.XC putsRoman. Y o u can literally implement def or attr_accessor with a few lines of code in a module. Modules The most popular metaprogramming style in Ruby is the module. Roman. TheAPIissomucheasier: Consider the cost. "IIII" ) roman.W t i hRuby.number_for"i" . we just count Roman digits and multiply by the value of that number.0printing.gsub!("IX" .rb classRoman defself .withstringsthatareeasiertocount.D AY 3: S ERIOUS C HANGE 51 bad. There are no mandatory parentheses or semicolons to get in the way.Then.count("X" ) * roman.count("L" ) * roman.Use itwisely. First.gsub!("XC" .XII putsRoman. we replace the only in the name. "LXXXX" ) (roman. W e r ’e interested String.X 5+ 10+ 50+ 100) method_missing inaction.X putsRoman.i versus Roman.W e firstoverride method_missing.gsub!("IV" .wecandobetter: Download ruby/roman. we convert that to specialcases.like iv and ix. A commontechniqueletsyoudesignyourowndomain-specificlanguage Reporterratum thiscopyis (P1. "VIIII" ) roman. though.to_s roman.gsub!("XL" .count("I" )+ roman.Ifyoudon’tknowwhatyou’re lookingfor.youcouldhaveatoughtimefindingthatimplementationof that ii methodon Roman.Still. Y o u can also extend class definitions in surprising ways.W e l’ getthenameof the method and its parameters as input parameters. *args roman=name.method_missingname.count("V" ) * roman. "XXXX" ) roman. W e do have a class that will be much more difficulttodebug.becauseRubycannolongertellyouwhenamethod ismissing!W ewoulddefinitelywantstrongerrorcheckingtomakesure itwasacceptingvalidRomannumerals.count("C" ) * end end putsRoman.

I’m going to break an example down using a common superclass first.headers. it loops over lines.csv_contents. reads headings.new(self .The read method opens a file.D AY 3: S ERIOUS C HANGE 52 (DSL)todefineyourclass.Mostoftheworkhappensin read.split( '.downcase+ @headers=file.' ) file.gets. the ActiveRecord persistence framework uses domain-specific languagestomapaclasstoadatabasetable.0printing.It’sasimpleprogramtoopenaCSVfilebasedonthenameofthe class. DSLs let you tailor a language for a specific domain.eachdo|row| @result<<row. and chops them into individual fields.inspect '. izestheresultsoftheread. Download ruby/acts_as_csv_class. Next. 4 TheDSLdefinesmethodsinamodulethat addsallthemethodsandconstantsneededtomanageaclass.chomp. Reporterratum thiscopyis (P1. For perhaps the best-known example in Ruby.rb classActsAsCsv defread file=File. placing the contents of each line in an 4.txt' ) '.to_s. Here’s the type of class that we want to build through metaprogramming. initialize initialpleaccessorsthatreturnthevalueofinstancevariables.class.' ) headers and csv_contents aresimThisbasicclassdefinesfourmethods.October2010) .chomp.new putsm.split( end end defheaders @headers end defcsv_contents @result end definitialize @result=[] read end end classRubyCsv<ActsAsCsv end m=RubyCsv.inspect putsm.

inspect putsm.chomp.new(self .split( end end define_method "headers" do @headers end define_method "csv_contents" do @result end define_method 'initialize' do @result=[] read end end end classRubyCsv<ActsAsCsv acts_as_csv end m=RubyCsv.rb classActsAsCsv defself . Thenextstepistotakethefileandattachthatbehaviortoaclasswith a module method often called a macro.acts_as_csv define_method 'read' do file=File.butyougettheidea.headers.txt' ) '. That code The metaprogramming happens in the calls define_method for all the methods we want to add to the target class. Macros change the behavior of classes.inspect '.0printing.Now. often based on changes in the environment. our macro opens up the class and dumps in all the behavior related to a CSVfile: Download ruby/acts_as_csv.' ) acts_as_csv macro.to_s. Reporterratum thiscopyis (P1.ThisimplementationofaCSVfileisnotcompletebecauseitdoes nothandleedgecaseslikequotes.gets.split( '.eachdo|row| @result<<row.October2010) .class.D AY 3: S ERIOUS C HANGE 53 array.downcase+ @headers=file.whenthetargetclasscalls acts_as_csv.chomp.' ) file.new putsm.csv_contents. In this case.thatcodewilldefine allfourmethodsonthetargetclass.

but it’s about to get more interesting.eachdo|row| @csv_contents<<row.rb moduleActsAsCsv defself .0printing.new putsm.extendClassMethods end moduleClassMethods defacts_as_csv includeInstanceMethods end end moduleInstanceMethods defread @csv_contents=[] filename=self .csv_contents.included(base) base.split( '.chomp.headers.downcase+ '.gets. the acts_as macro code does nothing but add a few methods we could have easily added through inheritance.inspect putsm.txt' file=File.new(filename) @headers=file.Let’sseehowthesamebehaviorwouldworkinamodule: Download ruby/acts_as_csv_module.split( end end attr_accessor:headers. That design does not seem like much of an improvement.chomp.' ) file.inspect '.' ) Reporterratum thiscopyis (P1.D AY 3: S ERIOUS C HANGE 54 So.to_s.October2010) .class.:csv_contents definitialize read end end end classRubyCsv #noinheritance!Youcanmixitin includeActsAsCsv acts_as_csv end m=RubyCsv.

dramatically reducing the amount of clutter for a common scenario. WhatW eLearnedinDay3 Inthissection.0printing.Sometimes. The interesting thing about all these metaprogramming techniques is thatyourprogramscanchangebasedonthestateofyourapplication. In our included base (which is the RubyCsv method. ActiveRecordusesmetaprogrammingtodynamicallyaddaccessorsthat arethesamenameasthecolumnsofthedatabase. Day3Self-Study Do: each method to return a Modify the CSV application to support an CsvRow object. we extend the target class called RubyCsv. When your syntax is more beautiful. And we’re writing a program that writesaprogram. SomeofthebestRubyframeworks. These programming techniques fall in the category of metaprogramming.suchasBuilderandActiveRecord.October2010) . Reporterratum thiscopyis (P1. Remember.Theonlyclass class).youcanclosethegapbetweenvalidRubysyntaxandsentences. W t i h metaprogramming.D AY 3: S ERIOUS C HANGE 55 Ruby will invoke the included method whenever this module gets included into another. heavily depend on metaprogramming techniques for readability. Y o u blank? usedopenclassestobuildaduck-typedinterfacesupportingthe method for String objects and nil.That’sthepowerofRuby. And finally. a class is a module.SomeXMLframemethod_missing to works like builder let users define custom tags with provide a beautiful syntax. you used modules to define a domain-specific languagethatyouusedtospecifyCSVfiles. Every line of code that you write has twokindsofaudiences:computersandpeople.andthatmoduleaddsclassmethodsto method is acts_as_csv. you can let the reader of your code get past the syntax and closer to the intentions. Use method_missing on that CsvRow to return the value forthecolumnforagivenheading. That method in turn opens up the class and includes all the instance methods.Y o uused method_missing tobuildbeautifulRoman numerals. Y o u saw some code that used many of thesametechniques.it’shardto strikeabalancebetweenbuildingcodethatcanpassthroughtheinterpreter orcompiler and is also easy to understand.youlearnedtouseRubytodefineyourownsyntaxand change classes on the fly.

W r t i n ggluecodetomungetwo applications together. The language is intensely productive. Reporterratum thiscopyis (P1.one} Thisshouldprint "lions". writing a spider to scrape web pages for a stock quoteorbookprice. The language has a wide varietyoflibrariesincludedwiththebase. and others.aswellasthousandsofgems.orrunninglocalbuildenvironmentsorautomated testsareexcellentusesforRuby.Ruby is a good choice for scripting environments. C#.two lions. Some of the features that enable that productivity make Rubyhardtocompileandmaketheperformancesuffer.0printing.W RAPPING U P R UBY 56 Forexample. I hope you can see the comparison to Mary Poppins. Rubyisidealasascriptinglanguage. processingXML.tigers allowanAPIthatworkslikethis: csv=RubyCsv.new csv.October2010) . Asalanguagewithapresenceonmostmajoroperatingsystems.Theducktypingallowstruerpolymorphicdesigns based on what an object can support rather than that object’s inheritance hierarchy.orasawebdevelopmentlanguage if the scaling requirements are reasonable. I have heard scores of people profess their love for Ruby because it is fun. that can be used for loading CSV files. Scripting Rubyisafantasticscriptinglanguage.forthefile: one.5 WrappingUpRuby W e have covered a lot of ground in this chapter. Ruby is a breath of freshair.orworkingwithlow-levelInternetAPIs. CoreStrengths Ruby’spureobjectorientationallowsyoutotreatobjectsinauniform andconsistentway. Java. And Ruby’s modules and open classes let a programmer attach behavior to syntax that goes beyond the typical method or instancevariabledefinitionsinaclass. After speaking at dozens of Ruby conferences.each{|row|putsrow. or prepackaged plug-ins. 2. To an industry that grew up embracing the C family of languages including C++.

Many large. including mine.Ruby Reporterratum thiscopyis (P1.buttoomanypeoplefocusonenoughscalabilitytobuild thenexteBaywhentheycan’tdeliveranysoftwareontime. The combination of the beautiful syntax and the communityofprogrammers.Eventoday.W RAPPING U P R UBY 57 W e bDevelopment Rails is already one of the most successful web development frameworks of all time. TimetoMarket IwouldconsidertheproductivityofRubyandRailstobeanimportant componentinitssuccess.Andtheframeworkhasplug-insthathandlesomedifficultproductionissues: • The structure of Rails applications is always consistent and well understood.andplug-insisextremelypowerful. and the extraordinary productivity of the language allowed the website to grow to huge proportions.First. but Ruby can do all of these things. • Several well-documented conventions reduce the total amount of configurationcode. commercial websites use Ruby and Ruby on Rails. and internationalization.Often.thescalabilityofRubyislimitedin someways.tools. the role of Ruby is often seen as a little more limited.Second. the core of Twitter was rewritten in Scala. Eventually. Y o u can find Ruby gems to find the ZIP code of a surfer and another to calculate all address codes in a fifty-mile radius.Rubyisagreatlanguageforgettingaviable producttomarketquickly. concerns about the right application frameworks and scalability are well-founded. There aretwolessonshere. fail-safe messaging.youcouldnotthrowarock in San Francisco without hitting someone who worked at a start-up poweredbyRails. and communicate acrossmanyprogramminglanguages. • Migrationshandlechangesinthedatabaseschema. • Manydifferentplug-insareavailable.October2010) . Sometimes. work with web services. The design is based on well-understood model-viewcontroller paradigms.Rubyisprolificinthesekindsofcompanies. Y o u can process images and credit cards.0printing. In formal big enterprises with distributed transactions. The many namingconventions for database and application elements allow a typical application to be built with few linesofconfigurationatall. The original Twitter implementation was in Ruby.Inthemid-2000s.

ThisapproachworkswellforRuby. W e a k n e s s e s Nolanguageisperfectforallapplications. He works to optimize the programmer’s experience. Still.Sure. But ducktypingcomesataprice. and theverytoolsthatenablecompilationandtheassociatedperformance gains. This programming strategy leads to serious problems with concurrency. you can generally have cleaner abstractions with concise. duck typing. ConcurrencyandOOP Object-orientedprogramminghasacriticallimitation. P e r o fr m a n c e Ruby’sprimaryweaknessisperformance.too. W t i h this typing strategy. I’ve lamentedthelossofanIDE-styledebugger.0printing. IDEs for Ruby are more difficult to build. and so far.Rubyisgettingfaster.Rubyhasitsshareoflimitationstoo.AnewRubyvirtualmachinewrittenbyEvanPhoenixcalledRubiniushasthepotential to compile Ruby using a just-in-time compiler. significant resource contentions are built into the language. object-oriented systems are next to impossible to debug and cannot be reliably tested for concurrent environments.Thewholepremiseofthemodeldependsonwrappingbehavioraroundstate. This approach looks at an interpreter’s usage patterns for a block of code to anticipate which codeislikelytobeneededagain. As of this writing.October2010) .Statictypingallowsawholerangeof toolsthatmakeiteasiertodosyntaxtreesandthusprovideintegrated development environments.thedefinitionofaclasscanchangeatanytime. TypeSafety I’m a firm believer in duck typing. At best. not the performance of the language.Remember.andusually the state can be changed.Let’swalkthroughsomeofthemajorones. Many of the language’s method_missing defeat features such as open classes. readable code.W RAPPING U P R UBY 58 wouldbemorethanadequateconsideringthetime-to-marketpressures manyenterprisesface.9isuptotentimesfasterforsomeusecases. Matz is very clear. the Rails team is only now startingtoaddresstheproblemofmanagingconcurrencyeffectively. most Ruby developers do not use them. V e r s o in 1.a languagewheresyntaxcluesareusuallynotenoughtoallowcompilation.IknowI’mnotalone. Reporterratum thiscopyis (P1. At worst. Many times.

Ruby can excel. And keep your eyes open for a little magic alongtheway. use it to solve the right set of problems. and you’re not likely to be disappointed.Rubyisanexcellentlanguageforobjectoriented development.W RAPPING U P R UBY 59 FinalThoughts So.October2010) . Reporterratum thiscopyis (P1.Thecoreweaknessesarearoundperformance.0printing.Allinall.thoughtheperformanceisreasonable formanypurposes. As with any tool. For the right applications.Ruby’scorestrengthsareitssyntaxandflexibility.

most of Io’s community is focused on Io as an embeddable language with a tiny virtual machine and rich concurrency. Directed by John Hughes.youwillnotbebored. 1.wickedsmart.and easy to understand but hard to predict. Iostartedasahobbyistlanguageandremainsprettysmalltoday. you’ll have to let Io show you around the town.1999. wreck your dad’scar. CA: Paramount. Hollywood.Asthequoteabove says. 1986. He might give you the ride of your life.Try tofocusonthesimplicityofthesyntax and the prototype programming model. as well as a strongconcurrencymodel.Eitherway. W r t ie nasanexercisetohelpSteveunderstandhowinterpreterswork.1 IntroducingIo SteveDekorteinventedtheIolanguagein2002. There are no surprises. Ferris Bueller’s Day Off .Ioisaprototypelanguagelike LuaorJavaScript.Thequestionisn’t. like a good party. He’ll try anything once.orboth. The complexity and the richness comes from thelibrarydesign. 1 If you 3. I found that after Io.Ioisarulebender.It’salwayswrittenwith anuppercase I followedbyalowercase o.“Whataren’twegoingtodo?” FerrisBueller Chapter 3 Io MeetIo. DVD. The core strengths are richly customizable syntax and function.He’syoung.Y o u canlearnthesyntaxinaboutfifteenminutesandthebasicmechanics of the language in thirty.LikeRuby.youwon’thavemanyrulestoholdyouback. I had a muchstrongerunderstandingofhowJavaScriptworked. Today. .“Whatarewegoingtodo?”Thequestion is. But the libraries will take you a little longer. Think Ferris Bueller.meaningeveryobjectisacloneofanother.

It’s simultaneously reckless (ever try Googling for o u Io ?)2 and brilliant. Y get only two letters. Reporterratum thiscopyis (P1.Theseclonesarecalled prototypes. In Io. Io syntax simply chains messages together.andenterthetraditional“Hello. The language’s syntax is simple and low-level.Let’scutschoolandskipstraighttothegoodstuff.0printing. with each message returning an object and each message taking optional parameters in parentheses.andthemessagesemanticsareelegantandpowerful. BreakingtheIce Let’s crack open the interpreter and start the party.butthesimplicityofthesyntaxmeansithasafighting chance.HangingOut MeetingIoislikemeetinganylanguage.October2010) .W o r d l” program: Io>"Hiho. It’s too early to tell whether Io will have lastingimpact. both vowels.Io==>Hiho. Y In Ruby. and Io is the first and only prototype-based language we’ll look at.D AY 1: S KIPPING S CHOOL .2 Day1:SkippingSchool.Reflection iseverywhere. you won’t worry about both classes and objects.Theconcurrencylibrariesthatyou’llseeinday3arewellconceived. new on some class.Io"print Hiho. Download it and install it.Io" .Therearenokeywordsandonlyahandfulof charactersthatbehavelikekeywords.Iomakesnodistinction createdanewkindofobjectbydefininga 2. every object is a clone of an existing objectratherthanaclass. everything is a message that returnsanotherreceiver. you created a new object by calling o u class. Y o u can find it at http://iolanguage. but you can tell a lot from Io. Names are sometimes deceiving. Y o u won’t find much syntactic sugar at all. Open the interpreter bytyping io. Y o u l’ deal exclusivelyinobjects.Iogetsyouaboutasclosetoobject-oriented Lisp as you’re likely to get.cloningthemasneeded. It will be much easier if we can interact outside of stifled conversations in the hallway before history class.Receiversgoontheleft. In a prototype language. like the name.com. Try Googlingfor Iolanguage instead.Io print mesY o ucantellexactlywhat’sgoingonhere. Y o u l’ just send messagestoobjects.Y o u r ’esendingthe sagetothestring "Hiho.Y o u l’havetoputinalittlekeyboard time to get properly acquainted. H ANGING O UT 61 3. W t i h Io.andmessagesgoon the right.

Mustdefineslotusing:=operatorbeforeupdating. H ANGING O UT 62 betweenthesetwothings. which ree hicle. --------message'updateSlot'in'CommandLine'online1 Y o u can get the value from a slot by sending the slot’s name to the object: Io>Vehicledescription ==>Somethingtotakeyoufaraway Infact.D AY 1: S KIPPING S CHOOL . Io>Vehicledescription="Somethingtotakeyoufaraway" ==>Somethingtotakeyoufaraway Io>VehiclenonexistingSlot="Thiswon'twork.0printing.Y o u l’createnewobjectsbycloningexisting ones.Let’sinteractwithit: Io>Vehicledescription:="Somethingtotakeyouplaces" ==>Somethingtotakeyouplaces Objectshaveslots.based onthe Object prototype.Y o u l’refer := toassignsomethingtoaslot."description") canlookat e hicle and got a list of slot names W e sent the slotNames method to V description slot. W e send the clone message.Thinkofthecollectionofslotsasahash. V e hicle isnot turnsanewobject.anobjectislittlemorethanacollectionofslots.W e assignthatobjectto V aclass.Here.Theexistingobjectisaprototype: batate$io Io20090105 Io>Vehicle:=Objectclone ==> Vehicle_0x1003b61f8: type ="Vehicle" Object is the root-level object.It is anobject.Y o ucanuse = forassignment. W e just created a slot called description.It’snotatemplateusedtocreateobjects.Everyobjectsupports type: Io>Vehicletype ==>Vehicle Io>Objecttype ==>Object Reporterratum thiscopyis (P1. theslotdoesn’texist. Y o u v ’e seen the havea type slot.Iowillcreateit.Y o ucanalsouse If the slot doesn’t exist.W e V e hicle likethis: thenamesofalltheslotson Io>VehicleslotNames ==>list("type". but we also back. Io throws an exception. There are two slots.October2010) .If toeachslotwithakey." Exception:SlotnonexistingSlotnotfound.

0printing. • Objectsarecollectionsofslots.. only Objects. In an object-oriented language.Let’smoveontoinheritance. H ANGING O UT 63 Object Vehicle description Car Instance ferrari description: Something.notaclass. For now.W e r ’e scratchingthesurface. we’re going to deal with inheritance. Reporterratum thiscopyis (P1. •Y o ugetaslot’svaluebysendingthemessage.Here’swhatweknowsofar: •Y o umakeobjectsbycloningotherobjects.October2010) .Butsitback. think of how you would model a object that is an instance of a car.andInheritance In this section. you’d do something likeFigure3. know that sentsthekindofobjectyou’redealingwith.1:Anobject-orienteddesign type repreW e l’ get to types in a few paragraphs.D AY 1: S KIPPING S CHOOL .1. Given a car that’s f e r a r i also a vehicle.Keepinmindthatatypeis anobject. Y o ucanalreadyseethatIoissimpleandfun.Prototypes.. Figure3.

H ANGING O UT 64 Let’s see how you’d solve the same problem in a prototype language. W e r ’e goingtoneedafewextraobjects.Iocalls the parent. you’ll get the type of yourprototype: Io>ferraritype ==>Car ThisishowIo’sobjectmodelworks. Let’s create another car.Objectsarejustcontainersofslots.Let’screateanother: Io>Car:=Vehicleclone ==> Car_0x100473938: type ="Car" Io>CarslotNames ==>list("type") Io>Cartype ==>Car Car by sending the In Io-speak. Y o u don’t have interfaces or modules.0printing. Types in Io are just conveniences. but this time. when you invoke the type slot.typesinIobeginwithuppercase letters. There are no classes or metaclasses. we created a new object called e hicle prototype.TypesarejusttoolsthathelpIoprogrammersbetterorganize code.Iftheslotisn’tthere.onthenextpage. Getaslotbysendingitsnametoanobject.Anyclonesof thattypestartingwithlowercaseletterswillsimplyinvoketheirparents’ type slot.October2010) .likeyouseeinFigure3. Reporterratum thiscopyis (P1.soIosetsthe type slot. Y o u just have objects. Io just forwards the V e hicle. Now. an object that begins withanuppercasenameisatype. we’ll assign it e r a r i to f : Io>ferrari:=Carclone ==> Car_0x1004f43d0: Io>ferrarislotNames ==>list() A-ha!There’sno type slot.D AY 1: S KIPPING S CHOOL . That’s all you have to understand.Byconvention. Idiomatically. It’s dead simple but sage totheprototypeand findstheslot in plenty powerful.Let’ssend description to Car: messagetothe V Io>Cardescription ==>Somethingtotakeyoufaraway clone description mesThere’s no description slot on Car.2.

H ANGING O UT 65 Object Vehicle Prototype: Object Description: Something to take you far away Car Prototype: Vehicle ferrari Prototype: Car Figure3.October2010) .D AY 1: S KIPPING S CHOOL .0printing.2:InheritanceinIo Reporterratum thiscopyis (P1.

Not so in Io.youcancreateamethodeasily. P e r s o nclone e r s o n . H ANGING O UT e r a r i Ifyouwanted f tobeatype.wecanassignittoaslot: Io>Cardrive:=method("Vroom"println) ==>method( "Vroom"println ) Reporterratum thiscopyis (P1. createsaclonecalled bruce fromtheprototypecalled P e r s o n e r s o n Both bruce and P areobjects. In other cases. they behave the same way.justlikeanyothertypeofobject.you'vecomeforanargument. P isatypebecauseithasatype P e r s o n slot.October2010) . n e w e r s o n createsanew person objectfromthe P class.you'vecomeforanargument. Methods InIo. classes are templates used to create objects.Y o ucangetits type: Io>method()type ==>Block Sinceamethodisanobject."println) ==>method( "So.likethis: Io>method("So. is identical to bruce. a class and an object. In most other respects. Let’s move on tobehavior. =P e r s o n .Theyare bruce := different entities entirely.W e r ’e usingasimple coding convention rather than a full language feature to distinguish between types and instances."println ) Amethodisanobject. bruce In Ruby and Java.youwouldhaveitbeginwithanuppercaseletter.D AY 1: S KIPPING S CHOOL .likethis: Io>Ferrari:=Carclone ==>Ferrari_0x9d085c8: type="Ferrari" Io>Ferraritype ==>Ferrari Io>FerrarislotNames ==>list("type") Io>ferrarislotNames ==>list() Io> 66 e r a r i F e r a r i Noticethat f hasnotypeslot.but does.0printing.

whetherthey arevariablesormethods... Let’sdigalittledeeper. H ANGING O UT 67 Ifaslothasamethod. Y o u know the basic syntax.. Y o u can add data and behavior to an object by assigning contentstoitsslots.0printing. plus a few more. Y o u Lobby that contains all the named There’s a master namespace called objects. Y o u can define types and objects.Y o ucanseeitlikethis: Io>Lobby ==> Object_0x1002184e0: Car =Car_0x100473938 Lobby =Object_0x1002184e0 Protos =Object_0x1002184e0 Vehicle =Vehicle_0x1003b61f8 exit =method(.) ferrari =Car_0x1004f43d0 forward =method(.areon Lobby.) type ="Car" Io>Carproto ==> Vehicle_0x1003b61f8: description ="Somethingtotakeyoufaraway" type ="Vehicle" These were the prototypes that you used to clone alsoseetheircustomslotsforconvenience.October2010) . All of the assignments you’ve done in the console. Think about it.Everythingelseinvolveslearningthelibraries.D AY 1: S KIPPING S CHOOL .) Reporterratum thiscopyis (P1. you now know the core organizational principles of Io. f e r a r i and Car....invokingtheslotinvokesthemethod: Io>ferraridrive Vroom ==>Vroom Believe it or not.Y o ucangetthecontentsofslots.likethis: Io>ferrarigetSlot("drive") ==>method( "Vroom"println ) getSlot willgiveyouyourparent’sslotiftheslotdoesn’texist: Io>ferrarigetSlot("type") ==>Car Y o ucangettheprototypeofagivenobject: Io>ferrariproto ==> Car_0x100473938: drive =method(.

it sends that message to itsprototype.4) Reporterratum thiscopyis (P1.Alistisanorderedcollectionofobjects Map is the prototype of any type.4) ==>list(1.Sinceyoucanseeorchangeanyslotoranyobject. • Slotscontainobjects. which wraps the arguments up into a list. Using convenientlycreatealist. Protos.Butfirst."Findapresent") Object supports the list There’s a shortcut way of representing a list."findContinuumTransfunctioner") Io>toDossize ==>2 Io>toDosappend("Findapresent") ==>list("findmycar".D AY 1: S KIPPING S CHOOL .2. • Every interaction withanobjectisamessage. • Objectsremembertheirprototypes.Createalistlikethis: Io>toDos:=list("findmycar".0printing. • Objectshaveslots."findContinuumTransfunctioner") ==>list("findmycar". and forkey-valuepairs. list. H ANGING O UT 68 Y o useethe exit implementation. • If an object can’t respond to a message.3. List is the prototype for all lists. proto- ListsandMaps Iohasafewtypesofcollections. youcandosomeprettysophisticatedmetaprogramming.liketheRubyhash. • A message returns the value in a slot or invokes the method in a slot. you can method. These are thebasicgroundrules: • Every thing isanobject.you needtoseethenextlayerofbuildingblocks:collections.October2010) .likethis: Io>list(1. The prototype programming paradigm seems clear enough.includingmethodobjects.youcloneotherobjectscalled types."findContinuumTransfunctioner". o fr w a r d . Andthat’smostofit. •Y o udon’tinstantiateclasses.3.andthestuffwedefined.2.

2.2.3)at(1) ==>2 Io>list(1.3.3) Io>list()isEmpty ==>true Map.October2010) .3)pop ==>3 Io>list(1.4) Io>list(1.2."rockandroll") ==> Map_0x115f580: Io>elvisasObject ==> Object_0x11c1d90: home ="Graceland" style ="rockandroll" Io>elvisasList ==>list(list("style".0printing.2."Graceland")) Io>elviskeys ==>list("style".3.2.2. H ANGING O UT List alsohasconveniencemethodsformathandtodealwiththelistas 69 otherdatatypes.you’llworkwiththemwithan APIthatlookslikethis: Io>elvis:=Mapclone ==> Map_0x115f580: Io>elvisatPut("home".IomapsarelikeRuby TheothermajorcollectionclassinIoisthe hashes.suchasstacks: Io>list(1.3.4)sum ==>10 Io>list(1.5 Io>list( ==>2.3)append(4) ==>list(1."Graceland") ==> Map_0x115f580: Io>elvisat("home") ==>Graceland Io>elvisatPut("style".Sincethere’snosyntacticsugar.list("home".D AY 1: S KIPPING S CHOOL ."rockandroll")."home") Reporterratum thiscopyis (P1.3)prepend(0) ==>list(0.1.

notfalseasin C. Now that you’ve seen the basic collections.0printing. W e l’ need to introduce control structures.andsingletons Io’s conditions are pretty similar to those of other object-oriented languages.D AY 1: S KIPPING S CHOOL .whatis true? Io>trueproto ==> Object_0x200490: =Object_() != =Object_!=() .So.October2010) . and those will depend on booleanvalues.Makeanote:0istrueasinRuby.. true. Io>trueclone ==>true Io>falseclone ==>false Io>nilclone ==>nil Reporterratum thiscopyis (P1.Hereareafew: Io>4<5 ==>true Io>4<=3 ==>false Io>trueandfalse ==>false Io>trueandtrue ==>true Io>trueortrue ==>true Io>trueorfalse ==>true Io>4<5and6>7 ==>false Io>trueand6 ==>true Io>trueand0 ==>true That’ssimpleenough. you’ll want to use them. a hash is a lot like an Io object in structure where the keys are slots that are tied to values. The combination of slotsthatcanberapidlytranslatedtoobjectsisaninterestingone.a fs le .. H ANGING O UT Io>elvissize ==>2 70 When you think about it.nil.

ifalittleunexpected. Now.0printing. Sometimes. thanlettingIoforwardrequestsupthetree. Io can trip you up. and nil are singletons.October2010) .D AY 1: S KIPPING S CHOOL .you’llgetthisbehavior: Io>Highlanderclone ==> Highlander_0x378920: clone =Highlander_0x378920 type ="Highlander" Io>fred:=Highlanderclone ==> Highlander_0x378920: clone =Highlander_0x378920 type ="Highlander" Io>mike:=Highlanderclone ==> Highlander_0x378920: clone =Highlander_0x378920 type ="Highlander" Io>fred==mike ==>true Twoclonesareequal.eventuallygettingto Now. Createyourownsingletonlikethis: Io>Highlander:=Objectclone ==> Highlander_0x378920: type ="Highlander" Io>Highlanderclone:=Highlander ==> Highlander_0x378920: clone =Highlander_0x378920 type ="Highlander" 71 W e v ’e simply redefined the clone method to return Highlander. H ANGING O UT fs le . such as changing an object’s clone method to make a singleton. Cloning them Now.whenyouuse Highlander. Y o u can do the same pretty easily. rather Object. but you know enough to do some pretty radical things. there can be only one Thissolutionissimpleandelegant.W e v ’e blasted through a lot of information.That’snotgenerallytrue: Io>one:=Objectclone ==> Object_0x356d00: Io>two:=Objectclone ==> Object_0x31eb60: Io>one==two ==>false Highlander. a just returns the singleton value. Reporterratum thiscopyis (P1. that’s interesting! true.

you can see the code. Ididn’tfeelIunderstoodhowprogramminglanguagesworkwellenough to have anything useful to say.(ed. Y o u changejustaboutanyslotonanyobject.SteveimplementedIo inC.Here’sonethatyoumaynotwanttotry: Objectclone:="hosed" can Since you overrode the clone method on object. such as people select(age > 20) . Love him or hate him. though. Before we wrap up the day.andtherearemoregamesthatare Reporterratum thiscopyis (P1. H ANGING O UT 72 Be careful. If you simplify the semantics enough. so I started writing a small language to understandthembetter. He invented Io in 2002.D AY 1: S KIPPING S CHOOL .andgetaprettygoodideaofwhatisgoingon.0printing. Bruce Tate: WhydidyouwriteIo? Steve Dekorte: In2002.myfriendDruNelsonwrotealanguagecalled Cel(inspiredbySelf)andwasaskingforfeedbackonitsimplementation. For example.Therearevideogamesthatare puzzlegamesthatassumeasolution.ItgrewintoIo. Theyhelpwithunderstandingwhat’sgoingon.Iconstantlyforgetthesyntaxandweird semanticrulesforCandhavetolookthemup. Bruce Tate: Whatisthethingthatyoulikeaboutitthemost? Steve Dekorte: Ilikethesimpleandconsistentsyntaxandsemantics.)That’soneofthethingsIdon’twanttodowhenIuseIo. things become more flexible.Y o u canquicklylearnthe basics. I had the pleasure of interviewing him about hisexperienceswithcreatingIo. Y o u canstarttocomposethingsthatyoudidnotunderstandwhenyouimplementedthelanguage.But you can also get some pretty amazing behaviors in a short time. Since youhavecompleteaccesstooperatorsandtheslotsthatmakeupany object.October2010) . Io can be a love-hate relationship. As with Ruby.gettingtheiraddresses. AnInterviewwithSteveDekorte SteveDekorteisanindependentconsultantintheSanFranciscoarea.Ihaveaterriblememory. you can’t deny that Io is interesting.eventheonesthatdefinethe language.Y o ujusthavetokilltheprocess.andprintingthemout.Y o u r ’ e m a p ( a d d r e s s )println filteringalistofpeoplebasedonage.Here’sanexample. you can build domain-specific languages with a few short fascinating lines of code.Y o ucan’tfixit. nothing can create objectsanymore. let’s hear what the inventorofthelanguagehastosay.

Y o ucannow pauseandputsomeofwhatyou’velearnedintopractice. Reporterratum thiscopyis (P1. That said. you can read them all. So far. and SIMD support). themoreworkyouhavetodo. A minimal syntax has some benefits as well. In some ways.Themoreworkaparserhastodo. async sockets. you don’t have to learn any special rules or exceptions to them. in a router configuration language. H ANGING O UT 73 open-ended. Bruce Tate: WhataresomelimitationsofIo? Steve Dekorte: The cost of Io’s flexibility is that it can be slower for many common uses.Theprototypelanguagehasverysimple syntax that you can use to build new basic elements of the language itself.soIunderstand. The more complicated a language.Thatleadstoextra parsing rules.D AY 1: S KIPPING S CHOOL . Since there is not much going on syntactically. and as a scripting language for video games.0printing. When you program in a language. WhatW eLearnedinDay1 Y o u r ’e now through a good chunk of Io.Newuserssometimessay Iohastoolittlesyntax.I’vehadsimilarproblemswithLisp. Sometimesotherlanguagesmakesyntacticshortcuts. Itwasabusyfirstday. which can also make it muchfasterthanevenCappswrittenwithtraditionalthreadpersocket concurrencyornon-SIMDvectorops. I’ve heard rumors of Io from place to place like on a satellite. you need to have the parser in your head.October2010) . it also has certain advantages (such as coroutines. the more of the parseryouneedtohaveinyourhead.Ioislikethat. The open-ended ones are fun because you can do things thatthedesignersofthegameneverimagined. this minimal approach will make you work a little harder toreadthesyntax. Y o u r learning time can go toward establishing your vocabulary. Pixar uses it too. They wrote a blog entryaboutit.buttheyusuallywarmuptoit.Extrasyntaxmakesforquickr e a d n ig . Once you know how to read one sentence. Even core elements lack even the simplest syntactic sugar. you know a good deal aboutthebasiccharacterofIo.soit’stimetobreakforalittlebit. I’ve also had some complaints that the lack of syntax can make quick visualinspectiontrickier. Bruce Tate: Whereisthestrangestplaceyou’veseenIoinproduction? Steve Dekorte: Over the years.

D AY 2: T HE S AUSAGE K ING 74 Y o u rjobasanewstudentisgreatlysimplified: • Understandafewbasicsyntacticalrules. • Understandmessages. := (colonequals). • Is0trueorfalse?Whatabouttheemptystring?Is Supportyouranswerwithcode.0printing. He got a great table in a great restaurant Reporterratum thiscopyis (P1.searchingforanswersisgoing to be a little tougher because Io has so many different meanings. 3. Make sure you understandhowprototypeswork. Spend a little time playing with slots and prototypes. In the movie. Find: • SomeIoexampleproblems • AnIocommunitythatwillanswerquestions • AstyleguidewithIoidioms Answer: • Evaluate 1 + 1 and then 1 + "one" . the middleclass high-school student represented himself as the sausage king of Chicago in a classic bluff. Day1Self-Study Whenyou’relookingforIobackground. • Executethecodeinaslotgivenitsname. • Understandthelibraries. • Understandprototypes. I recommendGooglingfor Iolanguage .October2010) .3 Day2:TheSausageKing Think back to Ferris Bueller for a moment. Is Io strongly typed or weakly typed?Supportyouranswerwithcode. • Howcanyoutellwhatslotsaprototypesupports? = (equals).and ::= • Whatisthedifferencebetween (coloncolonequals)?Whenwouldyouuseeachone? nil trueorfalse? Do: • RunanIoprogramfromafile.



becausehewaswillingtobendtherules.Ifyou’recomingfromaJava background and you liked it, you’re thinking about what could have happened—toomuchfreedomisnotalwaysagoodthing.Buellerprobably deserved to be thrown out. In Io, you’re going to need to relax a little and take advantage of the power. If you’re coming from a Perl scriptingbackground,youprobablylikedBueller’sbluffbecauseofthe result of the bluff. If you’ve traditionally played things a little fast and loose, you’re going to have to pull back a little and inject some discipline. In day 2, you’ll start to see how you might use Io’s slots and messagestoshapecorebehaviors.

All of Io’s conditional statements are implemented without syntactical sugar. Y o u l’ find they are easy to understand and remember, but they’re a little harder to read because of fewer syntactic clues. Setting upasimpleinfiniteloopiseasy.TypeControl+Ctobreakout:
Io>loop("gettingdizzy..."println) gettingdizzy... gettingdizzy... ... gettingdizzy.^C IoVM: Receivedsignal.Settinginterruptflag. ...

Loops will often be useful with the various concurrency constructs, but you’ll normally want to choose one of the conditional looping constructs,suchasa while loop.A while looptakesaconditionandamessagetoevaluate.Keepinmindthatasemicolonconcatenatestwodistinctmessages:
Io>i:=1 ==>1 Io>while(i<=11,iprintln;i=i+1);"Thisonegoesupto11"println 1 2 ... 10 11 Thisonegoesupto11

o f r loop. The o f r loop takes the name of Y o u could do the same with a the counter, the first value, the last value, an optional increment, and amessagewithsender.

Reporterratum thiscopyis (P1.0printing,October2010)

Io>for(i,1,11,iprintln);"Thisonegoesupto11"println 1 2 ... 10 11 Thisonegoesupto11 ==>Thisonegoesupto11


Io>for(i,1,11,2,iprintln);"Thisonegoesupto11"println 1 3 5 7 9 11 Thisonegoesupto11 ==>Thisonegoesupto11

Infact,youcanoftenhaveanarbitrarynumberofparameters.Didyou catch that the optional parameter is the third one? Io will allow you to attach extra parameters. That may seem to be convenient, but you needtowatchcarefullybecausethereisnocompilertobabysityou:
Io>for(i,1,2,1,iprintln,"extraargument") 1 2 ==>2 Io>for(i,1,2,iprintln,"extraargument") 2 ==>extraargument

In the first form, “extra argument” is really extra. In the second form, you’ve omitted the optional increment argument, and that effectively shiftedeverythingtotheleft.Y o u r“extraargument”isnowthemessage, i println , which returns i. If that line of and you’re working in steps of code is buried deeply into a complex package, Io just puked in your car. Sometimes, you have to take the bad with the good. Io gives you freedom.Sometimes,freedomhurts. The if control structure is implemented as a function with the form if(condition, true code, a fs le code) true code if . The function will execute condition istrue;otherwise,itwillexecute a fs lecode :
Io>if(true,"Itistrue.","Itisfalse.") ==>Itistrue.

Reporterratum thiscopyis (P1.0printing,October2010)

Io>if(false)then("Itistrue")else("Itisfalse") ==>nil Io>if(false)then("Itistrue."println)else("Itisfalse."println) Itisfalse. ==>nil


Y o u v ’espentsometimeoncontrolstructures.Now,wecanusethemto developourownoperators.

Like with object-oriented languages, many prototype languages allow for syntactic sugar to allow operators. These are special methods like + and / that take a special form. In Io, you can see the operator table directly,likethis:
Io>OperatorTable ==>OperatorTable_0x100296098: Operators 0 ?@@@ 1 ** 2 % * / 3 +4 <<>> 5 <<=>>= 6 !=== 7 & 8 ^ 9 | 10 &&and 11 or|| 12 .. 13 %=&= *=+=-=/=<<=>>=^=|= 14 return AssignOperators ::=newSlot := setSlot = updateSlot Toaddanewoperator:OperatorTableaddOperator("+",4) andimplementthe+message. Toaddanewassignoperator:OperatorTableaddAssignOperator( "=","updateSlot")andimplementtheupdateSlotmessage.

Y o u can see that an assignment is a different kind of operator. The number to the left shows the level of precedence. Arguments closer to 0 bind first. Y o u can see that + evaluates before ==, and * before +, ().Let’s justasyouwouldexpect.Y o ucanoverridetheprecedencewith xor returns true ifexactlyoneofthe defineanexclusiveoroperator.Our
Reporterratum thiscopyis (P1.0printing,October2010)

D AY 2: T HE S AUSAGE K ING fs le argumentsis true,and a table:



Io>OperatorTableaddOperator("xor",11) ==>OperatorTable_0x100296098: Operators ... 10 &&and 11 orxor|| 12 .. ...

Y o ucanseethenewoperatorintherightplace.Next,weneedtoimplefs le : mentthe xor methodon true and a
Io>truexor:=method(bool,if(bool,false,true)) ==>method(bool, if(bool,false,true) ) Io>falsexor:=method(bool,if(bool,true,false)) ==>method(bool, if(bool,true,false) )

W e r ’e usingbruteforceheretokeeptheconceptssimple.Ouroperator behavesexactlylikeyouwouldexpect:
Io>truexortrue ==>false Io>truexorfalse ==>true Io>falsexortrue ==>true Io>falsexorfalse ==>false

truexortrue getsparsedas truexor(true) .The Whenallissaidanddone, method in the operator table determines the order of precedence and thesimplifiedsyntax.

Assignment operators are in a different table, and they work a little bit differently. Assignment operators work as messages. Y o u l’ see an example of them in action in Section 3.4, Domain-Specific Languages , on page 83. For now, that’s all we’ll say about operators. Let’s move on to messages, where you will learn to implement your own control structures.

Reporterratum thiscopyis (P1.0printing,October2010)



As I was working through this chapter, one of the Io committers was helping me through a moment of frustration. He said, “Bruce, there’s something you have to understand about Io. Almost everything is a message.”IfyoulookatIocode,everythingbutcommentmarkersand the comma (,) between arguments are messages. Everything. Learning Io well means learning to manipulate them beyond just basic invocation. One of the most crucial capabilities of the language is message reflection. Y o u can query any characteristic of any message and act appropriately.
sender, the target, and the arguA message has three components: the ments.InIo,the sender sendsamessagetoa target.The target executes themessage.

The call method gives you access to the meta information about any postOffice that gets mesmessage. Let’s create a couple of objects: the a e lir sagesandthe m thatdeliversthem:
Io>postOffice:=Objectclone ==> Object_0x100444b38: Io>postOfficepackageSender:=method(callsender) ==>method( callsender )

Io>mailer:=Objectclone ==> Object_0x1005bfda0: Io>mailerdeliver:=method(postOfficepackageSender) ==>method( postOfficepackageSender )

There’s one slot, the deliver slot, that sends a packageSender message m a e lir to postOffice.Now,Icanhavethe deliveramessage:
Io>mailerdeliver ==> Object_0x1005bfda0: deliver =method(...)

So,the deliver methodistheobjectthatsentthemessage.W e getthetarget,likethis:
Io>postOfficemessageTarget:=method(calltarget) ==>method( calltarget )


Reporterratum thiscopyis (P1.0printing,October2010)

Io>postOfficemessageTarget ==> Object_0x1004ce658: messageTarget =method(...) packageSender =method(...)


Simple enough. The target is the post office, as you can see from the slotnames.Gettheoriginalmessagenameandarguments,likethis:
Io>postOfficemessageArgs:=method(callmessagearguments) ==>method( callmessagearguments ) Io>postOfficemessageName:=method(callmessagename) ==>method( callmessagename ) Io>postOfficemessageArgs("one",2,:three) ==>list("one",2,:three) Io>postOfficemessageName ==>messageName

So,Iohasanumberofmethodsavailabletoletyoudomessagereflection.Thenextquestionis,“WhendoesIocomputeamessage?” Mostlanguagespassargumentsasvaluesonstacks.Forexample,Java computes each value of a parameter first and then places those values on the stack. Io doesn’t. It passes the message itself and the context.Then,thereceiversevaluatethemessage.Y o ucanactuallyimpleif. The form is ment control structures with messages. Recall the Io if(booleanExpression, trueBlock, a fs le B o lc k ) . Let’s say you wanted to implementan unless.Here’showyou’ddoit:
Download io/unless.io

unless:=method( (callsenderdoMessage(callmessageargAt(0)))ifFalse( callsenderdoMessage(callmessageargAt(1)))ifTrue( callsenderdoMessage(callmessageargAt(2))) ) unless(1==2,write(


),write( "oneistwo\n"


doMesThis little example is beautiful, so read it carefully. Think of sage as somewhat like Ruby’s e v a l but at a lower level. Where Ruby’s e v a l evaluates a string as code, doMessage executes an arbitrary message. Io is interpreting the message parameters but delaying binding andexecution.Inatypicalobject-orientedlanguage,theinterpreteror compilerwouldcomputeallthearguments,includingbothcodeblocks, and place their return values on the stack. In Io, that’s not what happensatall.
Reporterratum thiscopyis (P1.0printing,October2010)

0printing. Here are a few of them in action. "\n---------------" ) prototypeslotNamesforeach(slotName. That concept is extremely powerful.andmessage)andputsitonthestack. So far. Theobject w sendsthepreviousmessage.prototypetype. Io begins executing the unless message. ("Itisa fs le "println). The message is not false. you’ve seen one side of reflection: behavior with message reflection. e s e t l y("Itistrue"println). That code simplifies to w e s e t l y trueLove . and the value is true.writeln(slotName)) writeln prototypeancestors)) Animal:=Objectclone Animalspeak:=method( "ambiguousanimalnoise" println) Reporterratum thiscopyis (P1. Iotakestheinterpretedmessageandthecontext(thecallsender. whichsimplifiesto w W e r ’e taking advantage of the fact that Io does not execute the arguunless controlstrucmentstocomputeareturnvaluetoimplementthe ture. Reflection Io gives you a simple set of methods to understand what’s going on in the slots. so we’ll execute the third code block. princessButtercup evaluates the message. If you’ve ever seen the movie The Princess Bride .("Itistrue"println)) . The other side of the equationisstate.W e l’ lookatstatewithanobject’sslots. unless 3. There is no unless. slot.soIowalksuptheprototypechainuntilitfinds call 4. target.io Objectancestors:=method( prototype:=selfproto if(prototype!=Object. Now. Io executes sender doMessage(call message argAt(0)) .D AY 2: T HE S AUSAGE K ING e s e t ly Saytheobject w 81 sendsthemessage princessButtercupunless(trueLove. writeln("Slotsof" . This code creates a couple prototype chainwithamethod ofobjectsandthenworksitswayupthe called ancestors: Download io/animals. 2. First.October2010) .Theresultisthisflow: e s e t ly 1. 5. e s e t ly you know that w has a slot called trueLove.

October2010) .anywhere.usedatastructures.andthoseprototypes areobjectsthathaveslots. with a speak method.Y o uknowhowtomakedecisions.In these exercises. Get thoroughly familiar with Io.Objectreflection means dealing with objects and the slots on those objects.andusethebasiccontrolstructures.yousawmessagereflection.0printing. disco’s and use that to create a prototype is Duck. No classes areinvolved. but we don’t handle this case.Everyobjecthasaprototype.To savepaper. The ancestors method prints the slots of an object’s prototype and then calls ancestors on the prototype.Runitwith ioanimals. Inthepostofficeexample. day 2 should have been a breakthrough day of sorts.D AY 2: T HE S AUSAGE K ING Duck:=Animalclone Duckspeak:=method( "quack" println) Duckwalk:=method( "waddle" println) disco:=Duckclone discoancestors 82 Animal prototype The code is not too complicated. we’ll put Io through its paces. Y o u will really want to have the basics down when we move into problems that stretch Io into the metaprogramming and concurrencyspaces.define methods. Y o u should know enough Io to do basic tasks with a little supportfromthedocumentation. Keep in mind that an object can have more than one prototype.io : Here’stheoutput: SlotsofDuck --------------speak walk type SlotsofAnimal --------------speak type Nosurprisesthere.InIo.wehalttherecursionbeforeprintingalloftheslots inthe Object prototype.dealingwithreflectionhastwoparts. Reporterratum thiscopyis (P1. we create an Duck instance. First. WhatW eLearnedinDay2 If you’re still following.

) dim(x. As a bonus. 2. one of the core committers for Io. set(x. 1. 3.21. W r t i e a prototype for a two-dimensional list. If you would like. solve the problem withrecursionandwithloops. W r t i eaprogramthatgivesyoutentriestoguessarandomnumber from 1–100.0printing. 3. A Fibonacci sequence starts with two 1s.October2010) . The y lists that are x elements long. m y A v e r a g e 4.whichwasalanguagethatchanged thewayIthink. 5. give a hint of “hotter” or “colder” afterthefirstguess.D AY 3: T HE P ARADE AND O THER S TRANGE P LACES 83 Day2Self-Study Do: 1. W r t i eaprogramtoaddupallofthenumbersinatwo-dimensional array. Domain-SpecificLanguages Just about everyone who is deeply involved with Io appreciates the power that Io gives you in the area of DSLs. x)) == 7.8. Addaslotcalled toalistthatcomputestheaverageof all the numbers in a list. 8.intheparade—everywhereyoudon’texpecthim. I found myself giggling like a school girl at the unexpected places the languagewouldtakeme.W r t i eaprogramtofindthenthFibonacci number.andreadamatrixfromafile. (new_matrix get(y. fib(1) is 1.y) shouldreturnthatvalue. W r t i ethematrixtoafile. Bonus: W r t i e a transpose method so that m a t x r i get(x. y) method 5. and fib(4) is 3. should allocate a list of v a u le ) get(x.4 Day3:TheP a r a d eandOtherStrangePlaces My first few days with Io were frustrating. Jeremy Tregunna. What happens if there are no numbers inalist?(Bonus:RaiseanIoexceptionifanyiteminthelistisnot anumber.and 6. but after a couple of weeks. y . Each subsequent number is the sum of the two numbers that came before: 1.y) ontheoriginallist. told me about an implementation of a Reporterratum thiscopyis (P1.Intheend.andsoon.13.I gotoutofIoexactlywhatIwanted.It’slikeFerrisshowinguponthenews. Howwouldyouchange / toreturn0ifthedenominatoriszero? 3. shouldsetavalue. 2.atthe ballpark.

callevalArgAt(1)) ) s:=Filewith( "phonebook.whobroughtthisexampleuptothecurrentversionofIo: Download io/phonebook. That’s another problem for another day.October2010) .here’sanotheroneofJeremy’s gems. Two that come to mind are parsing the list or interpreting it.txt" )openForReadingcontents phoneNumbers:=doString(s) phoneNumberskeys println phoneNumbersvaluesprintln That code is slightly more complex than anything you’ve seen so far. Sayyouwanttorepresentphonenumbersinthisform: { "BobSmith":"5195551212". "atPutNumber" ) Reporterratum thiscopyis (P1.io OperatorTableaddAssignOperator( ":" . This one implements an API that provides an interesting syntax forphonenumbers. rdoMessage(arg) ) r ) MapatPutNumber:=method( selfatPut( callevalArgAt(0)asMutableremovePrefix( "\"")removeSuffix(" \"" ). "atPutNumber" ) curlyBrackets:=method( r:=Mapclone callmessageargumentsforeach(arg.you willhavetoalterIo.Todothis.0printing.Iowillacceptthislistasavalid syntaxforbuildinghashes! Here’s how Jeremy attacked the problem. Parsing it means that you would write a program to recognize the various elements of the syntax.D AY 3: T HE P ARADE AND O THER S TRANGE P LACES 84 subsetofCinIothattookaround40linesofcode!Sincethatexample isjustalittletoodeepforustoconsider.Whenyou’redone. butyouknowthebasicbuildingblocks.Let’sdeconstructit: OperatorTableaddAssignOperator( ":" . "MaryWalsh":"4162223434" } There are many approaches to the problem of managing such a list. It would bemuchmorefuntointerpretthatcodeasanIohash. and then you could place the code in a structure that Io understands. with an assist from Chris Kappler.

weiteratethrougheachofthephone o fr E a c h numbersinthelistwith . the first phone number willexecuteas r"BobSmith":"5195551212" ."5195551212") . rdoMessage(arg) ) r ) The parser calls the curlyBrackets method whenever it encounters curly brackets ({}). Y o u can see that atPutNumber simply calls atPut on the target range.strippingthequotesoffthefirstargument. W t i h n i this method. k willbeparsedas atPutNumber("key".andthesecondis e y:v a u le a u le ) avalue.D AY 3: T HE P ARADE AND O THER S TRANGE P LACES 85 ThefirstlineaddsanoperatortoIo’sassignmentoperatortable. Remember.txt" )openForReadingcontents phoneNumbers:=doString(s) phoneNumberskeys println phoneNumbersvaluesprintln Reporterratum thiscopyis (P1.v . Then.understanding ever : isencountered.Then. we execute rdoMessage(arg) .v . callmessage .That bringsustothefollowing: MapatPutNumber:=method( selfatPut( callevalArgAt(0)asMutableremovePrefix( callevalArgAt(1)) ) "\"")removeSuffix(" \"" ).whichisthepartofthecode Fromlefttoright.tostripthequotes.Foreachphonenameandphonenumber. so we strip the leading and trailing quotes.wetakethe betweenthecurlybrackets. we create an empty map.WhenatPutNumber.Since:isinouroperatortable as atPutNumber. e y:v a u le a u le ) the key is already a string.Iowillparsethatas thatthefirstargumentisaname(andthusastring). we fr e a c h ( a r g .October2010) . r doMessage(arg)) for each execute call message arguments o argument.Moving on: curlyBrackets:=method( r:=Mapclone callmessageargumentsforeach(arg.That’saseriouslydenselineofcode!Let’stakeitapart.0printing.Inourcase.wehavetotranslatethemessageto amutablevalueforittowork.we’llexecute ratPutNumber("BobSmith". For example.So. Y o ucanusethecodelikethis: s:=Filewith( "phonebook. k willparseas atPutNumber("key".Sincemessages areimmutable. whichis self.

D AY 3: T HE P ARADE AND O THER S TRANGE P LACES 86 UnderstandingIo’ssyntaxistrivial. you can build DSLs to your heart’scontent.youseeafewnewlibraries. Each line in the map a p atPut("string1". When you send an object a given message is all baked into message.returnthedataorinvokethemethodinside. So.insideout. now you can begin to see how you would change Io’s syntax.and contents returns the contents of that file. It’s a bit like juggling hatchets any of the basic behaviors from onthehighwire. Io o fr w a r d doesn’thaveclasses.itwilldothefollowing: 1. openForingwithfiles.Thesearejustmessages.Y o ujusthavetoknowwhat’sgoing doString oninthelibraries. in Io. may Reporterratum thiscopyis (P1.October2010) . 2. The behavior for what happens in a Object. 4. Try toreadtheslotwiththenameofthemessageonthetarget. "string2") . and we’re left with a hash of phone does a m numbers.It’sacooltrickifyoucangetawaywithit.forwardthemessagetotheprototype.Y o ucanusethe messageinthesamewaythatyou would use Ruby’s method_missing. How would you go about dynamically changing the language’s behavior? That’sthetopicofthenextsection.Inthiscase. Computethearguments. Y o u wanttobuildsomethingthatletsyourepresentXMLdataasIocode. the braces define a map.The File isaprototypeforworkmessageevaluatesourphonebookascode. but the stakes are a little higher.0printing. Reading opensthatfileandreturnsthefileobject. 5.sochanging alsochangesthewayyouget object. Taken together. this code will read the phone bookandevaluateitascode. So. with specifiesafilenameandreturnsafileobject. normally o fr w a r d Butyoucan.andsenderofthemessage.target. "string1" : "string2" Then. Iftheslotexists. Getthename. 3. Io’smethod_missing Let’s review the flow of control.solet’sget started! XML is a pretty way to structure data with an ugly syntax. Y o u wouldn’tmesswiththem. since you can redefine anything from operators to the symbols that make up the language. These are the basic mechanics of inheritance within Io. Iftheslotdoesn’texist.

W e r ’e amissingmethod. if(contenttype== "Sequence" . Theoutputisexactlywhatyou’dexpect: <ul> <li> Io </li> <li> Lua </li> <li> JavaScript </li> </ul> Reporterratum thiscopyis (P1. it prints an open tag.writeln(content))) writeln("</" .Finally.callmessagename. The Builder prototype is the workhorse. li("JavaScript" )) Let’s carve it up.io goingtouseIo’sforwardlike Builder:=Objectclone Builderforward:=method( writeln("<" . First. </p> </body> likethis: body( p("Thisisasimpleparagraph.Here’sthecode: Download io/builder. we use a little message reflection. Io Builder prints the string without will recognize it as a sequence.October2010) . li("Lua" ). If the message is a string.") ) Let’scallthenewlanguageLispML.0printing.callmessagename. ">" ) callmessageargumentsforeach( arg.youmightwanttoexpressthis: <body> <p> Thisisasimpleparagraph. content:=selfdoMessage(arg). Builder printsaclosingtag. ">" )) Builder ul( li("Io" ).D AY 3: T HE P ARADE AND O THER S TRANGE P LACES 87 Forexample. Next. and quotes. It overrides o fr w a r d to pick up any arbitrary method.

I’mnotsurewhetherLispMListhatmuchofanimprovement over traditional XML.actors.io vizzini:=Objectclone vizzinitalk:=method( "Fezzik.October2010) . Y o u can fire a message asynchronously by using a message. A coroutine provides awaytovoluntarilysuspendandresumeexecutionofaprocess.Y o ucanevenoverride Concurrency Io has outstanding concurrency libraries. voluntarily yielding control to the other at specified intervals with the f e z z k i Reporterratum thiscopyis (P1.considerthisprogram: Download io/coroutine.we'llallbedead. AnyinstanceofBuilderwillhavethesamebehavior. Coroutines The foundation for concurrency is the coroutine." yield) fezzik:=Objectclone fezzikrhyme:=method( yield "Ifthereare.Doingthis.Forexample.Theserunconcurrently. Each yieldwillvoluntarily suspendtheprocessandtransfertoanotherpro@ or @@ before cess.fezzik@@rhyme CoroutinecurrentCoroutinepause println println println and vizzini are independent instances of Object with coroutines. The main components are coroutines. Y o u v ’e just completelychangedthewayinheritanceworksinoneofIo’sprototypes.Think of a coroutine as a function with multiple entry and exit points.D AY 3: T HE P ARADE AND O THER S TRANGE P LACES 88 Ihavetosay.youcan createanewlanguagewithIo’ssyntaxbutnoneofthesamebehaviors by defining your own Object and basing all of your prototypes on that Object tocloneyournewobject. W e fireasynchronous talk and rhyme methods. but the example is instructive.andfutures. The former returns a future (more later).arethererocksahead?" yield "Nomorerhymesnow. and the second returns nil andstartsthemessageinitsownthread." yield "Anybodywantapeanut?" println) vizzini@@talk.Imeanit. newobject.0printing.

Let’stakeasimpleexample.Coroutinesaregreatforsolutionsrequiringcooperative multitasking. process messages. W o r k e r processescouldpauseafterprocessingqueueitems.twoprocessesthatneedtocoordinate caneasilydoso.io Fezzik. Nomorerhymesnow.Endofstory. The messages an actor receives are concurrent. leading tounpredictableresults. an actor places an incoming message on a queue and processes the contents of the queuewithcoroutines. Actors Actors have a huge theoretical advantage over threads.Whenyoucombinethisconcurrencystrategywith objectsthathavechangeablestate. Anybodywantapeanut? Scheduler:nothinglefttoresumesoweareexiting Java and C-basedlanguagesuseaconcurrencyphilosophycalled preemptivemultitasking . Threads can change each other’s state without restriction. Adistributedclientcouldrelinquishcontrolwhenwaitingfortheserver.W t i hthisexample. The last pause waits until all async messages complete 89 andthenexits.we’ll createtwoobjectscalled a and slower: fs t e r Io>slower:=Objectclone ==> Object_0x1004ebb18: Io>faster:=Objectclone ==> Object_0x100340b10: Reporterratum thiscopyis (P1. and create other actors.we’lllookintoactors. Next.applicationscanvoluntarilygiveupcontrolatreasonabletimes. Here’sthebeautyofIo.0printing.Y o uwon’tbelievehoweasytheyaretocode. Coroutines are the basic building blocks for higher levels of abstractions like actors. W t i h coroutines.youwindupwithprogramsthatare hardtopredictandnearlyimpossibletodebugwiththecurrenttesting strategies that most teams use.toreadpoetry.arethererocksahead? Ifthereare.Sendinganasynchronousmessagetoanyobject makesitanactor.forexample: batate$iocode/io/coroutine. where two threads access resources at the same time. In Io. Coroutines are different.October2010) .First. Think of actors as universal concurrent primitives that can send messages.D AY 3: T HE P ARADE AND O THER S TRANGE P LACES yield message.we'llallbedead. An actor changes its own state and accesses other actors only through closely controlled queues.Imeanit.Threadsaresubjecttoaconcurrencyproblemcalled raceconditions.

Reporterratum thiscopyis (P1..faster@@start. A future is a result object that is immediately returned from an asynchronousmessagecall.0printing.October2010) .Sincethemessagemaytakeawhiletoprocess. But we can easily make each object run in its own @@.we’lladdamethodcalled start toeach: Io>slowerstart:=method(wait(2).com/")@fetch Icanexecutethemethodanddosomethingelseimmediatelyuntilthe resultisavailable: writeln("Dosomethingimmediatelywhilefetchgoesoninbackground.whichwillreturnimmedithreadbyprecedingeachmessagewith atelyandreturnnil: Io>slower@@start.. thefuturebecomestheresultoncetheresultisavailable. Say we have a method that takes a long timetoexecute: futureResult:=URLwith("http://google.wait(3) quickly slowly W e add an extra wait to the end so that all threads finish before the program terminates..fasterstart slowly quickly ==>nil They start in order.") //.W e madebothoftheseobjectsactors. because the first message must finish before the second can begin.D AY 3: T HE P ARADE AND O THER S TRANGE P LACES 90 Now. the process blocks until the value is available. but that’s a great result.likethis: Io>slowerstart..writeln("quickly") ) W e can call both methods sequentially on one line of code with simple messages. justbysendinganasynchronousmessagetothem! Futures Iwillfinishuptheconcurrencydiscussionwiththeconceptoffutures.writeln("slowly") ) Io>fasterstart:=method(wait(1).Ifyouaskfor the value of a future before the result is available. W e are running in two threads.writeln("quickly")) ==>method( wait(1).writeln("slowly")) ==>method( wait(2).

C.Let’swrapupday3soyoucan putwhatyouknowintopractice. WhatW eLearnedinDay3 In this section. W e added an operator to the operator table and wired that into operations on a hash table.wewrotesomecodethatusedcoroutinestomanageconcurrency.Thevalueisa result arrives. W esentsomeasynchronousmessagesthatmadeourprototypesactors. we built an XML generator that used method_missing toprintXMLelements. W e didn’thavetodoanythingbeyondchangingthesyntaxofourmessages. Day3Self-Study Do: • EnhancetheXMLprogramtoaddspacestoshowtheindentation structure. It’s a nice touch. leading toamorepredictableandunderstandableconcurrencymodelandless ofaneedforblockingstatesthatbecomebottlenecks.andtheyareeasytounderstandanduse. Futures in Io also provide automatic deadlock detection.") //thislinewillexecuteimmediately writeln("fetched"."bytes") //thiswillblockuntilthecomputationiscomplete //andIoprintsthevalue ==>1955 The futureResult code fragment will return a future object. you learned to do something nontrivial in Io.0printing.Icanusethefuturevalue: writeln("Thiswillblockuntiltheresultisavailable. immediately.Finally. a future is not a proxy implementation! The future will block Future objectuntilthe untiltheresultobjectisavailable. Next. Now that you’ve had a flavor of Io’s concurrency.October2010) . First.D AY 3: T HE P ARADE AND O THER S TRANGE P LACES 91 Then. Reporterratum thiscopyis (P1.welookedbrieflyatfuturesandhowtheyworkedinIo. Next. The coroutines differed from concurrency in languages like Ruby. The console is going to print the string value of the last statementreturned.futureResultsize. and Java because threads could only change their own state. we bent the rules of syntax and built a new hash syntax with braces. you have a sound foundationforevaluatingthelanguage. In Io. and then all instances of the value point to the result object.

getting to the same point took a little longer. • Enhance the XML program to handle attributes: if the first argument is a map (use the curly brackets syntax).TherearenoclassesormodulesinIo.Let’slookatwhereIoisexcelling today.Y o ucanlearnIoveryquickly. Io takes this flexibility to the max.. at least in a singlethread. Strengths Prototypelanguagesaregenerallyquitemalleable.Once youunderstandthecoresyntax. I found that I could work my way into metaprogramming quite quickly.MostoftheproductionIoapplicationsareembeddedsystems.Oneobject inheritsbehaviordirectlyfromitsprototype.everythingelseislearningthelibrary structures.0printing. and quite flexible.Thisapplicationmakessense.modernconcurrencylibrariesoftenmakeIoa goodlanguageforparallelprocessing.W RAPPING U P I O 92 • Createalistsyntaxthatusesbrackets.Thestrong. In Java.. allowing you to quickly create the syntax you want.Y o ucanchangeany slot on any object. but the semantics of the language lend plenty of power.5 WrappingUpIo Ioisanexcellentlanguageforlearninghowtouseprototype-basedlanguages. it took many months to get to the point where I could make any sense of metaprogrammingatall.sincethelanguageissmall. The virtual machine is easy to port to differentoperatingenvironments. The prototype languages encapsulate data and behavior like object-oriented programming languages.) wouldprint <bookauthor="Tate"> : 3. some of the trade-offs that make Io so dynamic tend to cap the performance. the syntax is stunningly simple. Simplicity Io’ssyntaxisremarkablycompact. Like Ruby. within my first month of using the language. In Ruby.October2010) . Footprint Io’sfootprintissmall. Inheritanceissimpler. Reporterratum thiscopyis (P1. Like Lisp. powerful. add attributes to theXMLprogram.Forexample: book({"author":"Tate"}.

Y o u can also override key language constructs by changing their slots directly. Said another way.Butthere’sacost.haveadifficulttimeunderstandingwhatyourprogram isdoing. W e a k n e s s e s There’s much to like about Io and some suboptimal aspects as well.theconcurrencyconstructsareup-to-dateand fresh. easy to understand. the trade-off is the opposite. Y o u would also need to learn that [ ] is a method to get the value at a specified index of an array. W t i h Io.Thisfree-wheelingnaturemeansyoucanchangethebasic rules of the language to suit your application.October2010) .sinceIohasthesmallest communityofanyofthelanguagesinthisbook. Forapointofcontrast. and coroutines make it much easier to build multithreadedapplicationsthatareeasiertotestandhavebetterperformance. the clean syntax makes Io.Erlang. Later.Ioalsogivesconsiderablethoughttomutabledataandhow to avoid it. Actors.butyoudohavetoworkalittle Reporterratum thiscopyis (P1.Also. in other languages.W RAPPING U P I O 93 Flexibility Io’sducktypingandfreedomallowyoutochangeanyslotinanyobject atanytime.youmayfindtheRuby code array[-1] bafflingbecauseyoudon’tunderstandthesyntacticsugar: -1 is shorthand for the last element in the array. you may find it easy to understand how a given program uses the Io language and.Y o u l’seeactorsinScala. On one side. at thesametime. futures.0printing.Simplesyntaxoftenmakesithardtocommunicate difficult concepts concisely. Y o u canevencreateyourownsyntaxquickly.Let’stakealookattheproblemsassociatedwithIo. Y o u don’t havetolearnverymuchtogetstarted.it’sariskierchoicefor someprojects. the language. you’d be able to process more code at a glance. Once you understood those concepts. Syntax Iohasverylittlesyntaxsugar.Atfirst. wewillbuildontheseconcepts.Simplesyntaxisadouble-edgedsword. Having these features baked into the core libraries made it easy to learn a robust concurrency model. Concurrency UnlikeJavaandRuby.considerRuby.and Haskell. Freedomandflexibilitycomeataprice. It’s quite easy to add proxies at any place through changing the forward slot.

Ithinkthelanguagehas ashottogrow. and it’s too difficult to learn a language and remember how to use it.0printing.October2010) . I also think that.future.Matzprefersplentyofsugar. The simple syntax and small footprint intrigued me. P e r o fr m a n c e Discussing performance in a vacuum of other issues such as concurrencyandapplicationdesignisnotusuallywise. and you need to spend more time to express code and potentially more energy to debug it. Steve Dekorte has created somethingliketheLispoftheprototypelanguages.butperilous. FinalThoughts In general.ThisproblemissomewhatmitigatedbyIo’sconcurrency constructs.W RAPPING U P I O 94 hardertoabsorbconceptsthatmightbeotherwisecommunicatedwith sugar. Y o u cannot always find librariesinIolikeyoucanwithotherlanguages.ithasabright. like Lisp. Community Right now.newlanguagesback.single-threadedexecutionspeed. The balance of syntactic sugar is a difficult one.LikeFerrisBueller.butIshouldpointout thatIohasanumberoffeaturesthatwillslowraw.Bystayingwiththisphilosophy uniformly in the language creation. Good JavaScript programmers could pick up Io quickly.EitherIowill get a killer application that drives acceptance or it will remain a niche player. Add too little. the Io community is very small. These issues are somewhat mitigated by having a good C interface (which talks to a variety oflanguages) and a syntax that is so easy to remember. Io has a strong overriding philosophyofsimplicityandflexibility. Add too much sugar. In the end.Stevedoesn’t.It’salsohardertofind programmers. Reporterratum thiscopyis (P1.Buthavingasmallercommunityisadefiniteweaknessandis themainthingthatholdspowerful.butyoushouldstillkeepthislimitationinmind. I liked learning Io. syntax is a matter of preference.

2000.1 I remember watching Raymond.Y o u l’throwsomefactsandinferences at Prolog and let it do the reasoning for you. if you can only frame your questions in the right way.CA:MGM. “How did he know that?” and “How didn’t he know that?” He’sa fountain of knowledge. the lead character.DibbsSally.fr/~liberti/public/computing/prog/prolog/prolog-tutorial.html http://www. 3. but you’re basically putting together a shopping list of ingredients and describing a stepby-stepprocessforbakingacake.SallyDibbs. 2 includingatutorialbyJ. IttookmeacoupleofweeksofplayingwithPrologbeforeIcouldmake an attempt at this chapter. Raymond Chapter 4 Prolog Ah.DVD.Fisher forsomeexamplestowadethrough 3 andanotherprimerbyA.withoutthinkingaboutwhetherheshould.1988.R.Y o utellthecomputerexactlyhowto doajob.W t i h both Raymond and Prolog. Imperativelanguagesarerecipes.Aaby tohelpthestructureandterminology gelforme. http://www. It’s more like going to a 1. Prologisadeclarativelanguage.461-0192. I used several tutorials as I ramped up. 2.edu/~jrfisher/www/prolog_tutorial/contents.andlotsofexperimentation. Think Rain Man . Prolog. Prolog represents a serious departure from the other languages we’ve encountered so far. RainMan .DirectedbyBarryLevinson.LosAngeles. Sometimes spectacularly smart. rattle off Sally Dibbs’ phone number after reading a phone bookthenightbefore.html . I often find myself asking. BothIo and Ruby are called imperativelanguages .Y o u l’getastoundinganswersonlyifyouknowhowtoaskthe question.Higher-levelimperativelanguagesmightgiveyoualittlemore leverage.lix.polytechnique. other times just as frustrating.csupomona. combining many longer steps into one. in equal parts.

pigslikemud.LikeSQL.) • Query. Reporterratum thiscopyis (P1.1 AboutProlog Developed in 1972 by Alain Colmerauer and Phillipe Roussel. As we walkthroughtheseexamples.basedon the rules you provided. A query is a question about that world.A BOUT P ROLOG 96 goodbaker. W t i hacasualflipthroughtheInternet. A rule is an inference about the facts in that world. (Does Babe like mud?) Facts and rules will go into a knowledge base .Y o ucanusethisrules-basedlanguageforexpressing logic and asking questions. W t i h Prolog. you don’t have to know how.andProlog willtrytofillintheholesthatwouldmakeyourincompletefactstrue. Like SQL. andsolvefamouspuzzlessuchastheTowerofHanoi(aroundadozen linesofcode). the data is in the form of logical rules. 4.Y o ucanleavegapsinyourassertions. (An animallikesmudifitisapig.October2010) .Prologwasoneofthefirstsuccessfullogicprogramming languages. Now.Prolog has two parts: one to express the data and one to query the data.Then.Y o umakeassertionswithpurelogic.Y o udescribethecharacteristicsofcakesthatyoulikeand letthebakerpicktheingredientsandbakethecakeforyou. Enoughbackground. from scheduling toexpertsystems. but thedatawillconsistoflogicalrulesandrelationships. Prolog works on databases.Let’sgetstarted. Afactisabasicassertionaboutsomeworld.0printing.you’lldodirectretrievalofdataandalsousePrologto linkrulestogethertotellyousomethingyoumightnothaveknown.you’llusePrologtoexpressyourknowledgebase. The computerdoesthereasoningforyou. These are the building blocks: • Facts. the venerable language provides the programming foundation for a wide variety of problems. crack Rubik’s Cube. In Prolog. Prolog is a logic programming language that gained popularity in naturallanguage processing.) • Rules.andPrologdetermines whethertheyaretrue. A Prolog compiler compiles the knowledge base into a form that’s efficient for queries.(Babeisapig.youcanfindexamplestosolve a Sudoku with fewer than twenty lines of code.

and the last statement is a rule. Facts are directobservationsofourworld.0printing. Key the following into an editor: Download prolog/friends.thecaseofthefirstletterissignificant. Raymond told his brother he was an excellent driver. The previous file is a knowledge base with facts and rules.Z). First things first.Y):-\+(X=Y). it’s a variable. friend(X.October2010) . I guarantee either you will change the way you think or you’ll fail.Ifaword begins with a lowercase character. make some rules. w . but if you choose a different version ofProlog. atoms can’t. The first three statements are facts.cheese).W e r ’e goingtousePrologtostatesome facts. Y o u can learn the syntax rules quickly. He was using all the main elements—the steering wheel. I’m using GNU Prolog.sheep). the brakes. meaning he could do a fine job of handling the car at five miles per hour in parking lots. Like Io. Dialects can vary. and w are atoms. W e l’ save the in-depth constructionforalaterday. Be careful. Y o u can read Reporterratum thiscopyis (P1. Let’s build a simple knowledge base with a few facts. likes(wendolene. These lines are a a lc e e n d o e ln e each facts. Prolog is an extremely simple language syntactically.D AY 1: A N E XCELLENT D RIVER 97 4.likes(X. I’ll do my best to stay on common ground. Regardless of the version you choose. BasicF a c t s In some languages. it’s an atom —a fixed value like a Ruby symbol. If it begins with an uppercase letter or an underscore.That’syourgoaltoday. The real fun begins when you layer concepts in interesting ways.likes(Y.Z).pl likes(wallace.cheese). and do some basic queries.2 Day1:AnExcellentDriver In Rain Man .you’llneedtodoalittlehomeworktounderstandwhereyour dialect is different. If this is your first exposure.3. Get a working installation. pay attention to the first three lines. V a r a ib e l values can change.butinProlog. capitalization is entirely at the programmer’s discretion.Rulesarelogicalinferencesaboutour world. for this book. grommit. the accelerator—he just used them in a limited context. For now.1. here’s how you’lluseit. version 1. likes(grommit.

calleda subgoal.October2010) . /Users/batate/prag/Book/code/prolog/friends.and w sheep.Let’sputthefactsintoaction.) These are not too interesting: Prolog is just parroting your facts back to you. The most basic questions are and no questionsaboutfacts.toloadyourfile.Then. BasicInferencesandV ariables Let’strythe friend rule: |?-friend(wallace. Prolog is working through the rules we gave it and answering or no questions.Askafew: |?-likes(wallace. In this case.D AY 1: A N E XCELLENT D RIVER a a lc e e n d o e ln e themas w likes cheese.Lookat InEnglish.sheep). grommit likes cheese. y e s w a a lc e Thesequestionsareprettyintuitive. yes y e s .wallace).Does likesheep?(No. There’s more here than meets the eye.Let’stakealookatinferences. 98 likes StartyourProloginterpreter.11ms yes |?- UnlessPrologiswaitingonanintermediateresult.pl'].for X tobeafriendof :-. Check out the friend ruleagain: y e s Y. thefirstparttotherightof so \+(X=Y) means X isnotequalto Y. no |?-likes(grommit. compiling/ Users/batate/prag/Book/code/prolog/friends.)Does grommit like cheese? (Yes.. Reporterratum thiscopyis (P1.Ifyou’reusingGNUProlog. the file loaded successfully. It starts to get a little more exciting whenyoustarttobuildinsomelogic. X cannotbethesameas Y.cheese).4linesread997byteswritten.enterthefollowing: |?-['friends.plforbytecode.itwillrespondwith y e s or no. \+ doeslogicalnegation.typethecommand gprolog. so it returned W e can start to ask some questions. no So.0printing..plcompiled.

is a Prolog rule with three variables.likes(X. Y. In this section. grommit. likes(X.Z) .Both w and grommit like cheese.separatedbycommas.Try anotherquery: |?-friend(wendolene. X So. so the logic engine reported notfriends. Y.Allmustbetruefortheruletobetrue.and cheese ..soweprovethesecond andthirdsubgoals..sothesequeries succeed.and Z: .. and Z.D AY 1: A N E XCELLENT D RIVER 99 Try somemorequeries: |?-friend(grommit. e call the rule friend/2. that grommit likes Z.Inthesequeries.wallace). grommit and w a a lc e like cheese. To do this. Z) and likes(Y. but we can do W e v ’e used Prolog to answer some more than that.October2010) . FillingintheBlanks y e s or no questions. shorthand for friend with two parameters. Reporterratum thiscopyis (P1.Z). This rule has three subgoals.0printing. None existed. yes |?-friend(wallace. no Inthiscase.Z). our rule means X is a friend of Y if X and Y are not the same and and Y likethesame Z.likes(Y. they are w e n d o e ln e Neither combination satisfied both goals. X isnotequalto Y. firstsubgoal.and sheep likes Z and no.Thequerywillusethesecondandthirdsubgoals.This. X. yes X likes some Z and Y In English. grommit..grommit).Y):-\+(X=Y).Prologhadtotryseveralpossiblevaluesfor e n d o e ln e • w e n d o e ln e • w X. friend(X. you will specify a variable in yourquery. Let’sformalizetheterminology.provingthe Let’sdiveintothecode.grommit). we’ll use the logic engine to find all possible matches for a query. X is a friend of Y if we can prove that a a lc e likesthatsame Z. W .

Z).“Findsomevaluefor spam.pl'].Y):-food_type(X.meat). food_type(spam..Asaconve- Reporterratum thiscopyis (P1. food_type(twinkie.15ms (1ms)yes andasksomequestions: |?-food_type(What. flavor(savory. mean a o a food type has a characteristic flavor.cracker). and it returned sausage. What=spam?. food_flavor(X. flavor(sweet. we asked for another.meat). we have a rule called o fo d _ fl a v o r X has a o fo d _ fl a v o rY that infers the flavor of food. such as .Z).meat).pl food_type(velveeta. 12linesread-1557byteswritten. and Prolog respondedwith no.meat).plforbytecode. Compileit: |?-['code/prolog/food.dessert). Finally. food_type(ritz. flavor(sweet.W e r ’e askingProlog. Then. Others..0printing.cheese).D AY 1: A N E XCELLENT D RIVER 100 Considerthefollowingknowledgebase: Download prolog/food. When we typed the .plcompiled.October2010) . no What Now. A food if o fo d _ t y p eZ thefoodisofa andthat Z alsohasthatcharacteristic flavor.that’sinteresting. o fo d _ t y p e ( v e v le e t a . such as flavor(sweet. cheese) W e have a few facts. mean fo d has a certain type. compiling/ Users/batate/prag/Book/code/prolog/food.flavor(Y.meat). food_type(sausage. dessert) . They were easy values to find since the queries depended on basic facts.soda). Some.soda). we were asking Prolog to find another.Thisbehaviorcanbeslightlyinconsistent.cheese). food_type(jolt.”Prologfoundone.dessert). flavor(savory. /Users/batate/prag/Book/code/prolog/food. thatsatisfiesthequeryfood_type(What.. What=sausage?.

“Whatfoodshaveasavory flavor?” Prolog must tie together primitive facts about food.sweet). What=soda yes No. o is a rule. no fo d _ fl a v o r ( X . Theseareallfacts.too: |?-food_flavor(What.W e donotwanttwostatesofthesamecolortotouch.savory).takethisexample. and flavors to reach the conclusion.Foramorespectacularlook atProlog. no |?-flavor(sweet.itwill. types. MapColoring Let’susethesameideatodomapcoloring. If you for the next and return Prologcangiveyouinformationsooner. Y) Remember.ifPrologcandetectthattherearenomorealternativesremaine s . Reporterratum thiscopyis (P1. What=velveeta?. The logic engine has to work through possiblecombinationsthatcouldmakeallthegoalstrue. it will prompt no.What). on the next page.October2010) . What=sausage?.0printing. What food types are sweet? dessert and soda. The feature is really a convenience. sausage is not sweet.W ewanttocoloramapofthesoutheastern United States.D AY 1: A N E XCELLENT D RIVER 101 nience.Try afewmore: |?-food_flavor(sausage. W e r ’e asking Prolog to findallpossiblevaluesthatsatisfythequery. What=spam?. not a fact.you’llseea y are more alternatives without doing more computation. What=dessert?.1.IfPrologcan’timmediatelydeterminewhetherthere ing.ButyoucanletPrologconnectthedotsforyou. W e l’ cover the states shown in Figure 4.

Alabama).Mississippi. W e tell Prolog the sets of different colors to use coloring rule.pl different(red.Georgia). we tell in the map coloring.Tennessee. different(Georgia. different(Alabama.blue).Mississippi).Florida).October2010) .Florida):different(Mississippi.Tennessee).andwe’redone.different(blue.1:Mapofsomesoutheasternstates W e codeupthesesimplefacts: Download prolog/map.red).Try it: |?-coloring(Alabama.different(green. different(Alabama.Tennessee).red). coloring(Alabama.blue). different(Mississippi.0printing.green). different(Alabama.different(red. W e have three colors.Mississippi.Georgia. Next. different(green.Tennessee). we have a rule.Georgia. different(blue. different(Alabama.Florida).green). In the Prologwhichstatesneighborothers. different(Georgia.Florida).Tennessee.D AY 1: A N E XCELLENT D RIVER 102 Tennessee Mississippi Alabama Georgia Florida Figure4. Alabama=blue Florida=green Georgia=red Mississippi=red Tennessee=green? Reporterratum thiscopyis (P1.

a..youhavetoaskyourself.pl cat(lion). W Y o u can get the other possible combinations too by typing t i ha dozenlinesofcode. tiger. = means unify.P a r t1 Atthispoint.Prologletsyou express the logic in facts and inferences and then lets you ask questions.and bear. Expressyourlogicinaprogram. twin_cats(X.we’redone.Y. variable x.thereisawaytocolorthesefivestateswiththreecolors.and Z are lion. 4.Considerthefollowingknowledgebase: Download prolog/ohmy. Reporterratum thiscopyis (P1. In this example.it’stimetobackupandprovidealittlemoretheory. Y o u r ’e not responsible for building any step-by-step recipe with this language. Putthepossiblesolutionsthroughyourprogram. Some languages use variable x=10 meansassign 10 tothe assignment.forexample. Prolog is not about writing algorithms to solve logical problems.InJavaorRuby.Z=bear. Y.respectively. cat(tiger).cat(Y).In twin_cats/2. Is your solution easy to understand? Think through what you’d have to do to solve complex logic problems like thisinRubyorIo.D AY 1: A N E XCELLENT D RIVER 103 Sureenough. W e have two facts: lions and tigers are cats. Where’stheProgram? W e have no algorithm! Try solving this problem in the procedural language of your choice. In dorothy/3. W e also have two simple rules. X.Onepossiblesolutionwouldbeasfollows: 1.Let’s shine a little more light on unification..October2010) . dorothy(X.Z):-X=lion. Letthecomputerdothework! Unification.Prologisaboutdescribingyourworldasitisandpresenting logicalproblemsthatyourcomputercantrytosolve.Y):-cat(X). Andyouwouldhavetowritethisprogramoverandover. Unification across two structures tries to make both structuresidentical.Atsomepoint. Collectandorganizeyourlogic.0printing. 3. Findallpossiblesolutions.Thelogicisridiculouslysimple—achild couldfigureitout. or make both sides the same.Y=tiger. 2.

yes Remember. 3. This case is pretty simple.Three).and Z to One.andmovesontothenextgoal.and Y isa cat. but cation is successful. unification means “Find the values that make both sides X.Prologbinds One to X and 1.Prologunifies X. let’s use the first rule.” On the right side. I’ll compile and then do a simple query withnoparameters: |?-dorothy(lion. One=lion Two=lion? twin_cats(X.and Three andthenreportstheresult.bear).Two).T T w o to Y. tiger. To solve these. 2. Y. and match. tiger. Prolog unifies X. These match the corresponding values on the left side. Prolog tries thefirstfact.binding X to lion. so unifiy e s . W e issuedthequery twin_cats(One.Two.October2010) . Prolog must start working through the goals. Prolog reports wecanspiceitupalittlebit.Try it: istrueifyoucanprovethat |?-twin_cats(One. Prolog binds bear. X and Y arebothcats.Y) Prolog reported the first example. One=lion Three=bear Two=tiger yes This example has one more layer of indirection. and Z to lion. Reporterratum thiscopyis (P1. cat(lion) and cat(tiger). T w o .tiger.let’sshifttothelastrule.0printing. Y.Thisrulesays Now. Let’s see w o ) . First. W e have two facts that match. In the goals.D AY 1: A N E XCELLENT D RIVER X isa cat. twin_cats/2.Try thisone: |?-dorothy(One.Unificationcanworkonbothsidesofthe implication.and Z to lion. howitgotthere: lion and lion are both cats. Y.and bear. Thefirstgoalis cat(X).W e 104 canusethisknowledgebasetoshedalittle lightonunification.Ontheleftside.

Sometimes. therestofthesolutionsbypressing Two=lion?a One=lion Two=tiger One=tiger Two=lion One=tiger Two=tiger (1ms)yes Notice that Prolog is working through the list of all combinations of and Y. thesamewayasthefirst. or we can get all of now step through solutions one by one by using a. you need more than one. AnInterviewwithBrianT a r b o x . Sometimes. only a description of the cake you’ll take out of the pan when you’re done. W e can . Bruce: DolphinResearcher CanyoutalkaboutyourexperienceslearningProlog? Brian: I learned Prolog back in the late 1980s when I was in graduate school at the University of Hawaii at Manoa. I was working at the KewaloBasinMarineMammalLaboratorydoingr e s e a r c hintothecognitive capabilities of bottlenosed dolphins. we have the first solution that makes the rules true.WhenIwaslearningProlog. In Prolog.choosing 5.Asyou’llseelater.sotheruleissuccessful. there’s not often a finely detailed step-by-step recipe.0printing. W e v ’e satisfiedbothgoals.October2010) .D AY 1: A N E XCELLENT D RIVER 105 4.ithelpedmetremendouslytointerviewsomeonewhohadusedthelanguageinpractice. Prolog now binds Y to cat(Y).That’senoughforday1. So. X ProloginPractice It has to be a little disconcerting to see a “program” presented in this way.ItalkedtoBrian Tarbox who used this logic language to create schedules for working withdolphinsforaresearchproject. Prolog can solve this goal in exactly lion. one solution is enough.. W e r ’e goingtodoalittlemoreheavyliftinginday2.Prologreports w o thatmadeitsuccessfulandreports thevaluesof One and T y e s .unificationalsoletsyoudosomesophisticated matchingbasedonthestructureofyourdata. At the time I noticed that much Reporterratum thiscopyis (P1. given the information available in the goals and corresponding facts.

or at least the tiny subset of it that we were doing r e s e a r c h on.0printing.”Languagesdon’tjustsay“no.Ibuiltasetoffactsdescribing each person’s skill set.October2010) .Ir e c a l one of my first experiments with Prolog. it can give you some pretty weird r e s u t l s . but I had never had a language talk back to me.Some roles. They asked me. If our executable model predicted Ake’s actual behavior. Y o u have to understand that r e s e a r c h dolphins are an incrediblylimitedr e s o u r c e . Every person had their own schedule and their own shift set of skills. the language would find an available person Reporterratum thiscopyis (P1. “Why would you want to change the value of a variable?” I mean. each person’s schedule. such as the actual dolphin trainer.butitwasunsettlingatthetime. but until you drink the Kool-Aid.undergraduates. Other roles such as data r e c o r d e r could be done by several people but still r e q u r i e d training. Many debates started with “Well.”Foreachtask listed in an experiment.” Idecidedthatmymaster’sthesiswouldbetotrytocreateanexecutable modelthatmatchedourbeliefsaboutAke’sunderstandingoftheworld. you understand that variables either have particular values or areunbound. or Ake for short.”Theymightgivethewrong answer or fail to compile. could be filled by only a few people.W ehadgraduatestudents.IcalledPrologsupportandsaidthatthelanguagehadsaid“no” when I tried to change the value of a variable. IdecidedtotrytobuildaProlog-basedschedulebuilder.Eachdolphinwasworkingondifferentexperiments. Finding a schedule that utilized everyone and made surealltasksweredonehadbecomeafull-timejobforoneofthestaff.Itturnedoutto beaproblemtailor-madeforthelanguage. and each experiment’s r e q u r i e m e n t s . what kind oflanguagewon’tletyouchangethevalueofavariable?Onceyougrok Prolog.andeachexperimentr e q u r i e dadifferentsetofpersonnel. Prolog is a wonderful language.So.D AY 1: A N E XCELLENT D RIVER 106 of the discussion at the lab concerned people’s theories about how the dolphins thought. W e worked primarily with a dolphin named Akeakamai. Bruce: HowhaveyouusedProlog? Brian: Idevelopedtwomainsystems:thedolphinsimulatorandalaboratory scheduler.IcouldthenbasicallytellProlog“makeitso. we would gain some confidenceinourtheoriesaboutherthinking. Ake probably seesthesituationlikethis. The lab would run four experiments a day with each of four dolphins.andEarthwatch volunteers. Most experiments r e q u r i e d a staff of six to adozenpeople. writing something along the lines of x = x + 1. Prolog r e sponded“no.

In the end. but the r e s e a r c h was proceeding well for a while.October2010) . This was a hard problem for Ake to solve.” and “not frisbee. Bruce: Are there some interesting examples of facts. Ake r e sponded to a gestural sign language containing “sentences” such as “hoop through” or “right ball tail-touch. you have solved the problem. At one point.Most trainers had forgotten about this word because it was rarely used. if you can describe the problem. W e didn’t understand it all.”Inthis context.” It was also a successful r e s p o n s e to “not hoop.” W e would give her instructions. If it could not findavalidbinding. but obviously we could not r e m o v e the window. how about inserting one and seeing whether that fixes it? Reporterratum thiscopyis (P1.wepresentedthetrainingtasktothesimulateddolphinandgotaninterestingr e s u t l . rules. Partofmyr e s e a r c hwastotrytoteachnewwordssuchas“not. however.W ehadgiven the simulated dolphin the same heuristic. In most languages I’ve found myself arguing with the computer at some point saying. It turns out that whenAkewassinkingtothebottomofthetankshewaspositionednext tothewindow.Itwouldcontinueuntiliteither satisfied the needs of the experiment or was unable to.0printing. The simulated dolphin discovered the rule that “window” was a successful r e s p o n s e to “not ball. just do it!” C and C++ compiler errorssuchas“semicolonexpected”aresymbolicofthis.thoughIcouldnotseethewindow! Bruce: WhatdoyoulikeaboutPrologthemost? Brian: The declarative programming model is very appealing.” “not pipe. it would either find a valid scheduleordeclarethattheexperimentwasover-constrained. or assertionsr e a lt e dtodolphinsthatwouldmakesensetoourr e a d e r s ? Brian: There was one particular situation I r e m e m b e r where the simulated dolphin helped us understand Ake’s actual behavior.Ifyouexpected a semicolon.itwouldstartundoingpreviousbindingsandtrying again with another combination. In general. This canbeaveryfrustratingsituationbecauseyoucan’taskadolphinwhy itdidsomething. andshewouldr e s p o n d .D AY 1: A N E XCELLENT D RIVER 107 withthatskillandbindthemtothetask. “touch not ball” meant touch anything but the ball.So. she started simply sinking underwater whenever we gave her the instruction.” W e had guarded against this pattern with theotherobjectsbychangingthesetofobjectsinthetankforanygiven trial. “You know what I mean. It turns out that Ake’s gesturallanguageincludeda“word”foroneofthewindowsinthetank.they willgenerallytrytofindthesimplestanswertoaproblem.Althoughdolphinsareverysmart.

Bruce: Whatgaveyouthemosttrouble? Brian: Prolog seemed to be an all-or-nothing approach to problems. and Prolog would tell us whether the facts were true or false. After we built a few knowledge bases. Second. only pure logic. And the language for the description of the problem is logic. In the laboratory scheduling problem.aswellasstrategiestoiterateoverlists.Thequerieshadtwoforms. Y o u don’t have to describe the solution to a problem.First. Y o u have only to describe the problem.allIhadtodointheschedulingproblemwasbasicallysay. WhatW eLearnedinDay1 Today. Reporterratum thiscopyis (P1. we learned the basic building blocks of the Prolog language.” “No” in this casemeantthatwehadover-constrainedtheday. we encoded knowledge using pure logic.thequerycouldspecifyafact. What you see here is an extremely powerful concept. however.Foranyclause. W e put our logic into knowledge basesandissuedqueriesagainstthem.we’regoingtomakemorecomplexinferences. W e r ’ealsogoingtolearntousemathandmorecomplexdatastructures suchaslists. the system would churn for 30 minutes and then either give us a beautiful schedule for the day or simply print “no. Prolog then computed all possibilitiesthatmadethosefactstrue.Prologtriedtosatisfyeachof the goals by going through the possible combinations of variables.0printing. Inthesectionstocome. give us a partial solution or much of any informationaboutwheretheover-constraintwas. or at least to the problems I was working on. Rather than encoding steps to guide Prolog to a solution. and let Prolog do the rest. we then compiled and queried them.“I wantadaythatlookslikethis. Prolog did the hard work of weaving that knowledge together to find solutions.D AY 1: A N E XCELLENT D RIVER 108 InProlog. Start from facts and inferences.sogomakemeone”anditwoulddoit. Schedules andbehaviorpatternsaregreatexamplesofproblemsrightinProlog’s wheelhouse.andtherewasnofull solution. W e learned that Prolog worked through rules by going through the clausesforaruleinorder. It did not. Prolog programs are at a higher level of abstraction. we built a query with one or more variables.October2010) . All Prologprogramsworkthisway.

Itexpressestheextensivefamily treeoftheW a t l o n s . 4. Recursion RubyandIowereimperativeprogramminglanguages. • Makeaknowledgebaserepresentingmusiciansandinstruments. Now.0printing.Likemostautistics. W e l’ look at recursion and use it to solve some problems with basic inferences. there are definitely “fifteen minutes to W a p n e r . you might be one of the lucky readerswhohaseverythingclickforthemrightaway. or great Reporterratum thiscopyis (P1. Represent some of your favorite booksandauthors.Prologisthefirstofthedeclarativelanguageswe’lllookat.andlists.Asyou’replowingthroughthisenigmaticlanguage. charactersina1963movieandsubsequentseries.butifyoudon’t.3 Day2:FifteenMinutestoW a p n e r Grumpy Judge W a p n e r from The People’s Court is an obsession of the centralcharacterin RainMan . Today.D AY 2: F IFTEEN M INUTES TO WAPNER 109 Day1Self-Study Find: • SomefreePrologtutorials • Asupportforum(thereareseveral) • OneonlinereferenceforthePrologversionyou’reusing Do: • Make a simple knowledge base. Alsorepresentmusiciansandtheirgenreofmusic. W e will need a few more tools in the toolbox.HelatchedontoJudgeW a p n e rand ThePeople’s Court. ” Sit tight.math. you’ll often use recursion rather than iteration.Y o uwouldspell outeachstepofanalgorithm. • Findallmusicianswhoplaytheguitar. Itexpressesafatherrelationshipandfromthatinferstheancestorrelationship. Y o u l’learn to use recursion.Let’sgetgoing.Raymondobsesses overallthingsfamiliar.youmightbe ready for things to start to click.andthenwe’llapplythesametechniquetolistsandmath. take heart. • Findallbooksinyourknowledgebasewrittenbyoneauthor.October2010) . Since an ancestor can mean a father.Whenyou’redealingwithcollectionsofthingssuch as lists or trees. Takealookatthefollowingdatabase. grandfather.

Y):father(X.Think and conditions and the periods of the commas between subgoals as X isthe ancestor betweenclausesas or conditions.Y):father(X.Inthiscase.D AY 2: F IFTEEN M INUTES TO WAPNER 110 grandfather.john_boy_jr).Whenyouhavemultipleclausesthatmake uparule.Y).Therule ancestor/2 hastwoclauses. john_boy_sr is an ancestor of john_boy_jr.wecantryvariablesin Reporterratum thiscopyis (P1. One clause in the ancestor clausewilluse ancestor. This first clausedependsonafact. ancestor(X.Y) isarecursive subgoal. zeb isanancestorof aquery.ancestor(Z. father(john_boy_sr.Thefirstclausesays“ ft h e r of Y if X isthe a of Y. we will need to nest the rules or iterate.”That’sastraightforwardrelationship.likethis: |?-ancestor(zeb. Who=john_boy_sr?a Who=john_boy_jr no john_boy_jr.Asalways. ancestor(Z.0printing.Z). a ft h e r isthecoresetoffactsthatenablesourrecursivesubgoal.Y):-a ft h e r ( X .john_boy_jr). Thesecondclauseismorecomplex: Y). Since we’re dealing with a declarative language. of Z andwecanalsoprovethatsame Whew. true? no Prolog reports true. true? Y e s . we’re going to nest.Let’susethesecondclause: |?-ancestor(zeb.john_boy_jr).W e can trythatrulelikethis: |?-ancestor(john_boy_sr. ancestor(X. This clause says X is an ancestor of Y if we can prove that X is the a ft h e r Z isan ancestor of Y.Who).onlyoneofthemmustbetruefortheruletobetrue.Y).ancestor(Z.Z).pl father(zeb. john_boy_sr). ancestor(X.Here’stheknowledgebase: Download prolog/family.October2010) .

P a r t2 Remember.3 ] ListsandtuplesareabigpartofProlog. Unification. and you can eventuallyrunout.3). ListsandT u p e ls [1.becausewecanusethisruleinourknowledge basefortwopurposes. Our call is tail recursive because the recursive subgoal.youneedtobecareful because each recursive subgoal will use stack space. yes |?-(1.2.0printing. Let’s take a look atacoupleofexamples: |?-(1. no Reporterratum thiscopyis (P1.4).tofindbothancestorsanddescendants.2. it tries to make both the left and right sides match.Listsarecontainersofvariablelength.3. keeping the memory use constant.2.Y o ucanspecifyalistas andatupleas (1.andtuples arecontainerswithafixedlength.October2010) . The That’sabeautifulthing. Y) . Abriefwarning. W t i h that last bit of housekeeping out of the way. Two tuples can match if they have the same number of elements and each element unifies. Who=john_boy_sr?a Who=zeb (1ms)no john_boy_jr and john_boy_sr.3) .2. isthelastgoalintherecursiverule. let’s start to look at listsandtuples.D AY 2: F IFTEEN M INUTES TO WAPNER 111 And we see that zeb is an ancestor for ancestor predicatealsoworksinreverse: |?-ancestor(Who.3)=(1. when Prolog tries to unify variables.3)=(1.you’llknowit’stimetolookforawayto optimizewithtailrecursion. If you can position the e c u r s o in optimization recursive subgoal at the end of a recursive rule. Prolog can optimize the call to discard the call stack.2.Whenyouuserecursivesubgoals. ancestor(Z.john_boy_jr).Bothlistsandtuplesgetmuchmore powerfulwhenyouthinkofthemintermsofunification.Declarativelanguagesoftensolvethisproblemwith a technique called tail r .WhenyourPrologprogramscrash byrunningoutofstackspace.2.

2. A=1 B=2 C=3 yes |?-(A. for some lists.2.C)=(1.Z].D AY 2: F IFTEEN M INUTES TO WAPNER |?-(1.1).2.thesecondtuplesdidnothavethesamenumberofelements.3]=[X. X=2 Z=3 yes Reporterratum thiscopyis (P1. They can work liketuples: |?-[1. Let’smixinsomevariables: |?-(A.3).3].B.2.October2010) . X=1 Y=2 Z=3 yes |?-[2.0printing.Y.B. and the third set did not have the same elements in the same order. A=1 B=2 C=3 yes It doesn’t really matter which sides the variables are on.2. Now.3).3]=[X.2.X. A=1 B=2 C=3 yes |?-(1.C).3)=(A. They unify if Prolog can make them the same.2.2. yes |?-[1.3]=[1.C)=(1.3)=(3.Z].2. The first tuples were exact matches. no 112 Two tuples unify if all the elements unify.B.

X.c]=[a|[Head|Tail]]. X.3]=[X.0printing.and bindtotherest.c]=[Head|Tail]. Lists have a capability that tuples don’t.likethis: |?-[a. Tail=[b. 2. 113 Thelasttwoexamplesareinteresting.October2010) .butaone-elementlistisfine: [Head|T |?-[]=[Head|Tail]. [X. When you unify a list with Y o u can deconstruct lists with [Head|T T a li will thisconstruct. Head=a Tail=[b.b. Head willbindtothefirstelementofthelist. 3 ] = [X.2.c]=[a|Tail]. [1. a li ]. Head=b Tail=[c] yes T a li .Z ] and [2.c] yes a li ] won’tunifywithanemptylist.3 ] unifiedbecause X = 2 .2.b.Orwecansplitthis Reporterratum thiscopyis (P1. Head=a Tail=[] yes Y o ucangetcomplicatedbyusingvariouscombinations: |?-[a.X.b.Z]. Z ] did not Prolog could make them the same with unify because we used X for both the first and second positions. no |?-[a]=[Head|Tail]. no |?-[]=[].D AY 2: F IFTEEN M INUTES TO WAPNER |?-[1. and those values were different.c] (1ms)yes Prologmatchedthe a andunifiedtherestwith tailintotheheadandtail: |?-[a.

”W etoldPrologtoskipthefirsttwoelementsand Head will grab the third element. These are examples to do counting.b.D AY 2: F IFTEEN M INUTES TO WAPNER 114 Orgrabthethirdelement: |?-[a.AverageisSum/Count.Itbasicallymeans“Idon’tcare what’sinthisposition. Thatshouldbeenoughtogetyoustarted.CountisTailCount+1. because the list is not empty.[]). ListsandMath Inournextexample.Let’stalkabouthowthisworks. step-by-step: •W e issuethequery count(What.[1]).TotalisHead+Sum.Tail). The andthetrailing _ willgrabthetail. no count.List).Fiverulesdoallthehardwork.ignoringtherestofthelist.Unificationisapowerfultool.0printing. average(Average.Thecount Therulesaretriviallysimple._|[Head|_]].count(Count. Thesimplestexampleis |?-count(What.October2010) .List).W e r ’e nowreadytocombinethese elementswithrulesandassertionstodosomebasicmathwithlogic. W e move on to satisfying the Reporterratum thiscopyis (P1. andusingitinconjunctionwithlistsandtuplesisevenmorepowerful.List):-sum(Sum. sum(Total. Download prolog/list_math.youshouldhaveabasicunderstandingofthecoredatastructures inPrologandhowunificationworks. [1]). What=1?.andaverages.Tail).[Head|Tail]):-sum(Sum. Now.whichcan’tunifywiththefirst rule.IthoughtI’dshowyouanexampleofusingrecursion and math to operate on lists.pl count(0.Thecountofanemptylistis ofalististhecountofthetailplusone.[Head|Tail]):-count(TailCount. Head=c yes _ isawildcardandunifieswithanything.e]=[_.[]). sum(0.d. sums.Useitlikethis: 0.c. count(Count. split the rest into head and tail.

W e canunifyvariables.TotalisHead+Sum. W e haven’t really told Prolog howtocomputesums.thefirstgoalis etrytoprove that subgoal.sowebind +1. no sum worksexactlyasyouwouldexpectin Ifyoulookatitimperatively.and T 115 unify.W • Afterunification. W e defined logical rules.[1. Count to 0+1 . That binds T a C li o u n t to 0. Thiscodeworkspreciselylikethecountrule.or 1.sowecanmoveonto thesecondgoal. a C li o u n t • Now. e a li to [ ].Forexample.0printing. Here’s the codeforthoserulesagain: sum(0. Similarly.Thefirstruleisnowsatisfied. the logic engine must satisfy some subgoals. The next example is adding up the elements of a list.List ).count(Count . W e did not define a recursive process.andthesumofalistis T o t a l .W e v ’emerelydescribedsumsasrulesandgoals. [ ]). T a li And that’s it.[ Head|Tail]):-sum( Sum.List ). sum(Total.weevaluate CountisT Count isboundto0. The sum of an empty list is zero. ing What to Count. restisthe Head plusthe sum ofthe T But there’s another interpretation here.Thedeclarativeinterpretationisasfollows:“Thesumofanempty T o t a l ifwecanprovethatthesumof listiszero.[]). the Head plusthe count ofthe T count ofalistisonefor Aswithlogic.Theusageissimilar: |?-sum(What. What=6?.Tail ). bind- count(TailCount.the average of List is A v e r a g e • the sum ofthat List is Sum. we unify with the first rule.thecountofanemptylistiszero.a basecaseandtherecursivecase.the a li .Italsohastwoclauses.3]). W goals for the second rule.youcan use sum and count togethertocomputeanaverage: average(Average. So. To satisfy some of the goals.D AY 2: F IFTEEN M INUTES TO WAPNER count(Count.AverageisSum/ Count. [Head|T a li ]).List ):-sum( Sum. a recursive language. ifyoucanprovethat Reporterratum thiscopyis (P1.theserulescanbuildoneachother.”W thetailplustheheadis e r ’ereplacingrecursionwiththenotion ofprovinggoalsandsubgoals. Head to 1. the sum of the a li .2.October2010) . This time.

One=[] Two=[apples.[bubbles].[oil.slick]).2.I’mgoingtoshiftgearsalittlebitandtalkaboutatightlittle rulecalled append. no UsingRulesinBothDirections Atthispoint.Who.bananas]?a One=[apples] Reporterratum thiscopyis (P1.What). Y o u differentways.D AY 2: F IFTEEN M INUTES TO WAPNER 116 • the count ofthat List is Count. no can use it in many It’salistbuilder: |?-append([tiny].[water].It’saliedetector: |?-append([oil]. What=2.oranges.and v e r a g e • A is Sum/Count.List2.[dessert_topping.bubbles] yes Itdoeslistsubtraction: |?-append([dessert_topping].oranges.Therule append(List1.[apples.List3) istrueif List3 is List1 + List2.[1. Who=[floor_wax] yes Anditcomputespossiblepermutations: |?-append(One.Two. That short little bit of code packs a punch.water]).0printing.[oil.0?.bananas]).It’sapowerfulrulethatyoucanuseinavarietyofways. What=[tiny.youshouldhaveafairlygoodunderstandingofhowrecursionworks.3]).October2010) .floor_wax]). Anditworksjustasyou’dexpect: |?-average(What.[water]. yes |?-append([oil].

we break List1 into the head and tail.bananas] One=[apples. No problem.List2. concatenate([Head|[]]. List1 onto 2. Our first step is to concatenate an empty list to That’safairlyeasyruletowrite: Download prolog/concat_step_1.oranges. concatenate is true if the first parameter is a list and the nexttwoparametersarethesame.[harry].oranges] Two=[bananas] One=[apples.pl List1. Itworks: |?-concatenate([]. Let’s rewrite concatenate.Let’saddarulethatconcatenatesthefirstelement of List1 tothefrontof List2: Download prolog/concat_step_2.List. List2.bananas] Two=[] (1ms)no 117 So.What).List). Let’s find out exactly how much.D AY 2: F IFTEEN M INUTES TO WAPNER Two=[oranges. Y o u may think that building such a rule will take a lot of code. List3) . For concatenate(List1. Seewhatwecangeneralize. 4. W the Prolog append. Addarulethatconcatenatesoneitemfrom 3.[Head|List]).List). concatenate([].October2010) .List. Let’s get started. List1 onto List2.List3) thatcanconcatenate List1. W e l’ break our third element into Reporterratum thiscopyis (P1. with the tail being an empty list. What=[harry] yes Ontothenextstep. but we’ll call it e l’ take it in several steps: 1.pl concatenate([]. Add a rule that concatenates two and three items from List2. one rule gives you four. W r t i earulecalled anemptylistto concatenate(List1.List.0printing.

List. Reporterratum thiscopyis (P1.0printing.List). Remember to the head and tail. concatenate([Head|Tail1].List.[Head|Tail2]):concatenate(Tail1.granger].List.Tail2).[potter].D AY 2: F IFTEEN M INUTES TO WAPNER List1’s head and List2 as the tail. using compileyourknowledgebase.Itworksjustfine: |?-concatenate([malfoy]. concatenate([1.Head2|List]).[Head1.Theyworkinthesameway: Download prolog/concat_step_3.List. Thatterselittleblockofcodehasanincrediblysimpleexplanation. we’ll have a differentcopyofthevariables. The second stays constant. What=[malfoy.List.pl concatenate lists of concatenate([].List.What). concatenate([Head|[]]. first clause says concatenating an empty list to List1 to List2 gives you List3 if the The second clause says concatenating heads of List1 and List3 are the same.pl concatenate([]. what we have is a base case and a strategy where each subgoal shrinks the first list and grows the third.List). and you can prove that concateList3.[Head|List]).I’llshowwhathappens whenPrologtriestoprovethenextsubgoal. 2 ].[potter]. Keep in mind that we’re nesting the rules. The simplicity nating the tail of List1 with List2 gives you the tail of andeleganceofthissolutionareatestamenttothepowerofProlog. What) .potter] yes So.Head2.W t i heachpass. so each time we try to prove a subgoal.[Head1.Here’stheconcatenateusingnestedrules: Download prolog/concat.October2010) .Head3|List]). |?-concatenate([malfoy. concatenate([Head1|[Head2|[Head3|[]]]]. [3]. concatenate([Head1|[Head2|[]]].granger. we can define another couple of rules to lengths2and3. W e nowhaveenoughinformationtogeneralizearesult.potter] yes 118 Now. What=[malfoy.The List gives you that List.List. Let’s see what it would do with the query W e l’ walk through unification at each step.What).I’llmarktheimportantoneswithaletter soyoucankeepthemstraight.

is [3].That’sgoingto concatenate([2].because unifytothis: concatenate([1|[2]]. [3]. Now. we know T is [3]. we described logical rules instead of algorithms and let Prologworkitswaythroughthesolution.October2010) . [3].T :-concatenate( [ ].W e tookadeeperlookatPrologunificationandhowProlog :. W e also nested rules. W e learned to use basic arithmetic and nested subgoalstocomputesumsandaverages. inal T a 2 liC ) • concatenate([ ].or =. [3]. plugging in at each step.T a 2 liB a 2 liA Noticethat T isthetailof T . [3]. Now.D AY 2: F IFTEEN M INUTES TO WAPNER 119 • Startwiththis: concatenate([1. we can work back up the chain.2 ] isnotanemptylist.3 ]. T a 2 liC a 2 li2 a 2 li ] is [1. T a 2 li Let’s look at the third parameter. you’ve taken a deep look at one of the richest functions in Prolog. [3]) .Butnow. [1|T a 2 liA e [1. and make sure you understandthem.3 ]. W works to match up both sides of a e saw that when we’re writing rules.whichmeans [2|T ] is[2. a 2 liC • So.3]. WhatW eLearnedinDay2 In this section. [3]. Reporterratum thiscopyis (P1. Go over this list until you understand it.Let’sunifytherightside. Unifying nested subgoals is a core concept for the advancedproblemsinthisbook.What) • Thefirstruledoesn’tapply. [3].0printing. W e goals.andfinally [1 |T 2.2.It’snotthesameastheoriga 2 li . we moved into the basic building blocks that Prolog uses to organize data: lists and tuples. [T Everything unifies but the second tail. W e also used math.wehavetounifytherightsideagain. What is [1. [3].2 ]. allowing us to express problems that you might handle with iteration in other languages. [T a 2 liA concatenate([2|[ ]]. •W e trytoapplytherule giveusthis: now move on to the ]). [2|T a 2 liB a 2 liB ) ]):-concatenate( [ ]. [3].W ]) a 2 liA ]):-concatenate( [2]. Take a little time to explore these solutions. Prolog is doing a lot of work for you here.

• Findthesmallestelementofalist.Codingtheexamplesinthischapter was equal parts maddening and exhilarating. What problems are they solvingwithittoday? If you’re looking for something more advanced to sink your teeth into.October2010) . for Prolog. but more importantly. W e used this technique to recursively iterate through lists. Day2Self-Study Find: • Some implementations of a Fibonacci series and factorials.D AY 3: B LOWING U P V EGAS 120 Finally. W e r ’e going to solve two famouspuzzlesthatarerightinProlog’scomfortzone.solvingsystems withconstraints. Thesebuildingblockswillserveasthefoundationsofthecomplexproblemswesolveinday3. 4. we learned to use lists. Raymond and his brother went to V e g a s and just about broke the bank. W e matched one or more variables within a list to variables. trytheseproblems: • AnimplementationoftheTowersofHanoi. the autistic savant. Though it’s sometimes difficult to understand. it’s amazing to think of programming in this way. you’re going to see a side of Prologthatwillleaveyousmiling.Howdoesitwork? • Whataresomeoftheproblemsofdealingwith“not”expressions? WhydoyouhavetobecarefulwithnegationinProlog? Do: • Reversetheelementsofalist.0printing. In this section.4 Day3:BlowingUpV egas Y o ushouldbegettingabetterunderstandingofwhyIpickedtheRain Man. How dotheywork? • A real-world community using Prolog. • Sorttheelementsofalist. we matched the head a li ] ofalistandtheremainingelementswithvariablesusingthe [Head|T pattern. One of my favorite points in Rain Man was when Ray’s brother realized he could count cards. Reporterratum thiscopyis (P1.

2.Thesearetherules: • Forasolvedpuzzle. W e r ’e going to start with a four-by-four Sudoku.D AY 3: B LOWING U P V EGAS 121 Y o u may want to take a shot at some of these puzzles yourself.Prologwillprovidethesolution. Each cell in the grid has a number. Solution). try describing the rules you know about each game rather than showingPrologastep-by-stepsolution._. If you do. and square has one each of all of thedigits.we’llmoveontotheclassicEightQueenspuzzle.Imerelyneedtoprovidetherulesforthe game. The concepts are exactly the same. with some spaces filled in and some blank.0printing. That’s simple sodoku(Puzzle.W e r ’egoingtostartwithasmall Sudoku and then give you a chance to build up to a larger one in the dailyexercises. SolvingSudoku CodingtheSudokuwasalmostmagicalforme. from 1–9 for a nine-by-nine square.we’llhaveaboardwith four rows.likethis: sodoku([_.October2010) . and boxes. four columns.4.W t i hProlog. Y o u r job is to fill out the solution so that each row.WhenIsolvedthis puzzleinRuby._. enough._.Then. Ifasolutionexists. A typical puzzle is a nine-by-ninegrid._. W e l’ have a puzzle and a solution.that’snotso. though the solutions will be shorter.thenumbersinthepuzzleandsolutionshould bethesame. column. of the form Solution). Reporterratum thiscopyis (P1. substituting underscoresforunknownnumbers._]. _._. Our users can provide a puzzle as a list.Ihadtoworryaboutthealgorithmforsolvingthepuzzle.Abstractly. and four squares. 3.asweknowit._. columns. _.withvaluesfrom1–4.3._.ASudokuisagridthat has rows. • ASudokuboardisagridofsixteencells. Let’s start by describingtheworld._. The table shows squares 1–4: 1 1 3 3 1 1 3 3 2 2 4 4 2 2 4 4 The first task is to decide what the query will look like.] yes getting Now. we have to limit the board to sixteen elements. Solution=[1. 2.First.4.andsquare hasnorepeatedelements.4. Second. values for each cell.4. 3. |?-sudoku([1.Thisproblemwillimpactusintwoways.1.3.soPrologwillnotbeabletoguesswhatthevaluesare.8.0.3. The numbers in the solution and puzzle should match: Download prolog/sudoku4_step_1. the set of results is not Thatmeansthatwehavenotexpressedrulesthatlimitpossiblevalues ofeachcell.6.Solution):Solution=Puzzle.3.Solution).1. W e haveanotherproblem.2].pl sudoku(Puzzle. but the intent is clear enough.5. • Apuzzleisvalidiftheelementsineachrow.0.itshouldhavenumbersfrom1–4.too.6].9.1. Solution=[] yes Forasolutiontobevalid.Solution).3. Let’s start at the top.8.1.3.D AY 3: B LOWING U P V EGAS 122 • Theboardhasfourrows.4.Solution).2.wemayallowsomeinvalidsolutions. W e v ’e actuallymadesomeprogress. W e r ’e sixteennumbersback.4.3.3. Solution=[4.andfoursquares. Clearly.2. but our solver reports that there is a valid solution.2] yes The format isn’t pretty.4.4.column.3.rowbyrow.9.5.October2010) .Our“Sudokusolver”worksforthe casewheretherearenoblanks: |?-sudoku([ Prolog doesn’t haveenoughinformation to test possible grounded.2.4. In other words. Reporterratum thiscopyis (P1.Thevaluesinthecellscanbeanything: |?-sudoku([1.3]. this board isn’t valid.

columns.5.October2010) .Now. Row4=[S41.andsquares. with values from 1–4.8.andsquares.S12. and we limited the domainofthecellstovaluesfrom1–4.Solution):Solution=Puzzle. S31. Row2=[S21. W e just need to make sureallvaluesin Puzzle rangefrom1–4.7.S32.9.6.S43.0printing.4).S33.S24.0.UpperBound) .4.Solution).D AY 3: B LOWING U P V EGAS 123 Let’s solve these problems by solving the next rule to the game.S23.5.2.Solution). Reporterratum thiscopyis (P1.S43.S23.S32.S44]. Row3=[S31. no |?-sudoku([1. hasabuilt-inpredicatetoexpresspossiblevalues.youcanseewhywenamed the cells the way we did.S13.S12. Download prolog/sudoku4_step_2.S22. fd_domain(Puzzle.2. we get to the main piece of the solution.S42.S14]. Rule 3 says a board consistsofrows.S42.S22. W e unified Puzzle with a list of sixteen variables.4.Thispredicateistrueifallthevaluesin List are between LowerBound and UpperBound. S21.columns.3]. inclusive.3.6].S34.2. GNU Prolog fd_domain(List.S14. It’s a straightforward process to describe the rows: Row1=[S11.called LowerBound.S24]. S41.S13. Rule 2 says a board has sixteen cells.S34].1.S44]. no Now. Puzzle=[S11.S33.pl sudoku(Puzzle.3.wefailifthepuzzleisnot valid: |?-sudoku([1.Now.W e r ’e goingtocarvethepuzzle upintorows.1.

Row3.3.Row2.columns.S41.2.andsquares arevalid.S24].S43.1._. Now that we’ve chopped the board into pieces. we can move on to the nextrule.2] yes Reporterratum thiscopyis (P1._.3.andsquareshaveno repeatedelements.3.3.Col2. _.2.Row4.S14. 3. Square2=[S13. Believe it or not._._.S41].columns. Andsquares: Square1=[S11. Col3=[S13.S24.W e l’ useasimpleruletoaccomplishthis: valid([]).S43].Col4.1.S42].S34. fd_all_different(List) succeedsifalltheelementsin ent.1. Col4=[S14.2. Allthatremainsistoinvokeour v a d il ( L s it ) rule: valid([Row1.S23.S32.S21.4.S23.Theboardisvalidifallrows.S12.Col3._]. This solution can solve a four-by-four Sudoku: |?-sudoku([_. _.3.4.D AY 3: B LOWING U P V EGAS 124 Likewiseforcolumns: Col1=[S11. Square3=[S31.S22]._.S31. valid([Head|Tail]):fd_all_different(Head).S21.S44].W e l’useaGNUPrologpredicatetotestforrepeated List aredifferelements. This predicate is valid if all the lists in it are different. Col1. we’re done._. Col2=[S12. Square1.S33.S42]. valid(Tail).October2010) .S32. Square4=[S33. Solution=[4.S22. The second clause says that a list is valid if the first element’s items are all different and if the rest of the listisvalid.W e needtobuildaruletotestthatallrows.Square2.S34.Square4])._._.0printing.S44].4.4. The first clause says that an empty list is valid.2. Solution).Square3.1.

S44].D AY 3: B LOWING U P V EGAS 125 Breakingthatintoafriendlierform. Col3=[S13. Col4=[S14.Square3.S23. fd_domain(Solution.S12.S43.thisexampleshouldgiveyoua nudgeintherightdirection.S22.Col2.S33.S34].S44].S12.S32.S33. Square1. Row4=[S41.S14. valid(Tail).Solution):Solution=Puzzle.wehavethesolution: 4 2 1 3 1 3 2 4 2 4 3 1 3 1 4 2 Here’sthecompletedprogram.S42].October2010) .Where’stheprogram?W e .S34.Square4]).4).S33.S44].Square2.S13. columns.S41.S23.S41].S43].beginningtoend: Download prolog/sudoku4. Square1=[S11.S34.S24]. Row1=[S11.S24.S32.S21.S14.S32.S42. and none of the rows.S23.0printing.S42].S43. The puzzle took a few dozen lines of Reporterratum thiscopyis (P1.S31. sudoku(Puzzle.S42. Row2=[S21. Col1. Col1=[S11.S24].S21. l wedidn’twrite a program.S14].S23. Puzzle=[S11. valid([Head|Tail]):fd_all_different(Head). S31. valid([Row1.pl valid([]).S32. Square4=[S33. S41.Col3.S22.S22. S21.1.Col4.S43. W e described the rules of the game: a board has sixteen cells with digits from 1–4. Col2=[S12.S44]. or squares should repeat any of the values. Square3=[S31. Square2=[S13.S13. Row3=[S31.S22].Row2.S12.S34.S24.Row4.Row3. Ifyouhaven’thadyourPrologmoment.

Reporterratum thiscopyis (P1.Let’slookathowwecansolvethisoneinProlog. Let’s look at another puzzle involving highly constrained resources:theEightQueensproblem.W ecanexpresseach Board isalist queenas (Row. • Notwoqueenscansharethesamerow.1).onthefollowing page. This puzzle is a great example of the types of problems Prolog solves well. Let’slookatthegoalsweneedtosatisfytosolvethepuzzle. In thedailyexercises..Eachqueenisontwodiagonals. It may appear to be a trivial problem on the surface.anddiagonals as constrained resources.onerunningfromthelower left (northwest) to the upper right (southeast) and the other running fromtheupperlefttothelowerrightasinFigure4. First.2. Our querywilllooklikethis: eight_queens([(1.. • No two queens can share the same diagonal (southwest to northeast). None can share the same row.atuplehavingarowandacolumn.October2010) . • Notwoqueenscansharethesamecolumn. eight_queens(Board) succeeds if we have a valid board.Iwon’tshowthefullsolutionuntillaterinthechapter.2). Our industry is full of problems that solve constrainedsystems..(3. Butonanotherlevel.justlookat thesegoals.D AY 3: B LOWING U P V EGAS 126 code to solve and no knowledge of any Sudoku solving strategies.columns.Col) .]).youcanlookattherows. you put eight queens on a chess board. It’s just a kid’s game. or diagonal. • No two queens can share the same diagonal (northwest to southeast). EightQueens To solve the Eight Queens problem.It won’tbetoodifficult. column.we’lllookatwhatthequeryshouldlooklike.butwemustbemorecarefulwith diagonals. • Aboardhaseightqueens.Ifyouwant totakeashotatthisgamewithoutlookingatthesolution.A of tuples. W e have a set of constraints that are easy to express but hard to solve.Buttheserulesshouldberelativelyeasytoencode.0printing.you’llgetthechancetosolveanine-rowSudoku. • Eachqueenhasarowfrom1–8andacolumnfrom1–8. Rowsandcolumnsmustbeunique.

Range).then: eight_queens(List):-length(List .8).we’llbuildaruletocheckwhetherthewholeboardismadeupof validqueens: valid_board([]). That’s easy enough to do. W e can use the count predicate you saw earlier in the book.6.Range).we’ll startatthetopofthelist.5. I’m going to walk you through the goals we’ll need to solvethewholeproblem.2.7.2:EightQueensrules Onceagain.Here’sthefirstgoal.0printing. or we length. rather than show you each goal in action. member(Row.member(Col. valid_board([Head|Tail]):-valid_queen(Head).Aboardhaseightqueens. al on ag Di 1 Row build Reporterratum thiscopyis (P1.W e aruletotestwhetheraqueenisvalid: valid_queen((Row.October2010) . it tests for membership. length(List.Col)):Range=[1.valid_board(Tail).4.3. N) can simply use a built-in Prolog predicate called succeeds if List has N elements. Di ag on al 2 The predicate member does just what you think.Aqueenisvalidifboththerowandcolumnareintegersfrom1–8. That means our list must have a size of eight.D AY 3: B LOWING U P V EGAS 127 Column Row C Figure4. This time. Next.8].weneedtomakesureeachqueenfromourlistisvalid. Next.

Col)|QueensTail].walkthroughit withafewtestlists. the next rule is that two queens can’t share the same row. rows([(Row. we’re going to need a little help.Ifnorthandwest are 1.Theeasiestwaytonumber themistodosomesimplesubtractionandaddition._)|QueensTail].October2010) .anddiagonals?Firstupisrows.[]). andaboardisvalidifthefirstitemisavalid queenandtherestoftheboardisvalid.Luckily. cols([(_.Ifit’sconfusingtoyou. r o w s ( Q u e e n s .[]).Rows) isanemptylist.columnsworksexactlythesameway. W e will break down the program into pieces that can help us describe the problem:whataretherows. To solve the next few constraints. diags2(QueensTail. but we match the second The logic works exactly the same as elementofaqueentupleinsteadofthefirst.and is Rows ifthe Row fromthefirst Rows and if r o w s of the queen in the list matches the first element of tailof Queens isthetailof Rows. diags1(QueensTail.[]). we’re going to assign the diagonals that run from northwest to southeast a value of Col – Row.0printing.columns.we’llgrabthesoutheasttonorthwestlikethis: diags2([]. Moving on.Thisfunctionshouldbe trueif Rows isthelistof Row elementsfromallthequeens.[Diagonal|DiagonalsTail]):DiagonalisCol+Row. diags1([(Row.[Diagonal|DiagonalsTail]):DiagonalisCol-Row. but we had one more constraint: Diagonal is Col -.Col)|QueensTail].DiagonalsTail). r o w s . o w s ( Q u e e n s .butnotmuch. Note that this is not unification! It’s an is predicate.RowsTail).D AY 3: B LOWING U P V EGAS 128 Anemptyboardisvalid.we’regoingtonumberdiagonals.but we’regoingtousecolumnsinsteadofrows: cols([]. This is the predicate that grabs those diagonals: diags1([].DiagonalsTail).Row . r o w s foranemptylist Thisonetakesalittleimagination. That rule worked just like rows and cols. rows([]. diags2([(Row.[Row|RowsTail]):rows(QueensTail. Movingon.Rows) W e l’ buildafunctioncalled r .[Col|ColsTail]):cols(QueensTail.ColsTail). and it will make sure that the solution is fully grounded.Col)|QueensTail]. Reporterratum thiscopyis (P1.[]). Finally.

fd_all_different(Cols). valid_board([Head|Tail]):-valid_queen(Head).2. diags2([]. diags1(Board.4. fd_all_different(Diags1). eight_queens(Board):length(Board.[]). fd_all_different(Rows).anddiagonalsarealldifferent. valid_board(Board). diags2(Board.6.[]).valid_board(Tail).[Col|ColsTail]):cols(QueensTail.here’stheentiresolution.Range). columns. rows([]._)|QueensTail].Diags2).Col)|QueensTail].Thetestsfor rowsandcolumnsarethelasteightclauses.[]).Col)):Range=[1.Diags1). diags1([(Row.ColsTail).DiagonalsTail).7. but try a few values until you’re satisfied that queens with the same sum of row and col are in fact on the same diagonal. Soyoucanseeitallincontext.5.DiagonalsTail). diags2(QueensTail. Reporterratum thiscopyis (P1. cols([]. rows(Board. and diagonals.RowsTail). all that remains is to make sure rows.D AY 3: B LOWING U P V EGAS 129 The formula is a little bit tricky.Range).3. diags2([(Row. diags1([]. cols([(_. rows([(Row.[Row|RowsTail]):rows(QueensTail.Col)|QueensTail]. fd_all_different(Diags2).Col)|QueensTail].8]. Download prolog/queens.[]).member(Col. member(Row.8).[Diagonal|DiagonalsTail]):DiagonalisCol-Row.Cols).Rows). Now that we have the rules to help us describe rows.pl valid_queen((Row. valid_board([]).October2010) . cols(Board. columns. diags1(QueensTail.0printing.[Diagonal|DiagonalsTail]):DiagonalisCol+Row.

[]).(7.buttheprogramisstillworkingtoohard.Col)):-member(Col. we know that there will be one andonlyqueenineveryrow. diags1(Board.0printing.[]).[]). and run. eight_queens(Board):Board=[(1. fd_all_different(Diags1).H)]).W e eliminate the row choices quite easily and simplify the API while we’re atit. diags2(Board.Col)|QueensTail].(3.(4. diags1(QueensTail.6. cols([].(8.DiagonalsTail).ColsTail).5.October2010) ._).B).(7.(6.(3._).C).Col)|QueensTail]. fd_all_different(Diags2).F).Diags1).(2.(5. Reporterratum thiscopyis (P1.G). valid_board([Head|Tail]):-valid_queen(Head). and it would run.pl can valid_queen((Row.valid_board(Tail). cols(Board. diags1([].andrun.._).(5..8]).(6. diags2([].[Col|ColsTail]):cols(QueensTail. diags2(QueensTail. though. A=1 B=5 C=8 D=6 E=3 F=7 G=2 H=4? Thatworksjustfine.3. you could run the program. fd_all_different(Cols).[Diagonal|DiagonalsTail]):DiagonalisCol-Row._).DiagonalsTail). valid_board([]).4.Cols). If you think about it. cols([(_.Diags2)._). diags2([(Row.Col)|QueensTail].[Diagonal|DiagonalsTail]):DiagonalisCol+Row. valid_board(Board).E).(2.(8.Therearejusttoomanycombinationstoefficientlysort through._).[1.Here’saslightlyoptimizedversion: Download prolog/optimized_queens.A).D AY 3: B LOWING U P V EGAS 130 At this point.._)].. diags1([(Row.(4._).2.7.W e canjumpstartthesolutionbyprovidingaboardthatlookslikethis: |?-eight_queens([(1.D).

W e wouldneverthinkofdoingaSQLninetable join imperatively. yet we don’t even blink at solving logical problemsinthisway. _). Then. W e mapped sixteen variables onto rows. Given the right problems.butevenoursimpleapproachcouldsolveitwithinahandful ofminutes. W e also removed all rules related to rows. WhatW eLearnedinDay3 Today. _).having92possible solutions. W e matched the Board with (1. W estartedwithaSudokupuzzle. andsquaretobeunique. all solutions compute insideofthreeminutes.D AY 3: B LOWING U P V EGAS 131 Philosophically. _). I don’t need to know them. (4. _).Prologthenmethodicallyworkedthroughthe possibilities. and the results show.Listconstraints. (3.Howdotheywork? Reporterratum thiscopyis (P1. _). we’ve made one major change. _). Next. (5.0printing. Find print predicatesthatprintoutvariables. Day3Self-Study Find: • Prolog has some input/output features as well. Thisclassicproblemwascomputationallyintensive. W e just described the rules to the game and applied a little logic to speed things up a little. _). we encoded the rules of the game and let Prolog work into a solution.October2010) . (6. and squares. column.W e usedwildcardsandvariablestobuildanintuitiveAPI. I still don’t know all of the tricks and techniques to solve advanced Sudokus. forcing each row. we described the rules of the game.Theconstraint-basedproblemshavemanyofthe samecharacteristicsasclassicindustrialapplications. andcrunchoutasolution. I only need the rulesofthegametoplay. (8. • Find a way to use the print predicates to print only successful solutions.quicklyarrivingatasolution. (2. columns.butwedidn’tprovideanyhelpatallfor solutiontechniques. Once again.IcouldreallyfindmyselfgettingintoProlog. (7. On my ancient MacBook.Prolog’ssolutionwasremarkablysimple. the end result is quite pleasing. _) to reduce the total permutations significantly. but with Prolog. W e built in very little knowledge of the solution set. Once again.youputtogethersomeoftheideaswe’veusedinPrologtosolve someclassicpuzzles. we used Prolog to solve the Eight Queens puzzle.

He was able to makesimpleinferencesabouttheworldandmakeabreakthroughwith a complex inference about dolphin behavior. and Prolog will e s or no. or otherslikeit.October2010) .butthe demanding problems that Prolog solves tend to make the language. He was also able to take Reporterratum thiscopyis (P1. which were in turncomposedwithaseriesofgoals.W RAPPING U P P ROLOG 132 Do: • Modify the Sudoku solver to work on six-by-six puzzles (squares are3x2)and9x9puzzles. Think back to Brian Tarbox’s work with the dolphins.Rather thanatuple. Next. Rather than simple assignment. 4. • SolvetheEightQueensproblembytakingalistofqueens.representeachqueenwithaninteger. Strengths Prologisapplicableforawidevarietyofproblems.Get therowofaqueenbyitspositioninthelistandthecolumnbythe valueinthelist. Prolog uses a process called unification thatmakesvariablesonbothsidesofasystemmatch. • MaketheSudokusolverprintprettiersolutions.0printing. W e used Prolog to process rules.buttheideasarestill interesting and relevant today.Prologhasaseriouslearningcurve. composed of clauses. Start by building a knowledgebase. Prolog programming has two major steps. Eight Queens is a good placetostart. Prolog means programming with logic. If you want to dive deeper into the puzzles I’ve presented. Some of the questions can be assertions.Otherquerieshavevariables.fromairlineschedulingtofinancialderivatives.Sometimes.composedoflogicalfactsandinferencesabouttheproblem domain. you can get lost in Prolog. and ask questions about the domain. If you’re a puzzle enthusiast.worthwhile.Prologfillsinthese respondwith y gapsthatmakesthosequeriestrue. Prolog has to try many different possible combinations of variables to unifyvariablesforaninference.from1–8. compile your knowledge base.5 WrappingUpProlog Prologisoneoftheolderlanguagesinthisbook.

Prolog language models can take natural language. ArtificialIntelligence Artificial intelligence (AI) centers around building intelligence into machines. but in every case. especially when the rules are concrete. Prolog models can easily express the behavior of other characters in the system.anditdoeshavesignificantlimitations. making it easier to satisfy requests. some “agent” modifies behavior based on complex rules. apply a knowledge base of facts and inferences. together with Prolog’s natural-language processing. based on formal logic. Many Prolog packages exist forprovidingthissortoffunctionalityinthecontextofawebserver. For this reason. Reporterratum thiscopyis (P1. Prolog is sometimes called a logic programming language. especially modeling the behavior of competitors or enemies.Aservercancompiletheseresourcesintoaknowledgebase. Still.ThesearesomeareaswherePrologisinactiveusetoday: Natural-LanguageProcessing Prolog was perhaps first used to work with language recognition. That knowledge. Many have used Prologtobuildoperatingsystemschedulersandotheradvancedschedulers.October2010) .0printing. can provide a rich end user experience. inexactlanguageinconcreterulesappropriateforcomputers. the language is datedinmanyways. W e a k n e s s e s Prolog is a language that has held up over time. SemanticW e b The semantic W e b is an attempt to attach meaning to the services and information on the W e b .W RAPPING U P P ROLOG 133 highly constrained resources and use Prolog to find schedules that fit amongthem. Scheduling Prolog excels in working with constrained resources. This intelligence can take different forms. and express that complex. Games Games are getting more complex. making a more lifelike and enjoyableexperience. Prolog excels in this arena. In particular. Prolog can also build different behaviors into different types of enemies. The resource description language (RDF) provides a basic description of resources.

Prolog was a particularly poignant example of my evolving understanding. knowingthatthroughtheyears.especiallyasdatasetsget very large. particularly those that relyheavilyonrecursion. It is not a general-purpose language. you’re likely to come out ahead in the longrun. it’s a fairly focused niche. It’s relatively easy to build Prolog applicationsthatcannotscalebeyondatrivialsetofdata.thestrategyisinherentlycomputationallyexpensive.Still. If you find a problem that’s especially well suited for Prolog. logic programming. It also has some limitationsrelatedtolanguagedesign. In such a setting.V a r o iu s languagesand compilersdoaprettygoodjobofoptimizingthisprocess.W RAPPING U P P ROLOG 134 Utility While Prolog excels in its core domain. you can best use this rulesbased language in combination with other general-purpose languages. just as you would use SQL within Ruby or Java.0printing.youmustunderstandhowPrologwillresolve recursive rules. take advantage. FinalThoughts AsIworkedthroughthelanguagesinthisbook. If you’re careful with the way you tie them together. Reporterratum thiscopyis (P1. Y o u must often have tail-recursive rules to complete even moderately large problems. using all possible combinationsmatchedagainstthesetofrules. Very LargeDataSets Prolog uses a depth-first search of a decision tree.October2010) .Y o umustoften have a deep understanding of how Prolog works to effectively design rulesthatwillscaleatacceptablelevels.I’vedrivenmanyascrewwithasledgehammer.Ioftenkickedmyself. It also forces Prolog users to understand how the language workstokeepthesizeofdatasetsmanageable. MixingtheImperativeandDeclarativeModels Like many languages in the functional family.

buttheprocessisnotasimpleone. and was one of my favorite characters of all time.languages. In thissense. 1.hewasoftenmisunderstood.hisscissorslethimdoincrediblethings. DVD.1 InthissurrealTim Burtonmovie. Every twenty years or so.ScalaisaFrankensteinmonsterofsortsbutnotamonster.Other times. sort of. Edward was a fascinating character in a beautiful movie. Directed by Tim Burton. 1990.”Butinoneofhisstrongermoments.Aswithanythingnewordifferent. In this case. meaning that it intentionally tries to bridge the gaps between programming paradigms.Ihaveintroducedthreelanguagesandthreedifferentprogramming paradigms. must evolve.Edwardwaspartboy.butalwayshadaunique expression. Beverly Hills. the bridge is between objectoriented languages like Java and functional languages like Haskell. CA: 20th CenturyFox.wassometimesamazing.partmachine.“Wearenotsheep.1 AboutScala Asrequirementsforcomputerprogramsgetmorecomplex. Edward Scissorhands . EdwardScissorhands Chapter 5 Scala Sofar.”Indeed.hewasawkwardandhumiliated. He wasoftenawkward. 5.2002.Sometimes.accusedof“strayingtoofarfromthe pathofrighteousness. with scissors for hands. the old paradigms become inadequate to handle the new demands for organizing and expressing ideas. too.Newparadigmsmustemerge. .theshykid offers. Think EdwardScissorhands .W earenotsheep. It’s a hybrid language. Scala will be the fourth.

At some point. These important improvementsrepresentimportantdeparturesfromtheJavalanguage: • Type inference. • Scala can use Java libraries directly.soScalacanrunside-bysidewithexistingdeployments. or parameter.sothelanguagesshareaphilosophicalbond. such as Java or C#. so developers can leverage existingframeworksandlegacycode. Think Smalltalk for objects or Lisp for functional languages. such as a C++. extending the very limiting concepts that make the base inadequate. we see a commercially adoptable language. you must declare the type of every variable.A BOUT S CALA 136 Each new programming paradigm ushers in a wave of programming languages. • Scala supports both object-oriented and functional programming paradigms. In Java. Scala infers variable types where possible. • LikeJava. Scala’s design has some significant departures that will serve its community well. pure implementations of the new paradigm. The initial language is often strikingly productive and wildly impractical. WithoutSlavishDevotion Some languages that embrace their ancestors go too far. Ada.Scalaisstaticallytyped. Next. AffinitywithJ a v a . Finally.sodeveloperscanlearn thebasicsquickly. languages from other paradigms build in features that allow people to absorb the new concepts while users can live safely within the old paradigm. Reporterratum thiscopyis (P1. we see some mature. argument. Scalaisatleastabridgeandmaybemore.October2010) . Although the similarities to Java are striking. so programmers can gradually learn to apply functionalprogrammingideastotheircode. allowed some coreobject-orientedideassuchasencapsulationtoexistwithinaprocedural language. • Scala’ssyntaxisrelativelyclosetoJava’s. not just one. Then. for example. some hybrid language offers just the right practical bridge between the old paradigm and the new.Itofferstightintegrationinto Java.0printing. offering a chance for people to protect their investment in many ways: • ScalarunsontheJavavirtualmachine.

layering on useful concepts. Scala introduces important functional concepts to Java. These decisions will have a profound effect on how applicationsbehaveinaconcurrentcontext.HehasworkedontheJavaGenericsspecificationandis thecreatorofthe javac referencecompiler. In this chapter.Heisalsotheauthorof Pro[OSV08]. one gramming in Scala: A Comprehensive Step-by-Step Guide ofthebestScalabooksavailabletoday. In this chapter. Bruce: Whatisthethingyoulikeaboutitthemost? Reporterratum thiscopyis (P1. I also wanted to create a languageinwhichIwouldpersonallyfeelcomfortablewritingprograms. AnInterviewwithScala’sCreator.MartinOdersky Martin Odersky. Specifically. • Immutable variables. the new language allows you to use existingfunctionsinmanydifferentwaystoformnewones.Scalagoesfarbeyond somebasicsyntacticalsugar.focusingonhowhedecided to tietwoprogrammingparadigmstogether.andfirst-classXMLprocessing. I was frustrated both by the dismissive attitude of the functional programming community toward OOP and by the belief of object-oriented programmers that functional programming was just an academic exercise. • Advanced programming constructs. So. you’ll see that Scala forces you to explicitly make a decision about whether a variable is mutable. I wanted to showthatthetwoparadigmscanbeunifiedandthatsomethingnewand powerful could r e s u t l from that combination.October2010) . Odersky: I was convinced that unifying functional and object-oriented programming would have great practical value.Conceptsyou’llseeinthischapterarecodeblocks. we’ll introduce you to actors for concurrency. is a professor at École PolytechniqueFédéraledeLausanne(EPFL).andasophisticatedcollectionlibrary. Beforewedivein. W e l’ spend sometime with thecreator. Scala uses the foundational language well.0printing.weshouldknowaboutthemotivationsbehindScala.A BOUT S CALA 137 • Functional concepts. Ruby-style collections withhigher-orderfunctions. Java does allow immutable variables but with a rarely used modifier.Hereiswhathehadtosay: Bruce: WhydidyouwriteScala? Dr. the creator of Scala.oneoftwoSwissFederalInstitutes ofTechnology.higher-orderfunctions.

willreturnthesamevalues. • Functionalprogramsavoidchangingstateormutatingdata. Bruce: What is a feature that you would like to change.IfIcouldstartover.aparticularstrengthofScalar e a lt v ieto othermainstreamlanguagesisitssupportoffunctionalprogramming.Thatsaid. using getters and setters would break that rule.youhavetoleaveitalone. (With most object-oriented languages.Scalaisnotapurefunctionalprogramminglanguage.October2010) . The object-oriented features allowaprettysmoothtransitionfromtheJavalanguage.giventhesameinputs. Odersky: Scala’slocaltypeinferenceworksgenerallywellbuthas limitations. just like C++ is not a pure object-oriented language.buttheideas that are drawing attention to Scala are the functional programming features.) But it offers tools that allow developers to usefunctionalabstractionswheretheymakesense. Odersky: It’s r e a y l general purpose. Strictlyspeaking. but the fact that we have to dealwithalargeinstalledbasemakesitmoredifficult.Once you’vesetavalue. yet at the same time gives strong support throughitstypesystem. everywhereafunctionalapproachisimportantScalashines.bethatconcurrencyandparallelismorwebappsdealingwithXMLorimplementing domain-specificlanguages.becauseTwitterhasswitcheditscore message processing from Ruby to Scala.Afunctionallanguagehasthese characteristics: • Functionalprogramsaremadeupoffunctions.I’dtrytouseamorepowerfulconstraint solver. if you could startover? Dr. It allows mutable values.So. • Afunction. Reporterratum thiscopyis (P1. • Afunctionalwaysreturnsavalue.A BOUT S CALA 138 Dr. There’s no problem I would nottrytosolvewithit. Odersky: I like that it lets programmers express themselves freely and that it feels lightweight. Maybe it’s still possible to do that. ThebuzzaroundScalaisgrowing. Bruce: Whatkindsofproblemsdoesitsolvethebest? Dr.0printing. Pure functional languages allow a style of programming that hasstrongmathematicalfoundations.whichcanleadtofunctionswiththesameinputsbutdifferent outputs.

it’sdifficulttoguaranteethattheexecutionwillleavethedatain avalidstate. you don’t have to choose between making some Smalltalk andhavingalittleLisp. Scala does not force you to completely eliminate mutable state. is showing some signs ofage.Fornow. but it does give you the tools to codethingsinapurelyfunctionalstyle.2 Day1:TheCastleontheHill In Edward Scissorhands . Reporterratum thiscopyis (P1. we’re going to talk primarily aboutScalainthecontextofthathouseonthehill. Functional programming languages can solve these problems by eliminating mutable state from the equation. The house that once felt so comfortable to its inhabitants is now cold and uninviting.7.andtestingisnearlyimpossible. a little different. that information is freely available elsewhere. Evil to mutable state’s Austin Powers.afterinitialization.especiallytheearlierobject-orientedimplementations. W t i h Scala. 5. well. The object-oriented paradigm.D AY 1: T HE C ASTLE ON THE H ILL 139 FunctionalProgrammingandConcurrency The biggest problem facing concurrency-minded programmers in object-oriented languages today is mutable state . is mutable.installScala. needs a face-lift. meaning data that can change.October2010) . and the rooms aren’t all what they once were. ScalarunsontheJavavirtualmachine(JVM).7. In this section. too. there’s a castle on a hill that is. the castle was a strange and enchanting place but is now showing signs of age and neglect.0printing. with its dated implementations of static typing and concurrency.Databasesdealwiththis problem with transactions and locking.evenwhentheyknowhow. In a bygone era. Y o u l’ see some Java ideas creeping through to Scala. Broken windows let the weather in.theobject-oriented programmingparadigm.I’mnotgoingtoofferan exhaustive overview of the Java language.TheJava language. And programmers generally don’t use thosetoolsverywell. Object-oriented programming languages deal with this problem by giving programmers the tools to control access to shared data.butI’lltrytominimizetheirimpactsoyouwon’thavetolearntwo languagesatonce. Concurrencyis the Dr.Anyvariablethatcanholdmorethanonevalue.I’musingversion2.Iftwodifferentthreadscanchangethesamedataatthesame time.final forthisbook.Let’sgetbusymergingtheobject-orientedand functionalworldswithsomeScalacode.

In fact. If all is well.lang. everythingisanobjectinScala.0 Hm.D AY 1: T HE C ASTLE ON THE H ILL 140 ScalaTypes When you have Scala working.Y o ucanthentypealittlecode.October2010) .String=41. you won’t get any error messages.lang.Let’stryalittlehardertoforceamismatch: scala>4 * "abc" <console>:5:error:overloadedmethodvalue * withalternatives(Double)Double <and>(Float)Float<and>(Long)Long<and>(Int)Int<and>(Char)Int <and>(Short)Int<and>(Byte)Intcannotbeappliedto(java. scala>println("Hello. *(3)) res12:Int=17 So. and you will see a scala> prompt.0 scala>(5).size res13:Int=3 Soastring. *(3)) res11:Double=17.surrealworld") Hello.isafirst-classobject.surrealworld scala>1+1 res8:Int=2 scala>(1).lang.String) 4 * "abc" ^ Reporterratum thiscopyis (P1.+(1) res9:Int=2 scala>5+4 * 3 res10:Int=17 scala>5.Let’strytoforceatypecollision: scala>"abc"+4 res14:java... fire up the console with the command scala. In Java.that’snotquitewhat we were lookingfor.0" res16:java.0printing.That’sasignificant departure from most statically typed object oriented languages.String=abc4 scala>4+"abc" res15:java. integers are objects. Let’sseehowScalahandlesstrings: scala>"abc".+((4). I’ve pulled out my fair share of hair converting between Int (primitives) and Integer (objects).withalittlesyntacticsugarmixed in.lang.too.String=4abc scala>4+"1.+(4.Scalais coercing those integersintostrings.withsomesmallexceptions.

D AY 1: T HE C ASTLE ON THE H ILL 141 Ah.0printing. That’s the ticket.somostofthetime. This is the C-style syntaxthatyou’refamiliarwithfromseveralofthelanguageswe’vetalked if statement: aboutsofar. Most Scala articles and books go into this topic in more detail. Scala is actually strongly typed.October2010) .HereareafewScalatrue/falseexpressions: scala>5<6 res27:Boolean=true scala>5<=6 res28:Boolean=true scala>5<=2 res29:Boolean=false scala>5>=2 res30:Boolean=true scala>5!=2 res31:Boolean=true There’s nothing too interesting going on there. I’ll point you to a few books that will go into the Java integration in detail. Scala’s console actually compiles lines ofcodeandrunseachonepiecemeal. Scala has a strategy for managing types across two languages. Part of that is using simple Java types where they make sense.Pleasetrustme. I’m going to tell you that in many places.String.Let’suseanexpressioninan scala>vala=1 a:Int=1 scala>valb=2 b:Int=2 scala>if(b<a){ | println("true") |}else{ | println("false") |} false Reporterratum thiscopyis (P1. ExpressionsandConditions Nowwe’regoingtomovethroughsomebasicsyntaxquicklyandstrictly byexample.andaccepttheseoversimplifications. For now.lang. but unlike Ruby. On a side note. I know you’re getting back Java strings. Scala can do that type checking at compile time. like java. but we can’t do so andstilldiveintotheprogrammingconstructsthatIthinkwillbemost interesting to you. Scala will use typeinference.itwillunderstandthetypesofvariables through syntactical clues.

v a l Next. static typing philosophy. fs le . Y o u l’seeanumberofwaystoiterateoverresultsetsinday2whenwe attackcodeblocks.sodon’ttreatthemlike t i hsimple expressions and the most basic decision construct behind us. and you can’t even test ior is consistent with Scala’s strong. notice that you didn’t specify a type.Fornow. In both languages. Nils and booleans. found :Int(0) required:Boolean if(0){println("true")} ^ scala>if(Nil){println("true")} <console>:5:error:typemismatch. v a r isnot. found :Nil.D AY 1: T HE C ASTLE ON THE H ILL if/else stateW e assign a couple of variables and compare them in an ment.LikeRubyandIo.type(withunderlyingtypeobjectNil) required:Boolean if(Nil){println("true")} ^ 142 nil Nil or 0. Unlike Ruby.October2010) .Y o ucanalsousethe v a r keyword. In Ruby.we’llfocusontheimperativeprogramming style of loops. Reporterratum thiscopyis (P1.scala . 0 evaluated to true. notice that these Scala variable declarations start with the keyword. v a l isimmutable.thoughyoucanifyouwant. But unlike Java. Scala can infer the type. so you don’t have to a la:Int=1 type v . Loops As the next couple of programs get more complex. Scala binds types at compile time.0printing.Let’sseehowScalahandlesthem: evaluatedto a scala>Nil res3:Nil.type=List() scala>if(0){println("true")} <console>:5:error:typemismatch. 0 was a fs le . This behavSo. let’s moveontoloops.you’llrun themwith scalapath/to/program. First. In C. a Nil is an empty list. Y o u l’ see that these look a lot like the Java-style loop structures. W e l’ talkmoreaboutthislater.W numbersarenot booleans. we’re going to run themasscriptsratherthanintheconsole. Take a closer look at the variable assignment.

Haskellanditsgreatstatictypesystemarehelpingmerecover butslowly.orjustdata. Hibernate. J a v a and Ruby are both strongly typed.Y o u’ve invitedaclosetpolitician to this casual dinner.D AY 1: T HE C ASTLE ON THE H ILL 143 MyInnerBattlewithStaticTyping Some novice programming language enthusiasts confuse the ideas of strong typing and static typing.Mybookstookthesamejourney. ur Reporterratum thiscopyis (P1. On the surface.Y o historyasadeveloperwilloftendeterminehowy o uf e e labout thetrade-offsofstatictyping.from increasinglydynamicframeworkstodynamiclanguages. Staticanddynamictypingisanotherissue.throwinganerrororcoercingthetypesiftheyare not.October2010) . My first OO development w a s in J a v a . or is it a duckbecauseitquacksorw a k lslikeone?Staticallytypedlanguagesbenefitbecausecompilersandtoolsknowmoreabout y o u rcodetotraperrors. JBoss. and the battles at e v e r y step of the w a yw e r e intense.Staticallytypedlanguages enforce polymorphism based on the structure of the types.0printing. Loosely speaking. on the other hand.astring.andrefactor. f e e n ilg more like rival cults than programmingenvironments. I saw one framework after another try to break free from the chains of J a v a ’ s static typing.highlightcode. but I’ll try m y hardest to k e e p the conversationlightandunbiased. are w e a k y l typed. strongtypingmeansthelanguagedetectswhen twotypesare compatible. Is it a duck b y the genetic blueprint (static). W e w e r em a k n ig J a v a ’ s typing model more dynamic.Myconscienceisclear.m ybiasagainststatictypingw a sshapedb ytheJ a v aw a r s . The industry invested hundreds of millions of dollars in three v e r s o in s of Enterprise J a v a Beans. The compilerdoesn’tnecessarilycarewhetherthedatainamemorylocationisaninteger. Spring. So.Thecost ishavingtodomorew o r kandlivingwithsomerestrictions. and aspect-oriented programming to m a k e certain usage models more m a e la b e l. (I realize this idea is an o v e r s m ip fi ilc a o t in . ) Assembly language and C compilers.

Java developers will notice that public.operator. you see a Java-style declaration of a while statement. As you can see. followed by the initialValueuntilendingValue . Then. As a side note.scalaitsallinthegrind forloopusingJava-styleiteration its all in the grind Reporterratum thiscopyis (P1.length){ println(args(i)) } } forLoop ) <. while loopthatcountstothree.scala 1 2 3 f r loopworksalotlikeJava’sandC’sbutwithaslightlydifferent The o syntax: Download scala/for_loop. followed by a The argument is a variable.wedeclareasimple i changes. W t i h n i themethod. rangefortheloopintheformof we’reiteratingovertheincomingcommand-linearguments: batate$scalacode/scala/forLoop.scala defforLoop{ println( "forloopusingJava-styleiteration" for(i<-0untilargs.Inthiscase. so we declare it with v a r .0printing.InScala.Y executesunlesstheconditionis o ucanrunthecodelikethis: batate$scalacode/scala/while.scala defwhileLoop{ vari=1 while(i<=3){ println(i) i+=1 } } whileLoop W e define a function. public isthedefaultvisibility. the code inside braces a fs le .D AY 1: T HE C ASTLE ON THE H ILL 144 Firstisthebasic while loop: Download scala/while.October2010) . youdon’thavetospecify meaningthisfunctionwillbevisibletoall.

Start the console. you can also use loops to iterate over a collection. one by one.3.start res2:Int=0 scala>range.Here’sthecodeinaction: batate$scalacode/scala/ruby_for_loop.we’lldelaythatpartoftheconversationforalittle while.Butsincewe’reconcentratingon thehouseonthehill. Y o u can also specify increments: scala>range.scala defrubyStyleForLoop{ println( "forloopusingRuby-styleiteration" args. In our case. For fr e a c h each: now. the same code would be args.0printing.we’llstartwith o . In Ruby.8. The syntax for specifying each argument isslightlydifferent.D AY 1: T HE C ASTLE ON THE H ILL 145 As with Ruby. Scala passes arg is one argueach element into this block.each { |arg| println(arg) } .whichisreminiscentofRuby’s Download scala/ruby_for_loop.4. It works like Ruby’s range.end res3:Int=10 That all makes sense.6. ment from the inbound args list.October2010) .2. RangesandT u p e ls Like Ruby. you’ll find yourself using this method of iteration much more oftenthantheotherimperativeloops.buttheideaisthesame.9) scala>range.5.scalafreezethosekneeschickadees forloopusingRuby-styleiteration freeze those knees chickadees Later.1. Scala supports first-class ranges.7. and enterthesecodesnippets: scala>valrange=0until10 range:Range=Range(0.foreach{arg=> println(arg) } } rubyStyleForLoop ) args is a list with the inbound command-line arguments.step res4:Int=1 Reporterratum thiscopyis (P1.

The objectsinatuplecanallhavedifferenttypes.Y o uarenotlimitedtointegers: scala>valrange='a'to'e' range:RandomAccessSeq. Y o u l’findthispatterninmanyotherfunctionallanguagesaswell. 1.3.10. regardless of the endpoints that you express for yourrange.7.lang.D AY 1: T HE C ASTLE ON THE H ILL scala>(0to10)by5 res6:Range=Range(0.Projection(a.lang. programmers often express objects and their attributes with tuples.Inpurelyfunctionallanguages.9.2.d.7.youwereactuallyspecifyingarange._3 ^ Reporterratum thiscopyis (P1. specifieda o LikeProlog.10) 1 is the default step.4.String=Elvis scala>person.6) 146 1.Presley) scala>person.10) scala>(0to10)by6 res7:Range=Range(0.Projection[Char]=RandomAccessSeq...2.Try thisexample: scala>valperson=("Elvis".5.whenyou f r statement.lang.Scalaofferstuples.String.b.java.5.Atupleisafixed-lengthsetofobjects.3.4._2 res10:java._1 res9:java.6.5. and the equivalent of The equivalent of Ruby’s range.String) person.Inclusive=Range(0..c.9.5) Y o ucanalsospecifydirectionwiththis: scala>valrange=(10until0)by-1 range:Range=Range(10.lang.lang.String)=(Elvis.8.10.String=Presley scala>person."Presley") person:(java. to isinclusive: scala>(0until10by5) res0:Range=Range(0.is 1until10 .String.8.java.1) Butthedirectionisnotinferred: scala>valrange=(10until0) range:Range=Range() scala>valrange=(0to10) range:Range.6.lang. Ruby’srange._3 <console>:6:error:value_3isnotamemberof(java.0printing.October2010) .1.e) Scalawilldosomeimplicittypeconversionsforyou. is 1 to 10 .Infact.

2.one-linedefinitionsinScala: classPerson(firstName:String. "east" .b)=(1. ClassesinScala Thesimplestclasses.Here’swhattheScalacodelookslike.0printing. let’s put it all together.W e l’ thisclass Compass."Gump") gump:Person=Person@7c6d75b6 But you’re looking for a little more.D AY 1: T HE C ASTLE ON THE H ILL 147 Scalausestuplesratherthanliststodomultivalueassignments: scala>val(x.Thecompassorientationwillstartwithnorth.b)=(1.Int) val(a.lastName:String) definedclassPerson scala>valgump=newPerson("Forrest".The P e r s o n class will be public and have firstName and lastName attributes.Int. Object-oriented classes mix data andbehavior. Andyoucanusethatclassintheconsole: scala>classPerson(firstName:String. found :(T1.2) x:Int=1 y:Int=2 Since tuples have a fixed length.2.2. "west" ) Reporterratum thiscopyis (P1.W e l’ tellthecompasstoturn90degreesleftorrightandupdatethedirection accordingly.thosewithattributesbutnomethodsorconstructors.scala call classCompass{ valdirections=List( varbearing=0 "north" .initsentirety: Download scala/compass. W e l’ createsomeobject-orientedclassdefinitions. "south" . Scala can do static type checking basedoneachofthetuplevalues: scala>val(a.aresimple.Let’sbuildafullobject-orientedclassinScala.b)=(1.3) ^ W t i h these foundations out of the way.3) ^ <console>:15:error:recursivevaluex$1needstype val(a.October2010) .T2) required:(Int.3) <console>:15:error:constructorcannotbeinstantiatedtoexpectedtype.y)=(1.lastName:String) Y o udon’thavetospecifyanybodytospecifyasimplevalueclass.

Our constructor has a which is simply an index for the directions. "south" .turnLeft myCompass. there are a couple of convenience methods to showtheuseroftheclassthecurrentdirection.D AY 1: T HE C ASTLE ON THE H ILL print("Initialbearing:" println(direction) ) 148 defdirection()=directions(bearing) definform(turnDirection:String){ println("Turning" +turnDirection+ } defturnRight(){ bearing=(bearing+1)%directions.withacoupleofnotablepeculiarities.turnLeft myCompass.And the initial block of code isn’t in any method definition at all.October2010) . Let’s take itapart: classCompass{ valdirections=List( varbearing=0 "north" .size inform("left" ) } } valmyCompass=newCompass myCompass.turnRight myCompass.0printing.size inform("right" ) } defturnLeft(){ bearing=(bearing+(directions.allmethoddefinitionshaveparametertypesandnames.inEnglish: defdirection()=directions(bearing) Reporterratum thiscopyis (P1.size-1))%directions.turnLeft ".Nowbearing" +direction) Thesyntaxisrelativelystraightforward. those you don’t pass into the constructor) and methods. UnlikeRuby. Later. Next. constructor. turning will manipulate the bearing. "west" ) print("Initialbearing:" println(direction) ) The whole block of code following the class definition is actually the List of directions and a bearing. The constructor is responsible for defining instance variables (at least. "east" .turnRight myCompass.

last_name:String){ this(first_name) println("Innerconstructor" ) } deftalk()=println( "Hi" ) } valbob=newPerson( "Bob" ) valbobTate=newPerson( "Bob" .thedirectionoftheturn.Considerthis P class.Let’slookatthemethodstohandleturns. The inform methodprintsafriendlymessagewhenevertheuserturns.size inform("right" ) } defturnLeft(){ bearing=(bearing+(directions. Scala od just returns the element of convenientlyallowsanalternatesyntaxforone-linemethods.size inform("left" ) } The turns method changes the bearing based on the direction of the turn.size-1))%directions.October2010) .andamethod called talk. firstName.Ittakes Reporterratum thiscopyis (P1. defturnRight(){ bearing=(bearing+1)%directions.(Thisoperatordoesadivision operation. A u x a i lr yConstructors Y o u v ’e seen how the basic constructor works. "Tate" ) Theclasshasaconstructorwithoneparameter.The % operatorismodulardivision.omitting thebracesaroundthemethodbody.Noticethe this method.It takesasimpleparameter.Nowbearing" +direction) direction methTheconstructorcontinueswithmethoddefinitions. It’s a code block that initializesclassesandmethods.0printing.scala classPerson(first_name:String){ println("Outerconstructor" ) defthis (first_name:String.Y o ucanhavealternateconstructorsas e r s o n well.The directions at the index of bearing. discarding the quotient and returning only the remainder.That’sthesecondconstructor.wrappingtheresultaccordingly.) The result is that right turns add one to the bearing and left turns subtractone.Thismethoddoesn’t returnavalue.D AY 1: T HE C ASTLE ON THE H ILL definform(turnDirection:String){ println("Turning" +turnDirection+ } 149 ".withtwoconstructors: Download scala/constructor.

Using this scenario.theclasseshavebeenprettyvanilla.class_method .W ecreatedacoupleofbasic classeswithnothingmorethanattributesandmethods. we’lllookatsomeofthewaysthatclassescaninteract.Inourexample. first with the primary constructor.Thisstrategyiscalled Reporterratum thiscopyis (P1. you can have both an tion and a class definition with the same name. CompanionObjectsandClassMethods InJavaandRuby.themethodinvokes firstName parameter. then next with the auxiliary constructor: batate$scalacode/scala/constructor. within the same body. Auxiliary constructors are important because they allow for a broad array of usage patterns.scala objectTrueRing{ defrule=println( } TrueRing.butitcreThe T definitionworksexactlylikeany object definiates a singleton object.October2010) . method rule isaclassmethod.0printing. withtheprimaryconstructor.rule "Torulethemall" ) r u e R n ig class definition. ExtendingClasses Sofar. firstName and lastName. In Java.When Instead.Initially.the companionobjects .scala Outerconstructor Outerconstructor Innerconstructor this That’s all there is to it. Scala uses neither of these strategies.youcreatebothclassmethodsandinstancemethods static keyword. class definitions.D AY 1: T HE C ASTLE ON THE H ILL 150 twoparameters.youwilldeclareinstancemethodsinthe there’ssomethingthatcanhaveonlyoneinstance.withonlythe The code after the class definition instantiates a person in two ways. Let’s look at how to createclassmethods.you’lldefineitwith the object keywordinsteadofthe class keyword. you can create class methods within the singleton object declaration andinstancemethodswithintheclassdeclaration.Inthissection. class methods have the Ruby uses def self. In Scala.Here’sanexample: Download scala/ring.

talk("Extendorextendnot. T r a t s i Everyobject-orientedlanguagemustsolvetheproblemthatoneobject can have several different roles.Movingon. Java usesinterfaces.. Notice P e r s o n .scala classPerson(valname:String){ deftalk(message:String)=println(name+ defid():String=name } "says" +message) classEmployee(overridevalname:String.andScalausestraits. if you prefer. number in Employee..0printing. C++ uses multiple inheritance.. id Notice that the Employee has an additional employee number in the field. Or.Here’sthecode: Download scala/employee. implemented with modules.Y o udon’twantyourshrubberytohavetoknowhow to push binary data into MySQL. Here’s an example of extending a class with Employee.4) employee. and W e r ’e adding a new instance variable called we’re also overriding the talk message to add some new behavior.Thereisnotry.Ido feelabitlikeEdwardtryingtopetafragilebabybunny.Rubyusesmixins.butattimes.AScalatrait is like a Ruby mixin.D AY 1: T HE C ASTLE ON THE H ILL 151 Inheritance Inheritance in Scala is pretty straightforward. though that you must specify the complete parameter list for youcanomitthetypes. both in the constructor and for any methods you want to extend from the base class.toString } valemployee=newEmployee( "Yoda" .Allinall.October2010) . a traitislikeaJavainterfaceplusanimplementation.Lookatatraitas Reporterratum thiscopyis (P1. This keyword will keep you from inadvertently introducing new methods with misspellings. serializableshrubbery. we’re extending the base class with Employee. but the syntax must be P e r s o n exact. valnumber:Int)extendsPerson(name){ overridedeftalk(message:String){ println(name+ "withnumber" +number+ "says" +message) } overridedefid():String=number." ) P e r s o n In this example. v e d r ie The o keyword.therearenomajorsurpriseshere. is mandatory. Most of the tricky syntax is around the class constructor definition. An object can be a persistent.

Thecompilercanalsocoercetypes. Nice There’snothingtoocomplicatedhere. WhatW eLearnedinDay1 W e coveredatremendousamountofterritoryinday1becausewehave tofullydeveloptwodifferentprogrammingparadigmsinonelanguage. running in the JVM side-by-side with existing Java libraries.0printing. Scala’sstatictypingisalsoinferred. Clients can now use the greet method on any instance of Character. mixes in the Nicetrait. It has a single method called class called Character." ) classCharacter(overridevalname:String)extendsPerson(name)withNice valflanders=newCharacter( flanders.Thesefunctionalprogrammingconceptsthatwe’llintroduceinday2willmakeiteasiertodesign concurrentapplications.itshouldimplementonecritical Nice to P e r s o n : concern.scala classPerson(valname:String) traitNice{ defgreet()=println( } "Howdilydoodily. But Martin Odersky wrote Scala to bridge two paradigms: object-oriented programmingandfunctionalprogramming. Scala’s syntax is similar to that of Java and is also strongly and statically typed.Here’sanexamplethataddsthetrait Download scala/nice. allowing implicit type conversions when theymakesense.October2010) . The second element is the greet. such as integers to strings. a is the mixin. Reporterratum thiscopyis (P1. The final element. The output is what you wouldexpect: batate$scalacode/scala/nice.Ideally.greet "Ned" ) The first element you see is P e r s o n .scala Howdilydoodily. Day 1 showed that Scala embraces object-oriented concepts. That attribute called name.D AY 1: T HE C ASTLE ON THE H ILL 152 apartial-classimplementation.W e cantakeourtraitcalled withamethodcalled greet andmixitintoanyScalaclasstointroduce the greet behavior. It is a simple class with a single trait called Nice.Usersdonotalwaysneedtodeclare types for all variables in all situations because Scala can often infer thosetypesfromsyntacticalclues.

Useclasseswhereappropriate.Instead. but it should be mostly familiar territory. but they don’t support class methods.Scaladoessupportsomemoreadvancedtypes.D AY 2: C LIPPING B USHES AND O THER N EW T RICKS 153 Scala’sexpressionsworkmuchliketheydoinotherlanguages.Theseexercisesarealittleadvancedcomparedtotheearlierexercisesinthebook.Mostconditionalsmusttakeabooleantype.Scalausesaconceptcalled companionobjects to mix class and instance methods on the same class.3 Day2:ClippingBushesandOtherNewT r c ik s In Edward Scissorhands . a magical moment happens when Edward realizes that he’s come far from the house on the hill and his unique abilitiesmaygivehimaspecialplaceintheexistingsociety. all-inclusiveorderedsequenceofnumbers).0printing. Reporterratum thiscopyis (P1. they can substitute for neither true nor a fs le . collections.Butthere’snothingdramaticallydifferentaboutScala’sloopingor controlstructures. These object-oriented concepts should be familiar to you.butthey arealittlemorestrict. Where Ruby uses mixins and Java uses interfaces.October2010) . Day1Self-Study The first day of Scala covered a lot of ground. Scala uses a structure like a r a t i .O. Scala classes work much like they do in Java. mixincalleda T In day 2. Find: • TheScalaAPI • AcomparisonofJavaandScala • Adiscussionof Do: •W r t i eagamethatwilltakeatic-tac-toeboardwithX. and some fd lL e f t advancedbuilt-inmethodslike o . • Bonusproblem:Lettwoplayersplaytic-tac-toe. we’ll take a full pass through Scala’s functional features. immutable variables. W e l’ cover code blocks.and 0 or Nil will not work at all.andblank characters and detect the winner or whether there is a tie or no winneryet. v a l versus v a r 5.butyoucanhandleit.like tuples(fixed-lengthlistswithheterogeneoustypes)andranges(afixed.

When the object-oriented paradigm was new.theparenthesesarenotoptionalinthiscontext. such as omitting parameters. W e needed a language that would let them continue to do procedural programming and experiment with object-oriented ideas.thenewobject-orientedtrickscouldlivesafelybesidetheexisting Cproceduralfeatures. Y o u l’ wanttopaycarefulattentiontothelifecycleofthevariableifyouwant tolearnthepurefunctionalprogrammingmodel. Some of this will seem awkward at first. the masses could not accept Smalltalk because the paradigm was too new.Notice thatunlikeRuby.Theresultwasthatpeoplecouldstartusingthe newtricksinanoldcontext. These are the major forms offunction declarations. Now.October2010) . but the ideas are powerful andimportant.Theywillformthefoundationfortheconcurrencyconstructs you’ll see later in day 3. The parameters and their types come next. Y o u definitioninblockform: scala>defdouble(x:Int):Int={ | x * 2 |} double:(Int)Int scala>double(6) res3:Int=12 def can also specify a method That = after the Int return type is mandatory. W t i h C++. Forgetting it will cause you trouble.0printing. with a simplefunction: scala>defdouble(x:Int):Int=x double:(Int)Int scala>double(4) res0:Int=8 * 2 Defining a function looks a whole lot like it does with Ruby. After that. you can specify an optional return type. but these are the formsyou’llseemostoften. Y o u l’ see minor variations. Let’s move on to the variables that you’ll use within a function.justusethenameandtheargumentlist. The keyword defines both a function and a method. This is a one-line method definition.D AY 2: C LIPPING B USHES AND O THER N EW T RICKS 154 Anyone with an eye for programming language history has seen this fable played out before. Let’s start from the beginning. Reporterratum thiscopyis (P1.it’stimetoputScalathroughitspacesasafunctionallanguage.Scalacanofteninferthereturntype. Toinvokethefunction.

" mutable:java.butwhileyou’relearning v a r when you can for better concurrency. When you declare variables.. Y o u l’ see an increased emphasis on making Scala friendly for concurrent programming.Lisp.redefining a v a l willgenerate anerror.thatmeansusingthe a l insteadof v a r : immutablemeansusing v scala>varmutable="Iammutable" mutable:java.InScala. v convenience. as a So.InJava. In the console.0printing.String=Iammutable scala>mutable="Touchme. Let’smoveontosomeofmyfavoriteareaswithinfunctionallanguages.lang..String=Iamnotmutable scala>immutable="Can'ttouchthis" <console>:5:error:reassignmenttoval immutable="Can'ttouchthis" ^ a r values are mutable.Oneoftheearliestfunctionallanguages. you can redefine a variable several times even if you use v a l .October2010) .youshouldmakethemimmutablewheneveryoucantoavoid final keyword. these design goals limit the language. Collections Functional languages have a long history of spectacularly useful featuresforcollections. conflictingstate. In some ways. scala>valimmutable="Iamnotmutable" immutable:java. Scala can take advantage of the last fifteen or twenty years of programming language development. it’s best to avoid basicdesignphilosophyisthekeyelementthatdifferentiatesfunctional programming from object-oriented programming: mutable state limits concurrency.D AY 2: C LIPPING B USHES AND O THER N EW T RICKS 155 v a rv e r s u sv a l Scala is based on the Java virtual machine and has a tight relationship with Java. dealingwithcollections.Onceyoustepoutsideoftheconsole. v a r -stylevariablestosupport Insomeways.changeme. Mutable state is bad. But all the concurrency features in the world won’t help you if you don’t follow basic design principles..changeme..lang. v a l values are not. In other ways. The very name stands for Reporterratum thiscopyis (P1.was built around the idea of dealing with lists. This Scala.Scalahadtointroducethe thetraditionalimperativeprogrammingstyle.lang.String=Touchme.

2.NoSuchElementException:headofemptylist atscala. the bread-and-butter data strucList.head(List.Scala’sindexforliststartswith0."two". 3) .Entertheselistsintotheconsole: scala>List(1.D AY 2: C LIPPING B USHES AND O THER N EW T RICKS 156 LISt Processing.two. List access is a function. Unlike Ruby.three) If you’re seeing a little Java influence here..October2010) .andmaps.0printing.reflect.3)(4) java.NativeMethodAccessorImpl. Scala’s primary collections are lists.head(List. Scala’s lists.Nil$.<clinit>(<console>) atRequestResult$result(<console>) atsun."two".3) List[Int] = List(1.Alistof scala>List("one".apply(List. so you use () instead Y o uusethe of [ ]..util. Java has a featurecalledGenerics thatallowsyoutotypetheitemswithinadata structure like a list or array. of type thingswithrandomaccess."three") res5:List[java. Here’showyou’daccessanitemofalist: scala>List("one".two. Functional languages make it easy to build complex structures containing data and code.scala:1362) atscala. accessing an item out of range will throw an exception. 2. are ordered collections of like ture is the list.<clinit>(<console>) atRequestResult$.3) res6:List[Any]=List(one. () operator.3) res4:List[Int]=List(1."two". This value not only Notice the first return value: shows the type of the overall list but also shows the type of the data Stringslookslikethis: structureswithinthelist. Let’s see what happens when you have a listcombining Stringsand Ints: scala>List("one".Nil$.String]=List(one.lang.3) Y o u get the data type Any. Lists As with most functional languages.<init>(<console>:3) atRequestResult$.<init>(<console>:5) at.scala:800) at.2."two". Reporterratum thiscopyis (P1.3)(2) res7:Any=3 scala>List("one".asitdoeswithJavaandRuby. which is the catchall data type for Scala.scala:1365) atscala.invoke0(NativeMet. you’re right.sets.List.

String]= Set(lions. Onefinalnote.3)(-1) res9:Any=one scala>List("one"."bears") animals:scala."two". found :scala.lang.Set[java.D AY 2: C LIPPING B USHES AND O THER N EW T RICKS 157 Y o u can try to index with a negative number."two"."two".bears) Addingorsubtractingfromthatsetiseasy: scala>animals+"armadillos" res25:scala.armadillos) scala>animals-"tigers" res26:scala.Y o uspecifya setwiththe Set keyword: scala>valanimals=Set("lions".0 corrects that behavior.String]=Set(lions.0printing.collection.collection. returning java.bears) scala>animals+Set("armadillos".immutable.October2010) .immutable.Set[java. Nil inScalaisanemptylist: scala>Nil res33:Nil.lang.collection.3)(-2) res10:Any=one scala>List("one". By default.Set[java."tigers".type=List() W e l’ usethislistasabasicbuildingblockwhenwecovercodeblocks.3)(-3) res11:Any=one NoSuchElement excepSincethatbehaviorisalittleinconsistentwiththe tion for an index that’s too large.immutable.bears.immutable.String] required:java.lang.lang. sets Reporterratum thiscopyis (P1. Sets Asetislikealist."raccoons") <console>:6:error:typemismatch.Eachsetoperation builds a new set rather than modifying the old ones.String]= Set(lions.I’mgoingtointroduceacoupleofothertypes ofcollectionsfirst."raccoons") ^ Keepinmindthatsetoperationsarenotdestructive.butsetsdonothaveanyexplicitorder.8. version 2. butfornow.bearwithme.collection.IndexOutOfBoundsException.lang.Set[java. Earlier versions return thefirstelement: scala>List("one".tigers.tigers.lang.String animals+Set("armadillos".

armadillos.String]= Set(bears. but you can’t use the ++ and -.collection.1->one.0.2.Map[Int. Maps A Map isakey-valuepair.October2010) .collection.lions) scala>animals--Set("lions".lang.3)==List(3.8.lang.Set[java. you want to use setdifference: scala>animals++Set("armadillos".immutable.collection.Let’smoveontomaps.tigers. a Set is independent of order.2.String]=Set(tigers) Y o ucanalsoperformsetintersection(elementsintwosetsthatarethe same)with **2 : scala>animals ** Set("armadillos".D AY 2: C LIPPING B USHES AND O THER N EW T RICKS 158 areimmutable."raccoons".because**isdeprecated."raccoons") res28:scala.to combine sets.immutable.1) res37:Boolean=false That’senoughsetmanipulationfornow. In Scala.Asyoucansee.String]= Map(0->zero.HashMap 2.3)==Set(3.lang.lang.for set union and would in Ruby.2->two) scala>ordinals(2) res41:java. Y separate the elements of the map with the o u just used some syntactic sugar that makes it easy to create a Scala map.Thesyntaxshouldbefamil- scala>valordinals=Map(0->"zero".java. Reporterratum thiscopyis (P1.mutable.2.collection.1) res36:Boolean=true scala>List(1.2->"two") ordinals:scala.tigers) Unlike a List.lang.mutable."bears") res29:scala.String=two Like a Scala List or Set.HashMap importscala.0printing.immutable.2.likeaRuby iartoyou: Hash. you specify a Map with the Map keyword."tigers") res1:scala.raccoons."lions".collection. Let’s useanotherformofthehashmapandspecifythetypesofthekeyand value: scala>importscala.Set[java.collection. as you a piece of cake.immutable.addingorremovingasingleelementis + or . This rule will mean that equalityforsetsandlistsisdifferent: scala>Set(1.String]=Set(lions.1->"one".Set[java. Y o u -> operator. Use&beginninginScala2.

you get a typing error. say foracollection. null.D AY 2: C LIPPING B USHES AND O THER N EW T RICKS scala>valmap=newHashMap[Int. Everythinginheritsfrom Any.Bycontrast. so is a trait that is a subtype of everything. but know that any Any.let’sdiveintosomeofthefinerdetails.lang.String] map:scala. Nothing meaninganemptyvalue.MapTo <and>((Int. Next. we declare an ima p .String.Anemptycollectionis Nothing has no instance. Notice that we’re also specifying the types of the keyvaluepairs. It is all laid out in Figure 5. Thereareafewdifferentnuanceswhenyou’redealingwithnilconcepts. in the Scala class hierarchy.weimporttheScalalibrariesforamutable HashMap.and Nothing inheritsfromeverything. AnyandNothing Before we move on to anonymous functions.HashMap[Int.Whenyou’reusingScalawithJava.String))Unitcannotbeappliedto((java.String]= Map(4->four. let’s talk a little bit more abouttheclasshierarchyinScala.8->eight) 159 First.1.Int)) map+="zero"->0 ^ As expected. .0printing.Finally. Any istherootclass youshouldknowalittlebitabouttheScalatypes.Still.weaddsomekey-valuepairsandreturntheresult.Sonowthatyou’ve seenthebasicsforcollections. The type constraints are enforced wherepossibleatcompiletimebutalsoatruntime.collection.Thatmeansthatthe mutablevariablecalled m tothemap r e f e r e n c e cannot change. Null is a T r a t i Reporterratum thiscopyis (P1. That way.October2010) . Here’swhatwouldhappenifyouspecifiedthewrongtypes: scala>map+="zero"->0 <console>:7:error:overloadedmethodvalue+=withalternatives(Int)map. and null is an instance of it that works like Java’s Nil. on the next page. It’s often confusing.collection.canreturn Nothing andconformtothereturnvaluefor the given function. Scalatypewillinheritfrom Similarly.HashMap[Int. youwilloftenbemoreconcernedabouttheJavaclasshierarchy. Nothing is a subtype of every type.Thatmeans the values within the hash map can change.mutable.mutable.String]=Map() scala>map+=4->"four" scala>map+=8->"eight" scala>map res2:scala. a function.

Forexample. List Map Nothing Null Figure5.. As with Ruby and Io.meaningnovalueatall. Just as Ruby used o fr e a c h o fr e a c h .ahigher-orderfunctionisonethatproducesorconReporterratum thiscopyis (P1. Inlayman’sterms.amethodthatthrowsan youcan’tdereferenceitlike Exception hasthereturntype Nothing.Thefirstsuchconceptis higher-orderfunctions . Keep those rules in the back of your mind..1: Any and Nothing Null. you’re ready to do a little bit more with collections using higher-order functions..D AY 2: C LIPPING B USHES AND O THER N EW T RICKS 160 Any AnyVal AnyRef Float Int etc.. Scala will let you pass functions into .October2010) . CollectionsandFunctions As we start on languages that have a stronger functional foundation. and you’ll be fine. ScalaObject etc. Scala collections get a whole lot more interesteach and Io used ing with higher-order functions.0printing. The underlying concept that you’ve been using all along is the higher-order function. Now. I want to formalize some of the concepts we’ve been working with all along.

thoughtheorderwon’tbeguaranteed: hobbit => println(hobbit) valhobbits=Set("frodo".foreach(hobbit=>println(hobbit)) frodo samwise pippin scala>valhobbits=Map("frodo"->"hobbit".Morespecifically. o fr e a c h calls the anonymous function.lang.immutable.butwewilllearntopasssimplefunctions. passingineachelementofthelistasaninputparameter.pippin) scala>list. meaning a function without a name.Y o ucantakeafunction and assign it to any variable or parameter. As with Io.Asyoumight have guessed.samwise.String]=List(frodo. o fr e a c h o fr e a c h Thefirstfunctionwe’regoingtoexamineis . In Scala.0printing. you’ll express that code block in a a r ib e lN a m e=>y o u r C o d e theform v likethis: scala>vallist=List("frodo". Y o u can pass them intofunctionsandreturnthemfromfunctions.asparametersintocollections. W e don’t have time to look at some of the advanced topics such as partially applied functionsorcurrying."pippin") list:List[java.Set[java.October2010) .often called codeblocks . the method on a collection takes a code block as a parameter.String]= Set(frodo.pippin) scala>hobbits. Composing functions that use other functions in this way is a criticalconceptforthefunctionalfamilyoflanguagesandonethatwill shapethewayyoucodeinotherlanguagesaswell."samwise".D AY 2: C LIPPING B USHES AND O THER N EW T RICKS 161 sumesfunctions. "samwise"->"hobbit". The declaration has the arguments to the left of the =>.samwise."pippin") hobbits:scala. Scala has powerful support for higher-order functions.lang."pippin"->"hobbit") Reporterratum thiscopyis (P1.collection. you can use the same technique for sets and maps too.ahigher-orderfunctionisonethat takesotherfunctionsasinputparametersorreturnsfunctionsasoutput.foreach(hobbit=>println(hobbit)) frodo samwise pippin is an anonymous function .theiterationworko fr e a c h horse in Scala.W e r ’e goingtofocuson anonymous functions as input parameters to a few of the more interestingmethodsoncollections."samwise". and the code is to the right.

_2)) hobbit hobbit hobbit W t i htheseanonymousfunctions.hobbit) (pippin.String]= Map(frodo->hobbit.D AY 2: C LIPPING B USHES AND O THER N EW T RICKS hobbits:scala.size res28:Int=3 length and size.foreach(hobbit=>println(hobbit.collection.java. First.Thesebasicmethodsprovidethefeaturesyou’llneedtodomanual iteration or recursion over lists. Reporterratum thiscopyis (P1. As you recall.Also.String]=List(frodo.String.October2010) .isEmpty res24:Boolean=false scala>Nil.length res27:Int=3 scala>list.hobbit) 162 Of course.youcandofarmorethanjustiterate. Noticethatyoucancheckthesizeofalistwithboth Nil isanemptylist.isEmpty res25:Boolean=true scala>list.pippin) scala>list.lang.lang.samwise->hobbit.samwise. here are the methods to test for theemptystateorcheckthesize: scala>list res23:List[java.hobbit) (samwise._1)) frodo samwise pippin scala>hobbits.pippin->hobbit) scala>hobbits. youcanaccesseitherendofthetuple.AswithProlog.foreach(hobbit=>println(hobbit.immutable. maps will return tuples instead of elements.0printing. rememberthattheimplementationof it’susefultobeabletograbtheheadandtailofalistforrecursion.likethis: scala>hobbits.foreach(hobbit=>println(hobbit)) (frodo. I’mgoingtowalkyouthroughsomebasicsandthenafewoftheother interestingwaysScalausesfunctionsinconjunctionwithcollections.lang.Map[java. MoreListMethods I’mgoingtotakeabriefdiversiontointroduceafewmoremethodson List.

reverse res29:List[java.frodo) scala>list.String=pippin scala>list.init res37:List[java.0printing.lang.String]=List(frodo.drop(1) res30:List[java.tail res35:List[java.pippin) scala>list.3.samwise.5) Reporterratum thiscopyis (P1.andOthers AswithRuby.kelly) scala>words.pippin) scala>list.size>2) res44:List[java. Y o u can use head and tail to recurse head first. count.last res36:java.lang.filter(word=>word.samwise) 163 There’s a surprise.and drop(n) returnsthelistwiththefirst removed.lang.String]=List(peg.bud.D AY 2: C LIPPING B USHES AND O THER N EW T RICKS scala>list. create other lists using each elementasaninput.W e l’doalittlemorewithrecursionlater.String]=List(peg.map(word=>word.String]=List(samwise. n elements invertedordering. Let’swrapupthebasicswithafewinterestingconveniencemethods: scala>list.size) res45:List[Int]=List(3.samwise.October2010) .head res34:java.filter.pippin) scala>list res31:List[java.drop(2) res32:List[java.andcreateaggregatevalues: scala>valwords=List("peg".lang.withoutmodifyingtheoriginallist.lang.String]=List(pippin) reverse returns the list with These do just about what you’d expect.size>2) res43:Int=3 scala>words.String]=List(pippin."bud".String=frodo scala>list.String]=List(frodo."al". Y o u can filter the list to match a given condition. sort a list using whatever criteria you want.count(word=>word.lang.al.lang.lang.2. or last and init torecursetailfirst.map.lang.lang.String]=List(samwise.kelly) scala>words."kelly") words:List[java.bud.Scalahasmanyotherfunctionsthatmanipulatelistsin various ways.

. Reporterratum thiscopyis (P1. Sometimes.0. o r d s . you may want to sort in the traditionalway: scala>words. Inversion2. In the 4 previous code.peg) s and t.lang. For example.wecansort basedonanypolicythatwewant.Using wordsthathaveasizegreaterthantwo.bud. o returns true if the code block returns set.lang. inject method in Ruby.muchlikeRuby’s a p builds a list of the sizes of all the words in the the same pattern.October2010) .t)=>s. s z ie > 2) In the same way.D AY 2: C LIPPING B USHES AND O THER N EW T RICKS scala>words.0. 5.bud. sort. 3.Use toLower instead.peg. o fd lL e f t will pass to the Inversion2. sort isdeprecated. toLowerCase isdeprecated.size) res50:List[java.0printing. you can generalize a feature using code blocks to make something more powerful. The count methodcountsallthe true expressions.toLowerCase<t.Use sortWith instead.8.toLowerCase) res49:List[java.forall(word=>word. we count all the words with a size w o r d => w o r d . Using This code uses a code block that takes two parameters. count will call the code block o r d .8.kelly.and exists returns true ifthecodeblockreturns true foranyitemin theset. m fr a l true for all items in the list. Then.size>5) res48:Boolean=false 164 W e start with a Scala list. o fd lL e f t Let’stakealookatamorecomplexexample.0.Use sortWith instead.exists(word=>word. w returns a list of all select.kelly) 5 Byusingacodeblock.t)=>s.String]=List(al. That will yield a case-insensitive search. .size<t. sort isdeprecated.exists(word=>word.3 you can compare the two arguments any way you want. 4.sort((s. s z ie > 2 evaluating the expression w for each element in the list. W e can also use the samemethodtosortthelistbythesizeofthewords: scala>words. Inversion2.charAt(0).size>4) res47:Boolean=true scala>words.charAt(0).String]=List(al. s z ie > 2 greater than two. fi t e lr ( w o r d => w o r d .size>1) res46:Boolean=true scala>words.8. o fd lL e f t The o method in Scala is much like the fd lL e f t Y o u l’supply an initial value and a code block.sort((s. we convert the characters to lowercase and compare them.

/: takes 1. The second value is either the initial value (for the first invocation) or the result from the code block (for subsequent invocations).butitmayhelpyoutosee itagain.2.3) list:List[Int]=List(1. i is 1. /:codeBlock . sum is 1. list. Just understand that what’s going on under the covers is a composition of functions rather than a single function.So. the result is exactly thesame: scala>vallist=List(1. • Next. sum and i.0printing. i isthenext foldsitbackintothecalculationas elementof list. the result returned from the code block. /: takestheinitialvalue. 1.2.3) scala>list.2. o fd lL e f t The syntax of the other version of will seem strange to you. mentof list.value)=>sum+value) res54:Int=6 Reporterratum thiscopyis (P1. on page 268. and sum. There are two ver/:.theresultreturnedfromthecodeblock.and sum+i is 6.3) list:List[Int]=List(1. i is the next eleit back into the calculation as 3. The code blocktakestwoarguments.3) scala>valsum=(0/:list){(sum.foldLeft(0)((sum. /: takes 3.andfolds sum. • Initially.D AY 2: C LIPPING B USHES AND O THER N EW T RICKS 165 code block each element of the array and another value. Functional languages use currying It uses a concept called to transform a function with multiple parameters to several functions with their own parameter lists.isanoperatorwith initialValue sionsofthemethod. sum is 3. 0.andtheresult andpassesthemintothecodeblock.andtheresultofthecodeblockis • Finally.andthefirstelementof sum is 0.i)=>sum+i} sum:Int=6 W e walkedthroughthissequenceforRuby.or 3. W e l’ see more currying in Chapter 8.Here’sthemethodinaction: scala>vallist=List(1.Thefirstversion.October2010) . Though the mechanics and syntax are different. Haskell . currying. So.Here’showitworks: •W e invoke the operator with a value and a code block.2.or 2. of 0+1 is 1.

Theseexerciseswillletyouusesomeof thecollections.W e willput these skills through their paces in day 3. Much of functional programming is learning to manipulate collections withhigher-levelconstructsinsteadofJava-styleiteration.Alistisanorderedcollection. just like Prolog.Butthemostpowerfulmethodstookfunctionblocks.foldLeft(0)((sum.andworkasimplepracticalexample.yousawthepowerful combinationsofcodeblocksandcollectionsofvariouskinds.welookedatvariouscollections. 166 has WhatW eLearnedinDay2 Day 1 was encumbered with working through the object-oriented featuresthatyoualreadyknow. to return the first element of the list or the rest.Asetisacollectionofobjects. That’s the currying concept that I mentioned earlier.mapsarekey-valuepairs.maps.W e alsolearnedtouse o toaccumulateresults asweiteratedthroughacollectiontodothingssuchaskeepingarunningtotal.Stay tuned.and first methodsforobviouspurposes.Wheneveryoudealwithfunctions. and the parameter list can vary. W e also used count.Day2introducedScala’sprimaryreason forbeing:functionalprogramming.aswellassomefunctions. W estartedwithabasicfunction. when we will learn to use concurrency. Finally. Reporterratum thiscopyis (P1. we could also use Lisp-style head and tail methods.AswithRuby. Day2Self-Study Now that we’ve gotten deeper into Scala.v a u le )=>sum+v a u le ) Noticethatthefunctioncall two parameter lists.Y o u l’seeversionsofthismethodwithalltherestofthelanguages inthisbook. For lists. fr e a c h W e iteratedwith o andused filter toselectivelyreturnvariouselefd lL e f t mentsofthelists.W elooked at some collection APIs that are indicative of functional programming paradigms.Scalahasflexiblesyntaxwithfunction definitions. you’re starting to see some ofitsfunctionalaspects.D AY 2: C LIPPING B USHES AND O THER N EW T RICKS list.October2010) . andsets. the function body has one-line and code-block forms.0printing. empty.Scalasupportsthree:lists.dosomeXML. Next.thecollectionsareagreatplacetostart. The compiler can often infer the return type.

become almost routine. Hard things. Scala takes the dramatic step of elevatingXMLtoafirst-classprogrammingconstructofthelanguage. like XML and concurrency. Censor traitwithamethodthatwillreplacethecursewords •W r t i ea Shoot and Darn with Pucky and Beans alternatives. Reporterratum thiscopyis (P1.xml.Y o u canexpressXMLjustaseasilyasyoudoanystring: scala>valmovies= |<movies> | <moviegenre="action">PiratesoftheCaribbean</movie> | <moviegenre="fairytale">EdwardScissorhands</movie> |</movies> movies:scala. it’s borderline spectacular.D AY 3: C UTTING T HROUGH THE F LUFF 167 Find: • AdiscussiononhowtouseScalafiles • Whatmakesaclosuredifferentfromacodeblock Do: fd lL e f t • Use o tocomputethetotalsizeofalistofstrings.0printing.Useamapto storethecursewordsandtheiralternatives. and even carves the family roast. you can access differentelementsdirectly.October2010) .craftsspectacularhairwiththeeffortlessskillofV d ia lSassoon. He molds shrubs into dinosaurs. W t i h Scala.Elem= <movies> <moviegenre="action">PiratesoftheCaribbean</movie> <moviegenre="fairytale">EdwardScissorhands</movie> </movies> After you’ve defined the movies variable with XML. we’ve encountered some awkward moments.4 Day3:CuttingThroughtheFluff Justbeforetheclimaxof EdwardScissorhands . 5. but when this language feels right. • Loadthecursewordsandalternativesfromafile.Edwardlearnstowield his scissors as an artist in everyday life. XML Modern programming problems meet Extensible Markup Language (XML) with increasing regularity.Let’stakealook.

xml. but yougettheidea.W e canbemoreselective. Scalabuildsinaquerylanguagethat’smuchlikeXPath.anXMLsearch language.IfwemixinProlog-stylepatternmatching.Scalawillusepatternmatchingoften.thingsget a little more exciting. we’ll walk through an example of pattern matchingwithsimplestrings. But since the // keyword in Scala is a comment. you’d use one backslash.toseealltheinnertext.Butwe’renotlimitedtoworkingwiththewholeblockatonce. Next.youwouldsimplytypethis: scala>movies.suchaswhenyou parseXMLorpassmessagesbetweenthreads.we’ddothissearch: scala>movieNodes(0)\"@genre" res4:scala. P a t e r nMatching Pattern matching lets you conditionally execute code based on some pieceofdata. likethis: scala>valmovieNodes=movies\"movie" movieNodes:scala. To search the top-level nodes.0printing.xml.Y W e justfoundelementnumberzero.text res1:String= PiratesoftheCaribbean EdwardScissorhands Y o useealltheinnertextfromthepreviousexample. Y o u vidualnodesbyindex: can find indi- scala>movieNodes(0) res3:scala.D AY 3: C UTTING T HROUGH THE F LUFF 168 Forexample.Node=<moviegenre="action">PiratesoftheCaribbean</movie> PiratesoftheCaribbean . to find the document.October2010) .or o ucan @ symalso look for attributes of individual XML nodes by using the genre attribute of the first element in the bol. we looked for XML movie elements. For example. Reporterratum thiscopyis (P1. Scala will use \ and \\.NodeSeq=action This example just scratches the surface with what you can do.xml.NodeSeq= <moviegenre="action">PiratesoftheCaribbean</movie> <moviegenre="fairytale">EdwardScissorhands</movie> In that search.

complain" } println(doChore("cleandishes" )) println(doChore("mowlawn" )) W e define two chores. Scala executes the strings.Y o ucanspecifyawidevarietyofconditionsinthisway.butthesecondguardhastheform casex Thefirstpatternmatchisa ifx>0 . the code blocks simply return _. Y o u l’ see an example later that defines empty classes and usesthemasmessagesinourconcurrencyexampleslater.InProlog. RegularExpressions . complain”ifneitherchorematches.D AY 3: C UTTING T HROUGH THE F LUFF 169 Here’sthesimplestformofpatternmatching: Download scala/chores. clean dishes and cook dinner .wespecifyaconditioninaguardforeach Download scala/factorial. we have a code block.The translate any string to a regular expression.thepattern matching often had associated conditions. In this case. On the next page is an exampleofaregularexpressionthatcanmatchuppercaseorlowercase F atthebeginningofastring.0printing.scala scrub.dry" case "cookdinner" => "chop. Next to each chore. To implement a factorial in m a t c h statement: Scala. a wildcard.dry whine.October2010) .complain Guards Patternmatchinghassomeembellishmentstoo.Patternmatchingcanalsomatchregularexpressions and types. Reporterratum thiscopyis (P1.scala deffactorial(n:Int):Int=nmatch{ case0=>1 casexifx>0=>factorial(n-1) } println(factorial(3)) println(factorial(0)) * n 0.Itmatchesany x for x>0 . The last chore we define is codeblockassociatedwiththefirstmatchingchore.sizzle" case_=> "whine.returning“whine.r methodonastringcan Scalahasfirst-classregularexpressions.scala defdoChore(chore:String):String=chorematch{ case "cleandishes" => "scrub.likethis: >>scalachores.

The verts the string to a regular expression.scala valmovies=<movies> <movie>TheIncredibles</movie> <movie>WALLE</movie> <short>JackJackAttack</short > <short>Geri'sGame</ short> </movies> (movies\ "_" ).That’sreallyallthereistoit.Regex=^(F|f)\w 170 * scala>println(reg. Forexample.r reg:scala. XMLwithMatching AninterestingcombinationinScalaistheXMLsyntaxincombination withpatternmatching. .Y o u canmatchwithregularexpressionsjustasyouwoulduseastring. we build a regular expression and use the the inthestring "thew a ythe methodtofindalloccurrencesoftheword scissorstrimthehairandtheshrubs" . W e usethe """ delimitedformofastring.considerthefollowingXMLmoviesfile: Download scala/movies.Ifwewanted.Regex.util.matching.matching.util.October2010) .util.r reg:scala. scala>valreg="the".findFirstIn("notFantastic")) None W e startwith asimple string.Y o ucangothroughanXMLfileandconditionally execute code based on the various XML elements that come back.findAllIn("thewaythescissorstrimthehairandtheshrubs") res9:scala.Regex=the scala>reg.MatchIterator=non-emptyiterator findAllIn In this example. W e then use the method findFirstIn tofindthefirstoccurrence.wecoulditeratethrough o fr e a c h theentirelistofmatcheswith .matching.r methodconallowingmultilinestringandeliminatingevaluation.foreach{movie=> moviematch{ case<movie>{movieName}</movie>=>println(movieName) case<short >{shortName}</short>=>println(shortName+ } } "(short)" ) Reporterratum thiscopyis (P1.D AY 3: C UTTING T HROUGH THE F LUFF scala>valreg="""^(F|f)\w *""".0printing.findFirstIn("Fantastic")) Some(Fantastic) scala>println(reg.

that’s a basic tour of pattern matching.Actorshavepoolsofthreadsandqueues.start vallisa=newKid().. So.scala importscala." ) println("Quitit.Whenyousendamessagetoan actor(usingthe ! operator)..Theresultisalmosteffortless..October2010) . I like the way Scala makes the most common tasks trivial by working in XML syntax. Y o u l’ see it in practice in theconcurrencysectionnext..start println("Readytopokeandfeed.0printing. Considerthe kids program: Download scala/kids.. Then._ importscala.Actor. pattern matching." ) println("Burp.Theprimaryconstructsareactorsandmessagepassing." bart!Poke lisa!Poke bart!Feed lisa!Feed ) Reporterratum thiscopyis (P1.youplaceanobjectonitsqueue.. Concurrency One of the most important aspects of Scala is the way it handles concurrency.actors." ) } } } } } valbart=newKid(). it uses pattern matching to match shorts and movies._ caseobjectPoke caseobjectFeed classKid()extendsActor{ defact(){ loop{ react{ casePoke=>{ println("Ow. and theXQuery-likelanguage.actors. the actor uses a pattern matcher to detect the message and perform the appropriate message." ) } caseFeed=>{ println("Gurgle. Often...Theactor reads the message and takes action.D AY 3: C UTTING T HROUGH THE F LUFF 171 It queries for all nodes in the tree...

Theydon’tdoanything. we would like to get all of Reporterratum thiscopyis (P1.. Quitit. Ow. Since there’s a lot of waiting time.. let’s do sizer.... you can also reactwithatimeout( reactWithin). I run the application a couple of times to show that it is actually concurrent.. W t i h n i that is a react construct..October2010) .wecreatetwoempty.whichwilltimeoutifyoudon’treceive receive themessagewithinthespecifiedtime... Gurgle... Gurgle..scala Readytopokeandfeed.Theysimplyserveasmessages.scala Readytopokeandfeed. which will always be P o k e or F e e d .trivialsingletonscalled F e e d . Gurgle. Burp. Kid isanactor.. batate$scalacode/scala/kids.. Quitit. Ow.Themeat Kid class. Notice that the order is different... It will process each message and move on to the next..Additionally.....youcanuse (whichblocksathread)and receiveWithin (whichblocksathreadwitha timeout)..W e hitafewpagesandthencompute the size. Ow. react receives an actor’s messages... Gurgle. The pattern match lets us match the appropriate message... Ow. Burp. In this application called computingthesizeofwebpages..D AY 3: C UTTING T HROUGH THE F LUFF P o k e and Inthisprogram. Quitit. W e start a simple loop. Burp. W t i h actors. Quitit....meaningitwillrunfrom oftheprogramisthe a pool of threads and get messages in a queue. we’re something a little more robust.Y sendingthem P o ucanrunitlikethis: batate$scalacode/scala/kids.0printing. Burp. 172 Therestofthescriptcreatesacoupleofkidsandmanipulatesthemby o k e or F e e d messages..... ConcurrencyinAction Since there’s only a limited market for simulated Simpsons...

0printing. "http://www.getPageSize(url))} } for(i<-1tourls.com/" ) deftimeMethod(method:()=>Unit)={ valstart=System.Take alookattheoverallprogram._ objectPageLoader{ defgetPageSize(url:String)=Source. "http://www._ importActor. "http://www.mkString.fromURL(url).getPageSize(url)) +url+ ":" +size) Reporterratum thiscopyis (P1.io." ) +PageLoader.length } valurls=List( "http://www.scala importscala.nanoTime println("Methodtook" +(end-start)/1000000000.October2010) .com/" .0+ } defgetPageSizeSequentially()={ for(url<-urls){ println("Sizefor" +url+ ":" } } defgetPageSizeConcurrently()={ valcaller=self for(url<-urls){ actor{caller!(url.cnn.twitter._ importscala.size){ receive{ case(url.google.nanoTime method() valend=System.actors. andthenwe’lllookatsomeindividualsections: Download scala/sizer.amazon.D AY 3: C UTTING T HROUGH THE F LUFF 173 thepagesconcurrentlyusingactors.com/" .com/" .size)=> println("Sizefor" } } } println("Sequentialrun:" ) timeMethod{getPageSizeSequentially} println("Concurrentrun" ) timeMethod{getPageSizeConcurrently} "seconds.PageLoader.

weknowwe’llbereceivingafixedsetofmessages.Thishappensmore receive.we sendfourasynchronousrequests.Next.W t i h n ia o fr E a c h loop.nanoTime method() valend=System.mkString. defgetPageSizeSequentially()={ for(url<-urls){ println("Sizefor" +url+ ":" } } +PageLoader.PageLoader.let’sstartatthetop.webuildamethodto Next.givenaURL: objectPageLoader{ defgetPageSize(url:String)=Source. or less instantly.Afterthat.fromURL(url).we willcomputethesizeofapage. we do the web requests with two different methods. Finally.nanoTime println("Methodtook" +(end-start)/1000000000. we’re ready to runthescriptthatinvokesthetest: println("Sequentialrun:" ) timeMethod{getPageSizeSequentially} Reporterratum thiscopyis (P1.getPageSize(url))} } for(i<-1tourls.October2010) . we simply receive four messages with This method is where the real work happens.0printing.length } a l withafewURLs.getPageSize(url)) Here’sthemethodtodothingsasynchronously: defgetPageSizeConcurrently()={ valcaller=self for(url<-urls){ actor{caller!(url.wecreatea v timeeachwebrequest: deftimeMethod(method:()=>Unit)={ valstart=System.D AY 3: C UTTING T HROUGH THE F LUFF 174 So." ) Then.size){ receive{ case(url. The first is o fr E a c h sequentially.0+ } "seconds.W e doafewbasicimportstoloadthelibraries for actors and io sowecandoconcurrencyandHTTPrequests. Next.whereweiteratethrougheachrequestina loop.size)=> println("Sizefor" } } } +url+ ":" +size) Inthisactor.

we had an inner patternmatch. we could just add naked attributes to our class definitions. distributedmessagepassingwithactors. As expected.welearnedtouseXMLdirectlyinScala. If we needed parameters within the message. it case statement. Concurrentrun Sizeforhttp://www.andregular expressions.andregularexpressions. the concurrent loop is faster.com/:100739 Sizeforhttp://www.theirpowerbecamereadilyapparent. Overthecourseofthechapter.google. looked like a simple types.October2010) . Next.scala Sequentialrun: Sizeforhttp://www.com/:81002 Sizeforhttp://www.twitter.First.com/:8076 Sizeforhttp://www.twitter. W e then introduced Scala’s version of pattern matching.light.Theyaresmall.com/:44158 Methodtook3. aswedidwiththeURLwithinthesizerapplication.amazon.amazon.W e usedrawclassesasmessages. but as we introduced guards.969936seconds. Reporterratum thiscopyis (P1. W e built a couple ofdifferentconcurrentprogramsandworkedindirectXMLprocessing. we shifted to concurrency. They usually have a wrapped around a react or receive method.patternmatching. W e couldqueryforindividualelementsorattributesusinganXQuerylikesyntax.com/:84600 Sizeforhttp://www.707612seconds. Actors loop statement are objects built for concurrency. That’s an overview of an interestingprobleminScala. it made up in intensity. At first.com/:100739 Methodtook6.google. robust. Finally.cnn.D AY 3: C UTTING T HROUGH THE F LUFF println("Concurrentrun" ) timeMethod{getPageSizeConcurrently} 175 Andhere’stheoutput: >>scalasizer.Let’sreviewwhatwelearned.cnn. and easy to manipulate.welearnedfourfundamentalconstructs thatbuiltononeanother.com/:8076 Sizeforhttp://www. WhatW eLearnedinDay3 What day 3 lacked in size.0printing. W e used the actor concept.com/:43640 Sizeforhttp://www. which does the dirty work of receiving queued messages to the object.

I haven’t covered constructs such as currying. Reporterratum thiscopyis (P1.andI’vemerelyscratchedthesurfaceoncomplex conceptssuchascurrying.asizerfor“google. Now. Scala borrows many elements from Java.W RAPPING U P S CALA 176 Like all of the languages in this book.Forexample.Butyouhaveagoodfoundationshouldyou choosetoexplorefurther. The object-oriented features firmly position Scala as a Java alternative. The interaction with Java classes is far deeper than I’veshownyouhere. Scala is far more robust than you’ve seen here. or exception processing.whatwouldhappenifyoudidnotcreatea newactorforeachlinkyouwantedtofollow?Whatwouldhappen totheperformanceoftheapplication? Do: • Take thesizerapplicationandaddamessagetocountthenumber oflinksonthepage. Syntactically.com”would computethesizeforGoogleandallofthepagesitlinksto. As always. 5. andloadthemaswell. but they are all worthy conceptsthataddtothepowerandflexibilityofScala. including curly braces and constructorusage. • Forthesizerprogram. fitting a wide variety of enterprise applications currently implemented intheJavalanguage. Find. Scalaalsooffersstrongsupportforfunctionalconceptsandimmutable variables.October2010) . you can try to put Scala through its paces yourself. The language has a strong focus on concurrency and XML. full closures. theseexercisesaremoredemanding. • Bonus problem: Make the sizer follow the links on a given page. Scala’sfunctionalcapabilitiesgobeyondwhatI’vecoveredinthischapter. multiple parameter lists. Scala has a static typing strategy. Unlike Ruby and Io. Day3Self-Study So.0printing. now you’ve seen some of the advanced features Scala has to offer.5 WrappingUpScala W e v ’e covered Scala more exhaustively than the other languages so far because Scala stronglysupportstwo programming paradigms.

andthatideahasvalue.Inferredtypingisamuch-neededadvanceoverthearchaic Javatypingsystem.theinteroperability isexcellent.0printing. Immutability is the single most important thing you can do to improve code design for concurrency. The actor model and the thread pool are welcome improvements. Code blocks are a first-class language construct. W t i h these Reporterratum thiscopyis (P1. allowing mutable state but also offering libraries and keywords that support immutability. you must strive for immutable values. It is a significant improvement overthestandardJavathreadinglibraries.Let’sget righttothelist.October2010) . built-in user base: the Java community.Inparticular. When objects share state.W RAPPING U P S CALA 177 Let’slookatsomeofScala’scorestrengthsandweaknesses. ScalaapplicationscanuseJavalibrariesdirectly.andthroughtheuse ofcodegenerationofproxyobjectswhennecessary.actors.andtheXMLintegrationareimportantandwell-designed.themessage-passingsyntaxyouseeinScalaismuchlikeyou will see in the next chapter on Erlang. and they work well with the core collection libraries.patternmatching. and the ability to design applications without mutablestateisabsolutelyhuge. EvolutionofLegacyJ a v a Scala starts with a strong. The concurrency model is only part of the story. Pattern matching is also a significant improvement. The actor paradigm that you’ve seen in Io and now Scala is easy to understand for developers and well studied by the academic community.ScaladoesagoodjobofferingamoreconciseJava. Finally.BothJavaandRubycouldusesomeimprovementinthisarea. Io and Scala get this at least partially right. CoreStrengths Most of Scala’s strengths are centered around an advanced programming paradigm that integrates well with the Java environment and somecorewell-designedfeatures. Concurrency Scala’s treatment of concurrency represents a significant advance in concurrent programming.Thebestwaytoestablishanewprogrammingcommunityistofullyembraceanexistingone. Scala also offers new features to the Java community. Scala also offers first-class mixins in the form of traits.

I find the syntax demanding and academic.andsemicolonsletthesyntaxtakemanydifferentforms. XML ScalahasintegratedXMLsupport. periods.thesearethetoolsthataDSLdeveloperseeks.October2010) . as in Ruby. Remember.Scaladeliversonthispromise. Thepatternmatchingmakesparsing blocks of disparate XML structures easy to use. W e a k n e s s e s Although I like many of the Scala ideas in concept. Additionally.Abetterprogramminglanguageshould allowyoutoexpressmorecomplexideaswithfewerlinesofcode. especially to theXML-heavyJavacommunity. Scalaiswell-positionedtobethatbridge.0printing. Java developers can have an advanced programming language without even touching the more advanced functional paradigms. and evolving processor designs are much more concurrent. Domain-SpecificLanguages Scala’s flexible syntax and operator overloading make it an ideal language for developing Ruby-style domain-specific languages.with minimaloverhead. Throw in the functional constructs. operators are simply method declarations. and you can have significantly improved applications. Scala doeshaveahigherburdenthanmostotherlanguages. Reporterratum thiscopyis (P1. I only see three weaknesses.Together withrobustmixins. optional spaces. Scala applications will usually have a fraction of the total lines of code than an equivalent Java app would have. and you can override them in most cases. Bridging The emergence of each new programming paradigm needs a bridge. Although syntax is a matter of taste.W RAPPING U P S CALA 178 and other features.IalsorecognizethatsomeofthecompromisesthatmakeScala such an effective bridge also will undercut its value.atleasttothese oldeyes.Thefunctionalprogramming model is important because it handles concurrency well. This advance is welcome and important. The integration of theXPathsyntaxfordivingdeepintocomplexXMLleadstosimpleand readable code.buttheyarebigones. andthat’sextremelyimportant. Scala offersan iterative waytotakedevelopersthere.

Laterinthisbook. Scala introduces a new convention.statictype systemlookslikewithHaskell. At other times. such as constructors. but some elements are a little baffling.theJavadeveloperinmegreatlyappreciatesthe Reporterratum thiscopyis (P1. the burdenismuchmorethanyoueverexpect.AsIlearnedScala.W t i h o u ttheburdenoftwoprogramming paradigms.InJava. Sometimes.new.astheyarewithJava. as with setName(Stringname) versusScala’s argumenttypes. a r . but I found the trade-off between programmerflexibilityandcompile-timecheckingwanting.Ifoundmyselfin afairlyconstantbattlewiththelanguagesyntaxandinprogramdesign. Syntax I do find Scala’s syntax to be a little academic and hard on the eyes. I hesitate to put this in print because syntax can be so subjective. Scala keeps Java cone r s o n e r ventions.myexperiencewithScalawasmixed. FinalThoughts Allinall. you must satisfy a compiler’s requirements by putting more of a burden on your developers. The problem is that moving back and forth between Scala and Java will take more effortthanitshould. Return types shift to the end of the method declarationversusthebeginning.Thestatictypingthrew me.Theselittledifferences keep me thinking about syntax rather than code.W RAPPING U P S CALA 179 StaticTyping Static typing is a natural fit for functional programming languages.you’llseewhatapurelyfunctionalstrong.October2010) . Traits eased this burden somewhat. providingbettersupportforpolymorphismandrequiringlessrigorfrom programmersforsimilarbenefit. W t i h static typing. Y o u d ’ use new P rather than P son.thetypesystembecomesmuchmorefluidandproductive. One significant compromise in Scala is the introduction of mutability.becausethemutable W t i h v stateallowsawidevarietyofconcurrencybugs. you must factor in compromises. Sometimes.ScalaopensPandora’sboxinsomeways.syntax.you’duse setName(name: String) .Theimpactoncode. andprogramdesignareprofound. but Java-style static typing for object-oriented systems is a deal with the devil.0printing.Atthesametime. Mutability When you build a bridge language.Butsuchcompromises areunavoidableifyouwanttobringhomethespecialkidwholivedin thehouseonthehill.

0printing. and XML. this Frankenstein has a good shot because it represents a bridge and fully embraces a significantprogrammingcommunity. I’d also consider Scala for an application that has significant scalability requirements that would require concurrency.W RAPPING U P S CALA 180 improved concurrency models.October2010) . Commercially. I would use Scala to improve my productivity if I had a significant investment in Java programs or programmers. Reporterratum thiscopyis (P1. inferred typing. Scala representsasignificantjumpinthestateoftheart.

Lana W a c h o w s k . In 1986. called BEAM.Mr. i 1999. continuing to develop and polish it through the last half of the decade.1 The Matrix was a 1999 science-fiction classic that painted our current world as a virtual world. Agent Smith was an artificial intelligence program in the matrixthathadanamazingabilitytotakeanyformandbendtherules ofrealitytobeinmanyplacesatonce. Burbank.Y o ucouldcallitefficient. . Through the 1990s. is rivaled only by the Java virtual machine for robust enterprise deployment. AgentSmith Chapter 6 Erlang FewlanguageshavethemystiqueofErlang. i CA:W a r n e rHomeV d ie o .AgnerKarup Erlang was a huge name in the math behind telephone network analysis. evenbrutallyso. Think AgentSmithof TheMatrix . it grew in fits and starts and gained still more traction in the 2000s.Hewasunavoidable.Itsvirtualmachine.ErlangalsopowersFacebook’schat. 6. Directed by Andy W a c h o w s k .but Erlang’s syntax lacks the beauty and simplicity of.1 IntroducingErlang The name is strange. say. a Ruby. but the acronym for Ericsson Language that sharesanamewithaDanishmathematiciansomehowfits.Anderson?Thatisthesoundof inevitability. Joe Armstrong developed the first version at Ericsson. The Matrix . as an illusion.2007.Doyouhearthat. DVD.ThebuzzforErlangisgrowingsteadilybecauseit 1.theconcurrencylanguage thatmakeshardthingseasyandeasythingshard.populardatabasesforcloud-basedcomputing. created and maintained with computers. It is the language behind CouchDB and SimpleDB.

like Java and C.Erlang’screatorsspentefforttosimplifythecreation.andyoudon’thavetotake Erlang down to replace entire modules. take a threading approach to concurrency.management. Reporterratum thiscopyis (P1.threadingsystemsrequire semaphores. Many threads make up a process.One common debate is whether threads or processes lead to better concurrency. Erlang can support insanely reliable systems. so theoretically.thoughimplementationsvary. Some of its applications have run for years without ever coming down for maintenance. Ericsson studiedprogramminglanguagesthroughthe1980sandfoundthat. Concurrencyexpertsdonotalwaysagreeonthebestapproaches. or operating system level locks. The systems often could not be taken down for maintenance. LightweightProcesses Rather than wade through the quagmire of shared resources and resourcebottlenecks. Processes have their own resources. Usually.I NTRODUCING E RLANG 182 provides what many other languages can’t: scalable concurrency and reliability. These requirements eventually led to the development of an entirely newlanguage.October2010) . and software development was prohibitively expensive.Erlangembracesthephilosophyoflightweightprocesses. Erlang is a functional language—one with many reliability features cooked in. you should be able to get better performance from them. Erlang takes a different approach. threads have their own execution path but share resources with other threads in the same process. a thread is lighter weightthanaprocess.forone reasonoranother. buggy implementations and the need for locks that form bottlenecks. Builto f rConcurrency ErlangisaproductofyearsofresearchfromEricssontodevelopnearreal-time fault-tolerant distributed applications for telecom applications. Y o u can’t takeaphoneswitchdownformaintenance. The downside to threads is that shared resources can lead to complex. Threads take fewer resources.existinglanguageswereinadequatefortheirneeds.0printing. But the key Erlangcapabilityisconcurrency. To coordinate control betweentwoapplicationssharingresources. NoThreading Many languages.Ittriestomakeprocessesaslightweightaspossible. and communication within applications with many processes.

Dr. The processes that you spawn are lightweight. The language isheavilyslantedtoremovesideeffectsandmutability.whichissimilartoErlang’smessagepassing.” Since Erlang makes it easy to monitor the death of a process.I’vehadthechancetomeetsomeofthepeoplewhoIrespectthemost.Thiscapabilityallowsfarsimpler maintenance strategies than similar distributed applications. The Erlang mantra is “Let it crash. Reporterratum thiscopyis (P1.October2010) .throughemail. Armstrong’s creation uses actors for concurrency. Like Io. Y o u l’ recognize Scala’s message passing syntax. Reliability Erlang does have traditionalerror checking. InterviewwithDr.I NTRODUCING E RLANG 183 Distributedmessagepassingisabasiclanguage-levelconstruct.but in a traditional application.Sweden. It’s easy to see how some applications run for years at a time withoutdowntime.monitoringaprocess—are all there.InErlang. so you don’t have to worry about constrained resources in this area. the Erlang concurrency story is compelling. The important primitives—messagepassing.Theactorreadsinboundmessagesfrom aqueueandusespatternmatchingtodecidehowtoprocessit.andmonitoring thedeathofaprocessissimple.InScala. Erlangcombinestherobust“Letitcrash”errorstrategieswithhot-swapping and lightweight processes that you can start with minimal overhead.Thecombinedpackageis compelling.atleast. killing related processesandstartingnewonesaretrivialexercises. meaning you can replace pieces of your applicationwithoutstoppingyourcode.JoeArmstrong Throughwritingthisbook.JoeArmstrong. I finally got to have several conversations with Erlang’s first implementor. Y o u can also hot-swap code. So.0printing. who hails from Stockholm.backedbyathreadpool.spawningaprocess. is high on that list for me.eventrivial.anactor representsanobject.anactorrepresentsalightweightprocess. so message passing is a critical concept. ProgrammingErlang:SoftwareforaConcreatorofErlangandauthorof current W o r d l [Arm07].you’llseefarlesserrorhandlingthanyouwouldinatraditional fault-tolerant application.eliminatingtheneedforlockingandimprovingconcurrency.

The whole notion of “nondefensive” programming and “Let It Crash. this set ofchangestoPrologacquiredaname.higher-ordermodules. Bruce: Whatisafeatureyoumostwouldwanttochange.” which is the mantra of Erlang programming.andanewlanguagewas born.Atthetimewewantedtofindabetterwayofwritingthe controlsoftwareforatelephoneexchange...RightnowIthinkit wouldber e a y l nicetogobacktotherootsofErlangandaddProlog-like predicate logic to the language.October2010) . is completely the opposite of conventional practice. how thingsevolve. Armstrong: This is a difficult question.Erlang. Bruce: Whatdoyoulikeaboutitthemost? Dr. a kind of new mixture of predicate logic plusmessagepassing. I’d probably give a lot more thought to how we fit things together. I’d probably give different answersondifferentdaysoftheweek. If I were to do it all over again.0printing.andsoon..weaddedmorestuffandgotsomemoreusers.whatarethegreatestlimitationsofErlang?) Dr.wefigured outhowtocompileit. Error handling is one of the leastunderstoodpartsofthelanguageandthepartwhereitmostdiffers from other languages.ifyoucould doitalloveragain?(Alternatively.Istartedfiddlingaroundwith Prolog.Whenlotsofcodehasbeenwritten. I wrote a Prolog meta-interpreter that added parallel processes to Prolog. “I wonder what would happen if I changed the way Prolog does things?” So. I thought. I didn’t set out to invent a new programminglanguage. So. I started messing around with Prolog. such as how we run big projects with lots of code—how we manage versions of code. After a while.W ecandothis inlibrarycode.theprogrammer’sjob Reporterratum thiscopyis (P1. Armstrong: Theerrorhandlingandon-the-flycodeupgrademechanisms and the bit-level pattern matching.butit’snotsupportedinthelanguage. and so on. Prolog was fantastic but didn’t do exactly what I wanted.thelanguagegrew.I NTRODUCING E RLANG 184 Bruce: WhydidyouwriteErlang? Dr. adding hashmaps.youcouldanswer. and then I added error handling mechanisms. how we find things. Armstrong: By accident. but it leads to r e a y l short andbeautifulprograms.Thenmorepeoplejoinedtheproject.and . Then there are a number of small changes that are desirable.Itwouldbenicetoaddmobilityto thelanguagesowecouldsendcomputationsovertheNet.

anddistributedmessagepassinginScala. but don’t fight it.This was to support CouchDB.This chapterwillstartwithanotherimportantconcept. • Those functions will usually return the same values.youmay struggle a little bit.thatmeansthefollowing: •Y o u rprogramsaregoingtobebuiltentirelyoutoffunctions. we’re going to cover some Erlang basics.reliabilitycanbecool. Y e s .with noobjectsanywhere. ThiskindofsneakedinErlangundertheradarto10millionmachines.0printing. Ifyoustartedthisbookasapureobject-orientedprogrammer.)Toyou.”It’snotgoingtobeeasy.(Scalaisahybridfunctional/object-oriented language.Erlangisthefirstof ourfunctionallanguages.WhenIupgradedmyversionofUbuntutoKarmicKoala. which was also running live on my machine. sofindingthingsandfittingthingstogetherbecomesincreasinglyimportant. 6.I’mgoingtotrymybesttogiveyou“normal. we’ll put Erlang through its paces as a functional language.ThesearefoundationalprinciplesinErlang. we’ll spend some time with concurrency and some cool reliability features. In this chapter.patternmatchinginProlog. Armstrong: W e .D AY 1: A PPEARING H UMAN 185 changesfromwritingfreshcodetofindingandintegratingexistingcode. The most basic trait that makes him dangerous is his ability to appear human. Bruce: What’sthemostsurprisingplaceyou’veeverseenErlangused inproduction? Dr. Ifoundaratherwell-hiddenErlangtickingawayinthebackground.2 Day1:AppearingHuman Agent Smith is as a program that kills other programs. or simulated people. given the sameinputs.actorsinIo. Then. we’re going to look at Erlang’s ability to build general-purposeapplications.friends. lIwasn’tactuallysurprisedsinceIknewthiswas goingtohappen. Y o u v ’e already seen code blocks inRuby. Finally. Reporterratum thiscopyis (P1. In this section. that disrupt the simulated reality known as the Matrix.ItwouldbenicetointegrateideasfromthingslikeGITandMercurial and type systems into the language itself so that we could understand howcodeevolvesinacontrolledmanner.October2010) .

V ariables.Butyouwillgetastrongflavoroffunctional-styleprogramming.Erlangparsesacommentasasinglespace.atleastforalittlewhile. Living by the next three canknockyoudown.Let’sgetstarted. GettingStarted I’m working with Erlang version R13B02.4. Y o u l’ get to the e r l on some W Erlang shell by typing erl (w n id o w s systems) at the commandline.Knowthatyoucanlearn tocodethisway.D AY 1: A PPEARING H UMAN 186 • Those functions will not usually have side effects.0 Reporterratum thiscopyis (P1. you caught the word usually in the second andthirdrules.andtheresultwillbeprogramsthatarebuiltfromthe inside out for concurrency. but the basic stuff in this chapter should work OK on any reasonable version.likethis: batate$erl Erlang(BEAM)emulatorversion5. as with other chapters.andtypethefollowing: 1>%Thisisacomment % and eat everything That was simple enough. Comments. Y o u can break out of the console. Y o u l’ compile a file with c(filename). 4. If you paid close attention.withControl+C. meaning they willnotmodifyprogramstate.Erlangisnotapurefunctionallanguage. When you remove mutable state from the equation. Erlang is a compiled language. Comments start with a untiltheendofaline.0. (you need the period at the end).oraloop.13[source] EshellV5. •Y o uwillonlybeabletoassignanyvariableonce. early on.0printing.concurrencygetsdramaticallysimpler. Crackopenthe console. 4 2>2+2.itdoesallow a few exceptions.4.October2010) . andExpressions Let’s get some ofthe basic syntax out ofthe way. Living by the first rule is mildly challenging. andyouwillcodetotheserulesmoreoftenthannot. Haskell is the only pure functional language in this book. Like Java. 1>2+2.13 (abortwith^G) 1> W e l’ do most of our work there.

variables begin with a capital letter.integers.October2010) . ** exceptionerror:badargumentinanarithmeticexpression inoperator +/2 calledas4+"string" UnlikeScala.there’snocoercionbetweenstringsandints.3].expr.Let’sassign avariable: 6>variable=4.andAgentSmithjustlaughedatyourmamma. "string" 187 Each statement ends in a period.andfloats. Here’salittlesurprise: 4>[72. Here.2}. you see the ugly side ofthe comparison between agents and Erlang. ** exceptionerror:nomatchofrighthandsidevalue4 Ah.D AY 1: A PPEARING H UMAN 3>"string". lists are in square brackets. and they are immutable.Now.thosesocialskills.97].This error message is really a reference to Erlang’s pattern matching.0 tellsusthatErlangdoessomebasictype coercion.3] As with the Prolog family of languages.[{erl_eval.72.72.97. "HaHaHa" So.a String isreallya List. Oh. It’s a a r ib e l breaking because v is an atom. [1. This concept gives Reporterratum thiscopyis (P1.39. 2+2. 1 ** As you can see. V a r a ib e ls must start with an uppercaseletter.thispeskylanguagehasmorebrainthansoul.[{erl_eval. Y o u can assign each value only once.3}]} ** exited:{{badmatch. 7>Var=1. =ERRORREPORT====8-Jan-2010::11:47:46=== Errorinprocess<0.Let’strytobreakalineofcodewithabadtype: 5>4+"string".3}]} 8>Var. 1 8>Var=2.expr. These are some of the basic types: strings.foralist: 4>[}.0>withexitvalue:{{badmatch.2.

andT u p e ls Infunctionallanguages. Atoms. the length can vary. just as it didinProlog.0} There are no surprises here."three"] 15>List=[1. For now. the size will matter. {one.2.3] 14>[1.two."three"].0}. Lists are heterogeneous and can be any length. {0. Y o u can see the strong Prolog influence here.youwillnoticethatwhen you match a tuple.Y o ucanassignthemtovariables.2.3].three} 19>Origin={0.October2010) .Theyareatomicvaluesthatyoucanuseto representsomething.3] So.Y o u l’representlistswithsquarebrackets: 13>[1.asymboliscalledan atom andbegins withalowercasecharacter.3].2. blue red and blue areatoms—arbitrarynamesthatwecanusetosymbolize red. W e first return a simple atom called assign the atom called blue to the variable called Pill. Y o u can’t match a three-tuple to a two-tuple. [1.InErlang.three}.Theyarethe most primitive data element and can represent anything you want to name.Y o u l’usethemlikethis: 9>red.whenwecoverpatternmatching.2.symbolsbecomemoreimportant. red 10>Pill=blue. Y o u v ’e encountered symbols in each of the other programming languagesinthisbook. let’s build on the primitives by looking atthelist.Later. Atoms get more interesting as you attach them to more robust data structures that we’ll see a little later.justasyouwouldaprimitive. we real-world things.D AY 1: A PPEARING H UMAN 188 mostfirst-timeprogrammerstroublewithinafunctionallanguage.Let’s introducesomedatatypeswithmorecomplexity.two.Lists. When you match a list. Tuplesarefixed-lengthheterogeneouslists: 18>{one. [1. [1.2. Next. Reporterratum thiscopyis (P1. blue 11>Pill. the list syntax is familiar.2.0printing.

"CalvinandHobbes"}. {character. A match will work against a single value.D AY 1: A PPEARING H UMAN 189 InRuby.Profession}}=Person."Killingprograms"}} Let’s say we want to assign the name to Name."AgentSmith"}. {person. Let’s use pattern matching to extract the values from a tuple. you’lloftenseetuplesusedasyouwouldusemapsorhashes: 20>{name.Y o u l’usepatternmatching. such as a list of comics. so the only work to be Name to "Agent Smith" and the variable done is to match the variable Profession to "Killing programs" .0printing. {person. "Killingprograms" profession to Erlang will match up the data structures.Thismatchwoulddothetrick: 25>{person.youusehashmapstoassociatenameswithvalues. {name. you matched all the values in thedatabase. {profession.Name}.InErlang."CalvinandHobbes"}.{profession.{profession.{name.{name.W e useatomsforthehash keys and use strings for the values. you’re alreadythinkingintherightdirection. I want to point out one major difference."SpacemanSpiff"}. when you defined a rule."Killingprograms"}}.{name.{character. Say we have a person: 24>Person={person. In Prolog.{name. "AgentSmith" 27>Profession.andPrologworkedthroughallthecombinations."AgentSmith"}. Y o u can mix lists and tuples as well. Reporterratum thiscopyis (P1.October2010) .{name."Killingprograms"}} 26>Name. {comic_strip. So. An atom will match itself.Erlang works like Scala. assigning variables to the values in the tuples.{name."SpacemanSpiff"}}. {profession."SpacemanSpiff"}} W e v ’e representedahashforacomicstrip. represented by tuples."AgentSmith"}. you got a pretty solid foundation of pattern matching. P a t e r nMatching If you worked through the Prolog chapter. how do you access the individual elements? If Prolog is fresh in your mind. and the Profession. This feature works much like it does in Prologandwillbethefundamentaldecision-makingconstructthatyou use."SpacemanSpiff"} 21>{comic_strip.

thepatternwon’tmatch: 36>[X|Rest]=[].2. [2.Itis Asyou’veseenbefore.leavdatastructuresthisway. you’ll often have multiple have the initial atom of matching statements and multiple kinds of tuples. ** exceptionerror:nomatchofrighthandsidevalue1 = statementisnotasimpleassignment.3] 29>Head. 1 BitMatching Sometimes.youcanquicklymatchallperson ingtheothersbehind.Ifyou’recramming more data into less space or dealing with predefined formats such as JPEGsorMPEGs.3].0printing.two. Reporterratum thiscopyis (P1.3]. 1 30>Tail.Erlangletsyoupack severalpiecesofdataintoonebytequiteeasily.3] Easyasone. Y o u r ’e asking Erlang to match the integer withtheatom one. [1.three. 1 34>Two. Let’s sayyouforgettostartyourvariableswithanuppercaseletter.October2010) .anditcan’t. some of the other error messages make a little more sense.3] 33>One.the actually a pattern match. 2 35>Rest.2. [3] Iftherearenotenoughelementsinthelist. it may seem strange to person.D AY 1: A PPEARING H UMAN 190 If you are used to Ruby or Java-style hashes.2.youneedtoaccessdataatthebitlevel.Y o ucanbindtomorethanonevariableatthe headofalist. ListpatternmatchingissimilartoProlog’s: 28>[Head|Tail]=[1.too: 32>[One.Two|Rest]=[1. By designing your tuples. ** exceptionerror:nomatchofrighthandsidevalue[] Now.thelocationofeachbitmatters.Y o u l’get thiserrormessage: 31>one=1. In Erlang.Todothesetwothings. [1.2.

4 Just like tuples and lists. we just supply the same syntax and let patternmatchingdotherest. because you’ve already been introduced to all the major concepts in the chapter.erl extension.Thefilecontainscode towritefunctionsinafilewithan foramodule.Atthispoint. 5 bits for Y. Believe it or not.thefunction.likethis: 1>W=1.Y o u r ’egoing .Y o uwon’thavetoworrytoo muchaboutassigningtypestodataelements. <<"(d">> 7>A 7>.you’lljust tellErlanghowmanybitstotakeforeachitem. and 5 it means take 3 bits for the variable bitsfor Z.October2010) .Erlangtyping isdynamic. 2 3> 3>Y=3.B:3. W. 1 8>D. we’re almost through the first day of the Erlang chapter.Y o ucanprobablyguess thesyntax: 6><<A:3.Next.Erlangisdynamicallytyped.abitmapworks justlikeothertypesofcollections.weneedtobeabletounpack. 1 2>X=2.0printing. Functions UnlikeScala.I’mgoingtocrackopen afreshcopyoftheconsole. but we firstneedtointroducethemostimportantconcept. 3 4>Z=4.D AY 1: A PPEARING H UMAN 191 youneedtwooperations:packandunpack.D:5>>=All.LikeRuby.Z:5>>.Topackadatastructure.basedonsyntacticclues suchasquotesordecimalpoints.C:5.W t i hthesebitwiseoperations.Erlangissurprisinglypowerfulforlow-leveltasks.Afteryou’vecompiled Reporterratum thiscopyis (P1.X:3.Letmeintroduceafewterms. 3 bits for X.andyouhavetocompileittorunit.Inthiscase. 4 5>All=<<W:3.InErlang. <<"(d">> The << and >> bracketbinarypatternsinthisconstructor.Erlangwillbindtypesatruntime.Y:5. W e r ’e covering a lot of ground pretty quickly.

Finally. The second line defines a function that you want to use outside of the module. you get to the function itself. After Scala’s strong typing.itproducesa beam. The function is called mirror. runinavirtualmachinecalledthe 192 W t i h the housekeeping out of the way. and to me. Notice one thing. and you will find a directory.followedbyacolon.Icanthencompileitlikethis: 4>c(basic).beam compiledmodulewill afile.D AY 1: A PPEARING H UMAN . ** exceptionerror:undefinedshellcommandmirror/1 6>basic:mirror(smiling_mug).October2010) . -export([mirror/1]). I’m coming home from a weekend in Siberia.Y o ucanrunitlikethis: basic. Y o u can see the influence of the Prolog-style rule. and the /1 means it has one parameter.0printing.erl -module(basic). I’ll fire up the console from the samedirectorythathasthecodefile. Erlang is dynamically typed. W e were able to bind Anything to two different types.basic} W e compiled basic. Reporterratum thiscopyis (P1. {ok. W t i h a function definition complete. The first line defines the name of the module.beam executable. The function definition names the function and determines the -> symbol. it feels good. Let’s look at a function that’s slightly more complicated. Afterward. Y o u also needtoincludethemodulename. you have the thefirstargument. mirror(Anything)->Anything. smiling_mug 6>basic:mirror(1).erl. 1 Noticethat it is not enoughto havethe function name alone. it’s time to create some basic functions. which simply returns arguments. or at least Peoria. I’mgoingtoenterafilethatlookslikethis: Download erlang/basic.Thisfunctionis deadsimple. This one definesseveralmatchingalternatives.beam file in the same 5>mirror(smiling_mug).The .

-export([another_fib/1]). another_factorial(0)->1. 2 11>matching_function:number(three). another_fib(1)->1.matching_function} 9>matching_function:number(one).Terminatethelaststatementwith allotherswith . and it’s defined recursively just like all the others. Reporterratum thiscopyis (P1. another_fib(N)->another_fib(N-1)+another_fib(N-2).October2010) . -export([another_factorial/1]). Scala. number(three)->3. and Prolog. So.D AY 1: A PPEARING H UMAN 193 Y o ucancreatea m a t c h n ig _ f u n c o t in . Like Prolog. In each case. Just as with Io. it’s another factorial. Andyoucanexecuteitlikethis: 8>c(matching_function). another_fib(0)->1.0printing. number(one) ->1. Each possible match has the function name..erl -module(matching_function). Here is the obligatory factorial: Download erlang/yet_again. {ok. and the code to execute after the . Erlang is optimized for tail recursion. 3 12>matching_function:number(four).erl -module(yet_again).too. recursion will play a big role. to match. and Erlangjustreturnsaninteger. number(two) ->2.ImayaswellincludeaFibonacciseries.WhileIwasatit. the argument -> symbol. -export([number/1]). 1 10>matching_function:number(two). e r l filelikethis: Download erlang/matching_function. another_factorial(N)->N * another_factorial(N-1). ** exceptionerror:nofunctionclausematchingmatching_function:number(four) This is the first function I’ve introduced with multiple matching possibilities.

Itisstrongly. 3316275092450633241175393380576324038281117208105780394571935437060380 7790560082240027323085973259225540235294122583410925808481741529379613 1386633526343688905634058556163940605117252571870647856393544045405243 9574670376741087229704346841583437524315808775336451274879954368592474 .andonandon. but you will learn a new bag of tricks. Now. 0000000000000000000000000000000000000000000000000000000000000000000000 Ooooh-kaaay. Y o u v ’e created some simple functionsandseenthemwork. Erlang does have a strong connection to Prolog. The functionallanguagehasnonotionofmutablestateorevensideeffects. That was certainly different. Like Prolog. but what is there is not at all like the typical object-orientedlanguages. Reporterratum thiscopyis (P1. WhatW eLearnedinDay1 Erlangisafunctionallanguage. 788657867364790503552363213932185062295135977687173263294742533244359 449963403342920304284011984623904177212138919638830257642790242637105 061926624952829931113462857270763317237396988943922445621451664240254 033291864131227428294853277524242407573903240321257405579568660226031 904170324062351700858796178922222789623703897374720000000000000000000 000000000000000000000000000000 22>yet_again:another_factorial(2000).. If you didn’t take the time to run it. Maintaining program state is awkward. let me assure you. through recursion. Y o u l’ soon see the other side of the coin. However. the results are absolutely instantaneous.. That’s a pretty good starting point.October2010) . Eliminating state and side effects will have a dramatic impact on how you will manage concurrency. you’re starting to see the butt-kicking side of the Agent Smith/Erlang comparison. butI’mgoingtogooutonalimbandsayit’sbigenoughforme.yet_again} 19>yet_again:another_factorial(3). The pattern matching constructs and multiple function entry points should look familiar to you. I don’t know what the maximum integer size is.dynamicallytyped. 6 20>yet_again:another_factorial(20)..D AY 1: A PPEARING H UMAN 194 Letmetrytomakeitworthyourwhilethistime: 18>c(yet_again).0printing. and you handle some problems in the same way.. 2432902008176640000 21>yet_again:another_factorial(200).It’sagoodtimetowrapupday1.There is not a lot of syntax. Erlang has no notion of an object. {ok.

Theycandodge bullets and punch through concrete.Thoughthey Reporterratum thiscopyis (P1.youworkedbothintheconsoleandwiththecompiler. Y o u also created simple functions. Like Prolog.Take alittletimetodosomeself-studytopractice whatyou’velearnedsofar. A conference in San Francisco is picking up momentum. Message} or sucor “error: message” given input of the form cess.I’mgoingtoexpandthebasicfunctionalconcepts.you’regoingtobegintoappreciateAgentSmith’spower. Y o u learned to pattern match across lists and tuples. Theagentsin TheMatrix havesuper-humanstrength. •W r t i eafunctionthatusesrecursiontocounttoten. •W r t i e a function that uses matching to selectively print “success” {error. 6. learn Day1Self-Study The online community for Erlang is growing rapidly. Functional languages are at a higherlevelofabstractionthanobject-orientedlanguages. you shouldbeabletouseGoogletofindwhatyouneed. Erlang lets a function havemultipleentrypoints. Tuples took the place of Ruby hashes and formed the foundation of data structures.W e l’ how to build code that will work in a concurrent world. Inday2. Find: • TheErlanglanguage’sofficialsite • OfficialdocumentationforErlang’sfunctionlibrary • ThedocumentationforErlang’sOTPlibrary Do: •W r t i e a function that uses recursion to return the number of wordsinastring. Y o u also used basic tuples and lists.October2010) .Y o uusedbasicpatternmatching. Primarily. but we won’t actuallygothereyet. you focused on the basics. And unlike Io and C.3 Day2:ChangingForms Inthissection.D AY 2: C HANGING F ORMS 195 Inthefirstday. Y o u created basic expressions. These ideas will allow you to quickly attach behavior to tuples or interprocess messages in later chapters.0printing.

sayyouhavea variablecalled Animal. I’d like to point out a basic syntactic wart here. underdog So. in this example. Notice that all case clauses but the last end in a semicolon.Y o uwanttoconditionallyexecutethecodebased onthevalue: 1>Animal="dog". Think ofthis control structure as a patternmatchthatyoucanuseanywhere.youthinkofapatternmatchin the context offunction invocation. so it matched the last clause. 3> _->something_else 3>end. Y o u can also use underscores in any other Erlang match. As with Prolog. 2>caseAnimalof 2> "dog"->underdog. Do you want to turn a shopping list into a list of prices? What about turning a list of URLs into tuples containing content and URLs? These are the problems that functional languages simplydevour.0printing. Agent Smith can also take the form of any other person in the matrix. you can use the underscore (_) to Animal isstill "dog"): matchanything.D AY 2: C HANGING F ORMS 196 aremoredifficulttounderstand. Y o u r ’e going to learn to apply functions to lists that can quickly shape the list into exactly what you need. ifsarelessprevalent.Mostofthetime. something_else The animal was not "elephant". 2> "cat"->thundercat 2>end. ControlStructures Let’s start with a few mundane pieces of Erlang: basic control structures.Forexample. the string matched the first clause and returned the atom underdog. beScala’s. Y o u l’notice that this section of the book is much shorter than case statements. you’ll see programs with plenty of causetheywillinterpretwhichmessagetoprocesswhenyou’rewriting concurrentapplications. That’s an important capability in a functional language.October2010) . Often.youcanexpressbiggerideaswithless code. Case Let’sstartwithacase.likethis(note: 3>caseAnimalof 3> "elephant"->dumbo. That means if you want to edit your statement to Reporterratum thiscopyis (P1.

and I think I heard him laugh. Each case must return a value. Later. Month. W e r ’e going to work with higher-order Reporterratum thiscopyis (P1. Whathappensifthereisnomatch? 8>X=0.AgentSmithjustkicked sand all over my kid nephew. 9> X<0->negative. because a function. Y o u r ’e going to get much more outofhigher-orderfunctionsandpatternmatchingtoaccomplishyour goals. if is That’s really it for control structures.Sure.Y butthemostbasicformofaguardisinan o ustartwith guard->expression clauses. the if keywordandthenfollowitwithseveral Here’stheidea: if ProgramsTerminated>0-> success. He has to brush up on those public relations if he wants to win Agent of the if. 9> true ->zero 9>end. and the guards. 0 9>if 9> X>0->positive.likethis: 9>if 9> X>0->positive. though itwouldhavebeenprettyeasytoallowanoptionalsemicolonafterthe lastclause. one of the statements must be true. If you truly want an else. ProgramsTerminated<0-> error end. if statement. we’ll introduce guards on pattern matches. a guard is a condition that must be satisfied for a match to succeed.0printing. 9> X<0->negative 9>end.D AY 2: C HANGING F ORMS 197 reorder your clauses.It’sjustnotveryconvenient.thesyntaxislogical:thesemicolonisaseparatorfor the case clauses.October2010) .solet’sleavethesecontrolstatementsbehindanddiveindeeper into functional programming. In Erlang. makethelastguard true.Let’smoveontothebasic If if statement uses The case statement uses pattern matching. ** exceptionerror:notruebranchfoundwhenevaluatinganifexpression Unlike Ruby or Io. you must adjust the syntax accordingly.

D AY 2: C HANGING F ORMS 198 functions and use them to process lists.Scala. -I. learn to solve progres- AnonymousFunctions As you recall. W e assign that anonymous function to Negate.we’reassigningafunctiontoavariable. Twosignificantideasarehappeninghere. lists and tuples are the heart and soul of functional programming. In Erlang.13229925> 17>Negate(1).thefunctiontakesasingleargumentcalled I and returns the negation. W e l’ sivelymorecomplexproblemswithfunctions.It’snoaccidentthatthefirstfunctionallanguagestarted Reporterratum thiscopyis (P1. we can easily invoke the underlyingfunction.Rubyusedcodeblocksforhigher-orderfunctions. Y o u v ’eseensomeoftheseconceptsbefore. ListsandHigher-OrderFunctions As you’ve seen. 1 fun.ThatkeyworddefinesananonyLine16usesanewkeywordcalled mousfunction. -1 18>Negate(-1). so we’re protected from some of the invasive syntax you see with.Tobeclear. you can assign arbitrary functions to variables and pass themaroundlikeanyotherdatatypes. Let’susesomeofthisnewfoundpower.I’llshow yousomeofthewaysErlangletsyoucompensateforthatlimitation.6.say.and inject conceptsthatyouinitiallyencountohandlethe each.It actually is thefunction.butwe’regoingtolaysome ofthefoundationsinErlangandthenbuildsomehigher-levelabstractions. Here’s how you’d assign afunctiontoavariable: 16>Negate=fun(I)->-Iend. higher-order functions either return functions or take functionsasarguments. It all starts with anonymous functions.withspecialattentiontopassingcodeblockstoiterateoverlists. W e don’t have to concern ourselves with the return type of the function.First. Second.justbyspecifyinganargumentlist.Inthiscase. Negate isnotthevaluereturnedbythefunction.Thisconceptallowsustopassaroundbehaviorsjust as we would any other data.Noticethedynamic typing.October2010) .0printing. #Fun<erl_eval.Thedownsideisthatthesefunctionscanfail.W e l’ useanonymousfunctions a p . m teredwithRuby.

Inthissection.2. Now.[X])end.Openafresh resultsalongtheway.Numbers).Stillmore.Thefirstargumentistheanonymous function fun(Number) -> io:format("~p~n". 1 2 3 4 ok That’sbasiciteration.Some. ~p pretty prints an argument.The tionandalist.you’ll starttoapplyhigher-orderfunctionstolists. ~n is a newline.3.definealistortwo.like filter or m o fd l l or o fd l r . That function has one argument and prints the value of whatever you pass in o fr e a c h with the io:format function.willprocesslists.likeRuby’s console.4].2.W estartby invokingafunctioncalled lists:foreach.theideashouldbeprettycleartoyou.willreturnlists.4] 2>lists:foreach(fun(Number)->io:format("~p~n".2 Finally.Themap function works like Ruby’s collect.Let’smoveontoafunctionthatmaps.W e r ’e goingtousefuncForEach.0printing.like inject orScala’s FoldLeft.[Number])end. Reporterratum thiscopyis (P1. tionstohelpusmanagelists. W e can simplify the code 8>lists:foreach(Print.eitherfilteredormappedonto Others.andgetcracking.like a p .sowe’llwalkthroughit. passing each value of a list to a 2. 1 2 3 4 ok Thesyntaxofline2isalittletricky.October2010) . Print is bound to the likethis: io:format function. the second argument to is Numbers.W e couldsimplifythisbydefining thefunctioninaseparateline: 3>Print=fun(X)->io:format("~p~n".andeverythingbuiltonthatfoundation.thelistwedefinedonline1.Numbers).likethis: 1>Numbers=[1. [1. and [Number] is a list of arguments to print.D AY 2: C HANGING F ORMS 199 withlists. lists:foreach methodtakesafuncFirst.3.we’llhandlebasiciteration.rollingup otherfunctions.Thefunctioncanbeanonymous. [Number]) end .williterateoverlists. ApplyingFunctionstoLists Bynow.

Numbers).Let’sdefineananonymous Small: functionandassignitto 11>Small=fun(X)->X<3end. .[0. false 13>Small(1).[]) ->[].wecantakethatfunctionanduseittofilterthelist. true 18>lists:any(Small.3]).6.4.[3.1.Numbers).T)]. false Alternatively.2.5] 200 fun(X) -> X + 1 That was easy.likethis: 15>lists:all(Small.3. map(F.[H|T])->[F(H)|map(F. lists:any returnstrueifanyoftheitemsinthelistsatisfies thefilter: 17>lists:any(Small.D AY 2: C HANGING F ORMS lists:foreach.Thefunction lists:filter willbuildalistofalltheelementsthatsatisfy Small orthoseless thanthree: 14>lists:filter(Small.[0. [1. Small functiontotestlistswith all and any. false Reporterratum thiscopyis (P1. Let’s use increasingeachvaluebyone: 10>lists:map(fun(X)->X+1end. true 16>lists:all(Small.2]). This time. and lists:map built a list with the results. It increased each value by one.2] Y o u can see that Erlang is making it very easy to code in this way.4. Definingmapisreallyeasy: map(F.5]).Themapof lookatamoreconciseversionwhenwelookatlistcomprehensions. Alternatively. takes a function and a list.October2010) .3]). F overalistis F(head) plus m a p ( F. [2.wecanusethe lists:all returns true onlyifalltheitemsinalistsatisfythefilter. true Now. our anonymous function was end.wecanfilterlistswithaboolean.2.W e l’ Movingon.tail) Simpleenough.13229925> 12>Small(4).[0. lists:map function and building a list with the results.1.0printing. #Fun<erl_eval. Like m a p with our list of numbers.1.

4] 24>lists:takewhile(Small.andthelist: 28>Numbers. Remember. so I’m going to teach it a fd ll fewdifferentways. Inthesecases.[]). all returns true (meaning all of the items present in any thelistsatisfythefilter. true As you’d expect.Numbers).D AY 2: C HANGING F ORMS 201 Let’sseewhathappenswithemptylists: 19>lists:any(Small.[]).4.2.let’sbreakthatanonymousfunctionintoavariableandmakeourintentionsclearwithbettervariablenames: 32>Adder=fun(ListItem. [1.October2010) .4] 29>lists:foldl(fun(X. false 20>lists:all(Small.2] 23>lists:dropwhile(Small. [4.SumSoFar)->ListItem+SumSoFarend.Numbers).4.0printing. o takes a little while to master.Numbers).12.1]).thoughtherearenoitemsinthelist).2.1]).Oneoftheargumentsservesasanaccumulator.Ifyou’reNeoandyou’ve mastered this part of the matrix.Let’sfinishthiswhirlwindwith o fd ll Irealizethatyou’veseentheseconceptsbefore. For some.2.0. ofmessages.1.theinitial andtheotherrepresentseachitem. #Fun<erl_eval.113037538> Reporterratum thiscopyis (P1.1.1] 25>lists:dropwhile(Small. valueoftheaccumulator. these functions are useful for rolling up the results of a functionacrossalist. [1. Y o u can also make a list of all the elements at the head of a list that match a filter or discard all the items at the front of a list that satisfy thefilter: 22>lists:takewhile(Small.Sum)->X+Sumend.1] Thesetestsareusefultodothingssuchasprocessordiscardheaders o fd l l and o fd lr . lists:foldl takesafunction.itdoesn’tmatterwhatthefilteris.and returnsfalse(meaningnoelementintheemptylistsatisfiesthefilter).3.[1. read the basic example and fight on. [3. [1.[1. 10 Tosimplifyalittlebit.2.

it may seem difficult to build lists without mutable state.Often. So.Butwecangetalittlemoresophisticated. AdvancedListConcepts AllofthelistconceptsI’veintroducedareextensionsoftheideasyou’ve seenintheotherlanguages.Eachtime.Thisprogramusesthelistconstructiontechniquetodoubleeachitemofalist: Download erlang/double.Y o u v ’ealreadyseensomething like [First|Rest] ontheleftsideofamatch.Ultimately. Sofar. and we’ve only used pretty basicabstractionswithsimplecodeblocks. -export([double_all/1]). Y o u l’use the [H|T] construct but in therightsideofamatchinstead.andthe lists:foldl functionwillremembertherunningtotalandpassitbackinto Adder.Itletsyoubreakalistintothe firstelementandtherestofthelist.InitialSum. 10 202 Ah. 0 34>lists:foldl(Adder. Reporterratum thiscopyis (P1.D AY 2: C HANGING F ORMS 33>InitialSum=0.Numbers).0printing. we are going to keep a running sum.Y o ucanreturnanewlistwiththelistitemadded. double_all([First|Rest])->[First+First|double_all(Rest)].There’s anotherway.thefunctionwillreturnthelastrunningsum.youwouldcontinuallyadditemstoalist. W e r ’e going to pass the SumSoFar and each number from Numbers into a function called Adder.October2010) . double_all([])->[]. The first says that returnsanemptylist.allyou’veseenarefunctionsthatworkonexistinglists.thesumwillgetbigger.Thisrulestopstherecursion.erl -module(double). that’s better. W e haven’t yet talked about building lists.Ihaven’t shownyouhowtobuildalistapieceatatime. but in the predicate of the The second rule uses the matchaswellasthefunctiondefinition. you’ll add items to a list headfirst.oneatatime. called double_all for an empty list two distinct clauses.Let’sshiftgearstoward listbuilding. ListConstruction On the surface. [H|T] construct. double_all. That function has The module exports one function.W t i hRubyorIo.

[1.3]]. #Fun<erl_eval.D AY 2: C HANGING F ORMS 203 Usingitontherightsidedoeslistconstructioninsteadofdestruction.2.4. your lists can mutate. Whatever is on the left side will be added as the first element of a newlist. They combine some of the concepts we have been talking about sofar.3.1.6.W mies.6.3] 17>[1|[]]. asthefirstelementand Y o ucancompileandruntheprogramasusual: 8>c(double).5].3]).2. just like The Matrix enea p .13229925> 3>lists:map(Double.3]].0printing.double} 9>double:double_all([1. {ok.October2010) .6] Let’stakeanotherlookatlistconstructionwith 14>[1|[2.3]|1] 16>[[]|[2.Erlangprovidesamorepowerful form that is concise and allows you to do multiple transformations atonce. [2. [First+First |double_all(Rest)] meansbuildalistwith double_all(Rest) astherestofthelist. [1.3] 15>[[2. [2.Fibs).3. [1] | fromtheconsole: Thereshouldbenosurprisesinthere. [[2.Sincethefeatureissoimportant. Let’s start things off with a fresh console.Thesecondargumentmustbea list.2. Let’s look at a more advanced Erlang concept. called list comprehensions. [[]. we called lists:map Reporterratum thiscopyis (P1. Then.2. ListComprehensions One of the most important functions in just about any functional language is m t i h it.3]|1].5] 2>Double=fun(X)->X * 2end. First+First Inthiscase.10] do a map the old- Fibs andananonymousfunctioncalled W e havealistofnumberscalled Double that will double whatever you pass in. W e l’ fashionedway: 1>Fibs=[1.

4.25}.0. but it’s used often enough that Erlang provides a much moreconcisewaytoprovidethesamesyntax.2.Ifyou’dprefer. [2.Quantity.08 ).Quantity.0._.4.let’susealistcomprehenof F(X) foreach X thatisamemberof siontoworkwithacataloghavingaproduct.{paper.2}] Reporterratum thiscopyis (P1.W e willstart m a p : withamoreconcisedefinitionof map(F.25}. [{pencil.4. 3.0.{paper.0.likethis: 8>WithTax=[{Product.1.2.25}.Price * Quantity * 0. we’re returning a list of tuples havinga Product.20}].0.Here’stheequivalent towhatwejusttyped.2.foreach Cart. 1.032}] AlltheearlierErlangconceptsyou’velearnedstillapply:there’spattern matching going on here! So in English.ignoringquantity: 10>Cat=[{Product. 5 ]. The catalogcouldlooksomethinglikethis.1.08}.1.0.Quantity.2.witha listcomprehension: 4>[Double(X)||X<-Fibs].Price}<-Cart].2.literallyondemand.5]]. [2. Quantity. Price.10] Double of X foreach X takenfrom InEnglish.Price}<-Cart].Thiscode tupleof {Product. 2.{pen.Price}||{Product.2}.Icanadda simplelistcomprehensiontorollupthenewcartwithtaxwithasingle listcomprehension.Theconstructiscalleda listcomprehension .andprice: 7>Cart=[{pencil.October2010) .0printing. This feature is a bit more than syntactic sugar.25.{pen.we’resayingcomputethe thelistcalled Fibs.6.quantity.1.I’lljusttakethecatalogfromthe cart.1.wecancutoutthemiddleman: 5>[X * 2||X<-[1.1.Price.2.096}.6.08}|| 8> {Product.2.3.10] X*2 foreach X takenfromthe Theconceptisthesame.0. Asanotherexample.Price} takenfromthelistcalled isabsolutelybeautifultome.4. [{pencil.4.20}.That’s a great tool.{pen.{paper.1.sayIhaveacatalogandIwanttoprovideasimilar catalog to my preferred customers with a 50 percent discount.0.D AY 2: C HANGING F ORMS 204 tocall Double oneachelementandbuildalistoutoftheresult.themapofsomefunction L. F oversomelist L isthecollection InEnglish.0. [{pencil.L)->[F(X)||X<-L].{pen.Thissyntaxallowsmetochangetheform ofmylist.1.andtax( Price*Quantity*0.{paper.2.Now. Let’sbuildsomemoresophisticated listcomprehensions.W e r ’ecomputing list called [1.2}.0.2}] SaythatIneedtoaddataxthatiseightcentsonthedollar.0.

and X isgreaterthanone.0printing. and filters trim the list down to the specified conditions. There’s a lot of Prolog influence here. Andthat’sthewholestory.andpowerful.125}..D AY 2: C HANGING F ORMS Product and Price foreachtupleof ProdInEnglish.5}.X<3.Generators determine the possible values. Generators add..3.Icanprovidemydiscount: 11>DiscountedCat=[{Product.4].6]].Y o ucanalsohavemultiplegenerators: 23>[{X.1}] 205 It’sconcise.3. || Clause1. Match<-List . but you are now armed with enough information to write Reporterratum thiscopyis (P1.3.5}.. • Theclausescanbegeneratorsorfilters.0.2.6 ].oftheform totheelementsofalistontheright. Let’s take a break to wrap up and put this stuff into practice.It’sabeautifulabstraction. WhatW eLearnedinDay2 Admittedly.6}.{2.readable.matchesapatternontheleft • Agenerator. and Price (ignoring the second attribute) taken from the Cart list. [{pencil.andErlangcomputesaCartesianproduct. • Listcomprehensionscanhaveanarbitrarynumberofclauses. Intruth. it’s not too hard.2. Thefullformcanbeevenmorepowerful: • A list comprehension takes the form of [Expression Clause2.Y o u v ’elearnedtouseErlangtodosequential programming.0.where X istakenfrom [1.4 ] that Thisonemakesatuple Y valuesfrom [5.4 ]. • A filter can be a boolean expression or a function returning a boolean.2.Price/2}||{Product.6}.4].2. and filters remove.{2.3.Y} bycombining X valuesfrom [1.I’veshowedyouonlypartofthepowerofalistcomprehension.{pen. [{1.{paper.6}] 24> {X. Here are a coupleofexamples: [X||X <-[1.givemetupleswith uct.3] InEnglish. we didn’t go into deep detail about Erlang expressions or the library..Y<-[5.Y}||X <-[1. Now. [2.0. X islessthanfour.Price}<-Cat].October2010) . Really.{1.X<4.X>1].Y X values arelessthan3with o uwindupwithtwo andtwo Y values.ClauseN].return X.

Still. ]. Thesyntaxwasamixedbag. thanks to Erlang’s dynamic typing strategy.headfirst.D AY 2: C HANGING F ORMS 206 functional programs. such as [{erlang.where total_price is quantity times price. "a functionallanguage"}. . Return the winner ( has been determined. W r t i e a list comprehension that builds a list of items of the form [{itemtotal_price}. W e used [H|T] on the right side of a match.butwepickedupthepacequickly.filterthem.. fd ll Y o u also learned to use o to roll up results.thereweresomeawkwardmoments.{ruby.. we’ll learn what all of the fuss was about. or no_winner ifnoplayerhaswonyet. ].Y o ucouldcruisethroughthehigherconcepts with very little typing.W r t i eafunctionthatacceptsthelistandakeywordandreturnstheassociatedvaluefor thekeyword. we moved on to advanced list concepts. Finally. W e used [H|T] on the left side of a match to deconstruct a list into the first element of the list and the rest...an elegantandpowerfulabstractionthatcanquicklytransformlistswith generatorsandfilters.especiallywiththesemicase and if clauses. Reporterratum thiscopyis (P1.October2010) ."anOOlanguage"} ].W e thenmovedontolistcomprehensions. • Consider a shopping list that looks like [{item quantity price}. Next. just as you did with Scala. or solo. colonsafterthevariouspiecesof In the next section. Y o u started the day with some mundane control structures. cat if there are no more possible moves. to constructlists. W e l’ tackleconcurrency. Bonusproblem: •W r t i eaprogramthatreadsatic-tac-toeboardpresentedasalist x or o) if a winner or a tuple of size nine.0printing..andmodifythem. Day2Self-Study Do: • Consider a list of keyword-value tuples. we covered higher-order functions. Y o u used higher-order functionswithinliststoiteratethroughlists.

Reporterratum thiscopyis (P1.IsaidErlangmadesomeeasythingshard. Let’s findouthow. But now. That red pill. The result is chaos. and receiving a message (using !). you’ll get the payoff.0printing. will seem like candy to you. takethe blue pill. W e have a whole industry slamming blue pills like a preacher’s kid in Amsterdam.sowehavetodoextrawork toprotecteachpieceofcode.D AY 3: T HE R ED P ILL 207 6. If you send the process a string in Spanish. you’ll have to change the way you approach coding altogether. W e use threads with shared state rather than shared-nothingprocessesforperformance. ABasicReceiveLoop W e l’ start with a translation process.4 Day3:TheRedPill Most ofyouhaveheardit before. Y o u l’have to put up with a Prolog-based syntax that seems alien to many. Our functions and methods have side effects. In general. so we can’t prove correctness or predict their outcomes. your strategy will be to spawn a process that receives and processes the messageinaloop. Concurrency is hard.Sometimes.I’llshowyouhowtousethesethreeprimitivestosendandreceiveamessageandtowraptheminabasicclientserveridiom.W t i h out side effects and mutable state. Take the red pill. concurrency and reliability. and youreyesareopentoreality. Concurrency hurts. W e add mutable state.Inthissection.and you can continue to live in blissful ignorance. so we punt. Inthe matrix.realityhurts.October2010) . not because it is inherently difficultbutbecausewe’vebeenusingthewrongprogrammingmodel! Earlierinthechapter. so our programs collide when we run them concurrently. spawning a process (with (with receive). it will reply with an English translation. BasicConcurrencyPrimitives Y o u r three basic primitives for concurrency will be sending a message spawn).



Download erlang/translate.erl

-module(translate). -export([loop/0]). loop()-> receive "casa" -> io:format("house~n" ), loop();

"blanca" -> io:format("white~n" ), loop();
_-> io:format("Idon'tunderstand.~n" loop() end. ),

That’s longer than our other examples so far, so we’ll break it down. translate andexportthe Thefirsttwolinesjustdefinethemodulecalled loop(): functioncalled loop.Thenextblockofcodeisthefunctioncalled
loop()-> ... end.

loop() threetimes,withoutanyreturns. Noticethatthecodeinsidecalls That’s OK: Erlang is optimized for tail recursion, so there’s very little receive clause is a loop(). overhead, as long as the last thing in any W e r ’e basicallydefininganemptyfunctionandloopingforever.Moving ontothe receive:
receive-> ...

receive This function will receive a message from another process. case works like the other pattern matching constructs in Erlang, the and the function definitions. Y o u l’ follow receive with several pattern matchingconstructs.Movingontotheindividualmatches:
"casa"-> io:format("house~n"), loop();

case This is a matching clause. The syntax is nicely consistent with "casa", Erlang statements. If the inbound message matches the string

Reporterratum thiscopyis (P1.0printing,October2010)

D AY 3: T HE R ED P ILL , will execute the following code. Separate lines are delimited with a ; character.Thiscode character,andyou’llterminatetheclausewitha displays the word house and then calls loop. (Remember, there’s no loop is the last function called.) All of overhead on the stack, because theothermatchingclauseslookthesame.


Now, we have a module with a use. SpawningaProcess First,wecompilethismodule:
1>c(translate). {ok,translate}

receive loop in it. It’s time to put it to

spawn,whichtakesafuncTospawnaprocess,you’llusethefunction spawn tion. That function will be started in a new lightweight process. translate returnsaprocessID(PID).W e l’ passinthefunctionfromour module,likethis:
2>Pid=spawn(funtranslate:loop/0). <0.38.0>

<0.38.0>.IntheconY o ucanseethatErlangreturnedtheprocessIDof sole, you’ll see process IDs enclosed in angle brackets. W e r ’e going to cover only the primitive version of process spawning, but you should know about a few others too. Y o u can register processes by name, so other processes can find, say, common services by name rather than spawn forcodethatyou processID.Y o ucanalsouseanotherversionof wanttobeabletochangeonthefly,orhot-swap.Ifyouwerespawning spawn(Node, function) instead. These a remote process, you would use topicsarebeyondthescopeofthisbook.

Sonow,we’vecodedamodulewithacodeblock,andwe’vespawnedit asalightweightprocess.Thelaststepistopassmessagestoit.Thatis thethirdErlangprimitive. SendingMessages AsyousawinScala,youwillpassdistributedmessagestoErlangwith the ! operator.Theformis Pid!message .The Pid isanyprocessidentifier. message can be any value, including primitives, lists, or tuples. Let’s sendafewmessages:
3>Pid!"casa". "house" "casa"

Reporterratum thiscopyis (P1.0printing,October2010)

4>Pid!"blanca". "white" "blanca" 5>Pid!"loco". "Idon'tunderstand." "loco"


io:format in our receive clauses prints Each line sends a message. The amessage,andthentheconsoleprintsthereturnvalueoftheexpression,whichisthemessageyousent.

If you were sending a distributed message to a named resource, you’d usethesyntax node@server!message instead.Settinguparemoteserver isbeyondthescopeofthisbook,butwithverylittleself-study,youcan easilygetadistributedservergoing. Thisexampleillustratesthebasicprimitivesandhowyou’dweavethem together to form a basic asynchronous service. Y o u may have noticed that there is no return value. In the next section, we’ll explore how to sendsynchronousmessages.

Someconcurrentsystemsworkasynchronously,likephonechats.The sender transmits a message and goes on, without waiting for a response. Others work synchronously, like the W e b . W e ask for a page, and the web server sends it while we wait for the response. Let’s turn thetranslationservicethatprintsreturnvaluesintoaservicethatactuallyreturnsthetranslatedstringtotheuser. To change our messaging model from asynchronous to synchronous, we’llhaveathree-partstrategy: • Each receive clause in our messaging service will need to match a tuple having the ID of the process requesting the translation and the word to translate. Adding this ID will allow us to send a response. • Each receive clause will need to send a response to the sender insteadofprintingtheresult.
! primitive,we’llwriteasimplefunction • Insteadofusingthesimple tosendtherequestandawaittheresponse.

Now that you know the background, take a look at the pieces of the implementation.

Reporterratum thiscopyis (P1.0printing,October2010)



receive clausestotakeaddiThefirstorderofbusinessistomodifyour tional parameters. That means we’re going to have to use tuples. Patreceive clauselookslikethis: ternmatchingmakesiteasy.Each
receive {Pid,"casa"}-> Pid!"house", loop(); ...

W e matchanyelement(thisshouldalwaysbeaprocessID),followedby the word casa. W e then send the word house to the receiver and loop backtothetop. Note the pattern match. This is a common form for a receive, where theIDofthesendingprocessisthefirstelementofatuple.Otherwise, the only major difference is sending the result rather than printing it. Sendingamessagegetsalittlemorecomplicated,though. SendingSynchronously TheothersideoftheequationneedstosendamessageandthenimmeReceiver, sending a diately wait for a response. Given a process ID in synchronousmessagewilllooksomethinglikethis:
Receiver! "message_to_translate", receive Message->do_something_with(Message) end

Since we’ll be sending messages so often, we’ll simplify the service by encapsulating a request to the server. In our case, that simple remote procedurecalllookslikethis:
translate(To,Word)-> To!{self(),Word}, receive Translation->Translation end.

Whenyouputitalltogether,yougetaconcurrentprogramthat’sonly marginallymorecomplicated.

Reporterratum thiscopyis (P1.0printing,October2010)



Download erlang/translate_service.erl

-module(translate_service). -export([loop/0,translate/2]). loop()-> receive {From, "casa" }-> From! "house" , loop(); {From, "blanca" }-> From! "white" , loop(); {From,_}-> From! "Idon'tunderstand." loop() end. translate(To,Word)-> To!{self(),Word}, receive Translation->Translation end.


1>c(translate_service). {ok,translate_service} 2>Translator=spawn(funtranslate_service:loop/0). <0.38.0> 3>translate_service:translate(Translator,"blanca"). "white" 4>translate_service:translate(Translator,"casa"). "house"

W e simply compile the code, spawn the loop, and then request a synchronousservicethroughthehelperfunctionwewrote.Asyoucansee, r a n s a lt o r the T processnowreturnsthetranslatedvaluefortheword.And now,youhaveasynchronousmessage.
receive loop. Each process Now, you can see the structure of a basic hasamailbox.The receive constructjustpicksmessagesoffthequeue and matches them to some function to execute. Processes communicate between one another with message passing. It’s no accident that Dr.ArmstrongcallsErlangatrueobject-orientedlanguage!Itgivesyou messagepassingandencapsulationofbehavior.W e r ’ejustlosingmutable state and inheritance, though it’s possible to simulate inheritance, andmore,throughhigher-orderfunctions.
Reporterratum thiscopyis (P1.0printing,October2010)



Client (console)

Server (roulette)


So far, we’ve worked in basic, sterile conditions with no error recovery capability.Erlangdoesprovidecheckedexceptions,butIwanttowalk youthroughanotherwayofhandlingerrorsinstead.

LinkingProcesseso f rReliability
In this section, we’re going to look at ways to link processes for better reliability. In Erlang, you can link two processes together. Whenever a process dies, it sends an exit signal to its linked twin. A process can thenreceivethatsignalandreactaccordingly. SpawningaLinkedProcess Toseehowlinkingprocessesworks,let’sfirstcreateaprocessthatcan easily die. I’ve created a Russian roulette game. It has a gun with six chambers. To fire a chamber, you just send a number 1–6 to the gun process. Enter the wrong number, and the process kills itself. Here’s thecode:
Download erlang/roulette.erl

-module(roulette). -export([loop/0]). %sendanumber,1-6 loop()-> receive 3->io:format( _->io:format( end.

"bang.~n" ),exit({roulette,die,at,erlang:time()}); "click~n" ),loop()

The implementation is pretty easy. W e have a message loop. Matching 3 executes the code io:format("bang~n"), exit({roulette,die,at,erlang:time()}; , killing the process.Anythingelse just printsamessage andgoes back tothetopoftheloop. W e reallyhaveasimpleclient-serverprogram.Theclientistheconsole, r o u e lt e andtheserveristhe process,asshowninFigure6.1.
Reporterratum thiscopyis (P1.0printing,October2010)

Reason]). loop(). I guess that’s more of a coroner than a monitor.W e canactuallytellwhethertheprocessisalive: 7>erlang:is_process_alive(Gun). Here’swhatthecodelookslike: Download erlang/coroner.the programmustregistertheprocessasonethatwilltrapexits.~n" ). io:format("Monitoringprocess.~n" loop() end. {ok.roulette} 2>Gun=spawn(funroulette:loop/0). .0> 3>Gun!1.erl -module(coroner). the gun process is dead. W e r ’e onlyinterestedindeath. Reporterratum thiscopyis (P1.October2010) . and further messagesdonothing. receive {monitor. It’s time to get on the cart. Asusual.Reason}-> io:format("Theshooter~pdiedwithreason~p.true). {'EXIT'. 4 6>Gun!1.D AY 3: T HE R ED P ILL 214 Andhere’swhattheexecutionlookslike: 1>c(roulette).38.[From.Process}-> link(Process).0printing.Y o uwon’t receiveEXITmessageswithoutit. "bang" 3 5>Gun!4. "click" 1 4>Gun!3. ). loop()-> process_flag(trap_exit. Let’s build a monitor that will tell us whether the process dies. W e can do a little bit better. <0.we’rebuildinga receive loop.From." io:format("Startanotherone. false The process is definitely dead.Beforewedoanythingelse. 1 The problem is that after a 3. -export([loop/0]).

loop() end.0printing. The receive gets two types of tuples: those beginning with the atom monitor and those beginning with the string ’EXIT’.D AY 3: T HE R ED P ILL 215 Then.{8. {monitor.coroner} 3>Revolver=spawn(funroulette:loop/0).Itwillbeathree-tuple From and the with ’EXIT’.48. Pro- Thisisthecodethatmatchestheexitmessage. 3 Theshooter<0.Revolver}.onthefollowingpage.43.Y o ucanalsospawnaprocesswiththelinksalreadyinplacewith spawn_link.0> 5>Coroner!{monitor.W eprintthePIDofthedyingprocessandthereason.W e v ’e addeda monitorprocess.~n").0>diedwithreason {roulette.~n").2.Reason}-> io:format("Theshooterdied.we’regettingmoresophisticatedthanclient-server. Now.October2010) .0>} 6>Revolver!1. bang. followed by the PID from the dying process as reasonforfailure.<0. This code links the coroner process to any process with a PID of cess. Here’stheoverallflow: 1>c(roulette). Reporterratum thiscopyis (P1.Now.1}}.Movingontotrappingtheerror: {'EXIT'.die. io:format("Monitoringprocess.ifthemonitoredprocessshoulddie.43.Startanotherone.itwillsendanexit messagetothis coroner.asinFigure6.at.0> 4>Coroner=spawn(funcoroner:loop/0). <0. {ok.45.From.Process}-> link(Process). {ok.roulette} 2>c(coroner). <0.sowecantell whentheprocessdies. loop(). {monitor. we process a receive.Startanotherone. click 1 7>Revolver!3. Monitoringprocess.Let’slookateachinmoredetail.43.

loop()-> process_flag(trap_exit.Ifweregisterthegun(gunpunintended). .thecoronercanrestart the process whenever the process dies. register(revolver.true). and one that’s capable of raisingthedead.From." io:format("Restarting.wecan pushtheguncreationintothecoroner. receive new-> io:format("Creatingandmonitoringprocess.erl -module(doctor). loop(). Reporterratum thiscopyis (P1.~n" ).Finally. He’s a doctor.Reason}-> io:format("Theshooter~pdiedwithreason~p. self()!new. {'EXIT'.Then. the coroner is not just a coroner.2:Addingmonitoring FromCoronertoDoctor W e candobetter.gameplayerswillnolongerhavetoknowthePIDoftheguntoplay.0printing.October2010) . loop() end.D AY 3: T HE R ED P ILL 216 Monitor (coroner) Client (console) Server (roulette) Figure6. And we’ve achieved much better reliability and without excessive error reporting. -export([loop/0]).Here’sthenewdoctor: Download erlang/doctor.spawn_link(funroulette:loop/0)).[From.~n" ). At this point.Reason]).

W esendamessagetoourself.doctor} 3>Doc=spawn(fundoctor:loop/0). <0.W e nolongerneedthePID.Theyarebothalittledifferentfromthecoronerpredecessor. Creatingandmonitoringprocess.spawn_link(funroulette:loop/0)).we’llcreateandregisterone: 5>Doc!new. Y we in fact create and register a new revolver.0>diedwithreason{roulette.This new block: isthemagiclineofcodeinthe register(revolver. W e then register the PID. 8>revolver!4. ** exceptionerror:badargument inoperator !/2 calledasrevolver!1 As expected. associating itwiththe revolver atom.Here’sthenewlineofcode: self()!new. The overall topology is Reporterratum thiscopyis (P1.userscansendmessagestothisprocess byusing revolver!message .at.wespawnaprocesswith doctor will get notified version of spawn will link the processes so the o u e lt e whenever a r process dies.47.{8.0> 4>revolver!1.The gameismucheasiertoplay.W e interactwiththerevolverbysendingmessagesthroughthe o u can also see after line 8 that revolver atom instead of the Gun PID.TheEXITmatch blockisalsosmarter. click 4 revolver through the W e now take the incongruous step of creating the Doctor. bang. click 1 7>revolver!3. we have not created the process yet.That W o r k n ig fromtheinsideout. so we get an error.spawningandregisteringanewgun.53. 217 EXIT spawn_link. new 6>revolver!1.43.40}}.October2010) .0printing.too: 2>c(doctor).D AY 3: T HE R ED P ILL new and the same The receive block now matches two messages: tuple. {ok. Now. Restarting.die. Creatingandmonitoringprocess. 3 Theshooter<0.Now.

though the ideas that we used could be used to build fault-tolerant systems.W e startedwiththeconcurrencyprimitives:send.D AY 3: T HE R ED P ILL 218 generallythesameasitwasinFigure6. we built a simple helper function that encapsulated a send and a receive together to simulatearemoteprocedurecallwithasendandreceive. When something crashes. OpenTelecomPlatform(OTP)isapowerfulpackagewithmuchofwhat you’llneedtobuildadistributed.concurrentservice. Find: • AnOTPservicethatwillrestartaprocessifitdies • DocumentationforbuildingasimpleOTPserver Reporterratum thiscopyis (P1. playingamoreactiverolethanthe doctor W e v ’e just scratched the surface. so that a standby monitored the master and took over in the event of a problem. you started to get a pretty good feel for what you can do withErlang. Y o u don’t see much error handling here at all. Let’sputsomeofwhatyou’velearnedtowork. Day3Self-Study Theseexercisesarerelativelyeasy. Then. WhatW eLearnedinDay3 In day 3. and spawn.butIdidaddsomebonusquestions tostretchyoualittlebit. W e built the natural asynchronous version of a translator to illustrate how basic message-passing works.Oursystemwasnotfaulttolerant. we just start a new one. Erlangdistributedcommunicationworksexactlylikeinterprocesscommunication. the base libraries have plenty of tools to build monitoring services and keep-alives that Erlang restarts automaticallyuponanykindoffailure. It’s relatively simple to build monitors that watch each other. on separate computers.2.0printing. Next.onpage216. we linked processes together to show how one process notifies another when it dies. but I hope that you can see how Erlang can make it easy to create much more robust concurrent systems. W e also learned to monitor one process with anotherforbetterreliability.withthe coroner did.October2010) . In fact. W e could link two processes.receive.

Some of the capabilities are philosophical. DynamicandReliable First and foremost. ButErlanghassomecorecapabilitiesthatwillbetremendouslyimportant as new hardware designs make programming for concurrency more important.W RAPPING U P E RLANG 219 Do: • Monitorthe translate_service andrestartitshoulditdie. I said that Erlang made hard things easy and easy things hard.Erlang’sstrengthsareinthemostimportant areasthatthisgenerationofprogrammerswillface. Most impressively.thestateoftheartin programmingmustevolve. The following bonus questions will take a little bit of research to complete: • CreateabasicOTPserverthatlogsmessagestoafile. Doctor monitor. Erlang is built for reliability. Rather than depend on the compiler for an artificial safety net.andthefunctional programmingparadigmhasitsownsetofchallenges. Erlang depends on the ability to link Reporterratum thiscopyis (P1. The core libraries havebeentested.The “Letitcrash”philosophysimplifiescodetremendouslybutalsorequires basesupportatthevirtualmachinelevelthatjustdoesn’texistinother systems.Let’sbreakdownthecoreadvantagesanddisadvantages. CoreStrengths Erlangisallaboutconcurrencyandfaulttolerance. • Make a monitor for the restartit. 6. the language designers achieved this reliability without sacrificing the dynamic typing strategies that make Erlang so productive.fromtheinsideout. Asprocessordesignerslooktodistributedcores. If either monitor dies. The lightweightprocessesruncountertoJava’sthreadandprocessmodels. • Makethe translate_service workacrossanetwork.October2010) .0printing. • Makethe Doctor processrestartitselfifitshoulddie.5 WrappingUpErlang At the beginning of this chapter. The Prolog-style syntax is alien to those familiarwiththebroadfamilyofC-stylelanguages.andErlangapplicationsareamongthemostreliable and available in the world.

Share-NothingProcesses Another place Erlang shines is the underlying process model. Erlang processes are light.soprogrammersbuild systems that are inherently less likely to fail by conflicting with one another. it has twenty years worth of libraries that supportthisstyleofdevelopment. Reporterratum thiscopyis (P1. Y o u can build your own server processes thattakeadvantageofthesefeatures.Iwasastoundedabouthow easy it was to build dependable monitors without relying on operating systemkludges. LetItCrash When you’re dealing with parallel processes and no side effects. keep-alive processes. Like all the other languages in this book. Erlang buildsonaphilosophyofenforcingimmutability. IthinkthesetofcompromisesthatyoufindinErlangiscompellingand unique. link to databases. Erlang is tainted.scalability. O T P . Only the natureoftheproblemschanges.October2010) .theEnterpriseLibraries SinceErlanggrewupinatelecomcompanywithhighrequirementsfor availability and reliability.distributedsystems.0printing.TheprimarylibraryisOpenTelecom Platform (OTP).W RAPPING U P E RLANG 220 concurrentprocesses.OTPhasafullwebserverandmanytoolsforbindingtotelecom applications. The functional programming modelamplifiesthebenefitsofErlang’sdistributionstrategy. The message-passing paradigm and primitives make it easy to code applications with a level of separation that you rarely find in object-orientedapplications. “Let itcrash”works—you’renotasworriedaboutwhyindividualprocesses crash because you can restart them.Y o udon’t have to worry about them. Y o u can find libraries that help you build monitored.ThesearetheplacesthatAgentSmith maynotalwaysplaysonice. Lightweight.soit’srelatively easytobuildreliable. so Erlang programmers use them often.transactionalintegrity. Thenicethingaboutthesetoflibrariesisthatfaulttolerance. or build distributed applications.reliablyandsimply.andhot-swappingareallbuiltin. The Java language and virtual machine does not provide the rightsetofprimitivestoduplicateErlangperformanceorreliability.The librariesbuiltontheBEAMalsoreflectthisphilosophy.

Interestingly. a JVM-based VM called Erjang has made progress but is not yet to the level of the best JVM alternatives.andhavingtolureJava Reporterratum thiscopyis (P1. if and case constructs.Alittlesyntacticsugartoeasethetransitioncouldgoalong way. if. Cleaning theseupwouldhelpErlangtremendously. To most of the programming population.October2010) . In the chapter. Also.suchasaprocessandthreadingmodelthat’s inadequateforErlang’sneeds.ButbeingontheJVMhasasetofadvantages as well. The JVM doescomewithbaggage. byfarthebestimplementationisontheBEAMandnottheJavavirtual machine.W RAPPING U P E RLANG 221 CoreW e a k n e s s e s Erlang’s fundamental problems with adoption come from roots firmly plantedinanichelanguage. I mentioned the problems with The syntactic rules are logical—use a separator between statements— case. the functional programming paradigm is different enough that it will cause problems with widespread adoption. too. and the syntax comes off as awkward andalien. These restrictions are unnecessary.Thesyntaxisalientothevastmajorityof programmers. not being on the JVM has been a doubleedged sword.syntaxissubjective. as well as its weaknesses. Erlang faces someseriousobstaclesonthemarketingside. Syntax Likeamovie. FinalThoughts The success of a programming language is a fickle thing.0printing. including the wealth of Java libraries and the hundredsofthousandsofpotentialdeploymentservers. Recently.though.Let’sdiginalittledeeper. or but not practical because you can’t change the order of receive blocks without having to change your punctuation.Let’slookattwo ofthem. Prolog is obscure. some of Erlang’s core strengths come from the Prolog foundations.Beyondthisproblem. such as the conditional presentation of an array of numbers as strings. Integration As with the Prolog heritage. And there are other oddities.Erlang hassomeproblemsthateventheimpartialwillnotice. Finally.

In this battle between Anderson and Agent Smith. Reporterratum thiscopyis (P1. I give Agent Smithaneven-moneychanceatsuccess.W RAPPING U P E RLANG 222 programmersovertoaLisp-styleprogrammingparadigmandaPrologstyle syntax won’t be easy. Erlang does seem to be gathering momentum because it solves the right problems in the right way at the right time.October2010) .0printing.

2004.Bev- . there’s something special about Lisp that’s worth revisiting. Perplexing and powerful. 1. His communication style is often inverted and (understand me later y o u hard to understand. As with Lisp. StarW a r sEpisodeV :TheEmpireStrikesBack erlyHills. He seems too small to make a difference.LikeLisp’smacrosandhigher-order constructs. Lisp started it all. with wisdom (like the quote above) that has been honedbytimeandtriedunderfire. Dozens of dialectstriedtolaunchLispintothemainstreamandfailed.thereisnotry.In many ways. Lisp is one of the first programming languages and one of the latest too.1980. In many ways. so the new dialects continue to emerge. Think Y o d a .. Before diving in too deeply. or the enigmatic Jedi trainer.. In Star W a r s Episode 1 o d a was introduced as a cute character V : The Empire Strikes Back . like the Lisp syntactic rules with little more than parentheses and symbols. Some of the best programming universities lead with the Lisp language to form young mindswhiletheyarestillopen.DirectedbyGeorgeLucas. like Lisp prefix notation will). let’s talk a little bit about Lisp and then shift gears to what’s exciting about Clojure. Y e t .hehasaninnerpowerthatotherscan’tseemtomaster. But it quickly becomes apparent that there is more to Y o d a than meets the eye. Y with little significance. . he is old. Clojure is the wise kung fu master.Thesyntax andprogrammingmodelsofarhavebeentoomuchforatypicaldeveloper to absorb.CA:20thCenturyFox.Doordonot. the oracle on the hill. Y o d a Chapter 7 Clojure Clojure is Lisp on the JVM.

yougetalanguagethat’sidealfor metaprogramming.Lisphassome interestingcharacteristics: • Lispisalanguageoflists. The acronym standsforLIStProcessing. W t i h Scala.0printing. Y o u can build a pure-functional implementation.W t i htheLispsideoftheequationbehind us. It’s this flexibility that allows Lisp to morph the languageintojustaboutanyprogrammingparadigmyouwant. one of the most important characteristics is the JVM. Paul Graham chronicles the story of howasmalldevelopmentteamusedLispanditspowerfulprogramming model to defeat much larger companies.Y o ucanarrangeyourcodeasnamedmethodsina class. TheprimaryLisp dialectsareCommonLispandScheme. AllLisp After Fortran. you saw that having a commercially successful deployment platform can make all the Reporterratum thiscopyis (P1. Clojure is yet another Lisp dialect.Theprimarydifferencebetweenthedialect families has to do with the way namespaces work.Schemeand Clojure are from the same family of dialects called lisp-1. It will havethesamelanguagelimitationsandmanyofthesameconsiderable strengths.Y o ucouldarrangethoseobjectsintoatree.1 IntroducingClojure When all is said and done.theypaidmoreattentionto start-upspostingjobsrequiringLispandotherhigher-levellanguages. • Lisp uses its own data structures to express code.you’llseewhy. Whenyoucombinethesetwoideas.UnderstandingClojurestartswithunderstandingLisp.I NTRODUCING C LOJURE 224 7. They believed Lisp provided a significantprogrammingadvantage. and CommonLispisalisp-2dialect.andyouhaveabasic object model. For Clojure.andearlyon. Lisp followers callthisstrategy dataascode .Afunctioncallusesthefirstlistelement asthefunctionandtherestasthearguments. In Hackers and Painters [Gra04]. It’s a functional language but not a pure functional language. Common Lisp uses a separate namespace for functions and variables.let’smoveontotheJavaside. OntheJVM Every Lisp dialect caters to its audience. while Scheme uses thesamenamespaceforboth. Y o u could also build a prototype-based code organization with slots for data and behavior.Infact. Lisp is the oldest commercially active language.October2010) .

But you’ll alsoseeliberation. Y o u may first need to install the Java platform. Follow the instructions to install Clojure on your plat- form and with your preferred development environment. Updatedo f raConcurrentW o r d l The last piece of the equation for this language is the set of libraries.com/wiki/show/clojure/ Getting_Started.inthewayyou invoke it.Y o uusedclosuresinRubyandgraduatedtohigher-orderfunctionsinScalaandErlang.soyour code will be more concise. And ClojurehastheexpressivenessofLisp. concurrent access to memory.2.0printing. with emphasis on functions without side effects. But when you do use mutable state. though today.assembla.you’regoingtolearntoapply someofthoseconceptsinClojure. in the libraries we use. Lisp needs the market placethattheJavavirtualmachinecanoffer. Clojure is a functional language.Clojureisdynamicallytyped.wewill. Though the language is relatively new. easier to read.Inthischapter.you’llseeevidenceoftheJVM. Y o u don’t have to sell a Clojure server to your deployment people to use it.theapprenticeLukejoinedwithY inginthewaysoftheJedi.Hehadstartedhistrainingunderanother. you have already started your training for functional languages. Transactional memory works like transactional databases to provide safe. Like Luke.too.soyou’llbeabletoapply advancedconceptstoyourcode.W e l’cover someoftheseconceptsinday3. Throughoutthischapter. Impatientareyou?StartwithClojure. and more fun to write.October2010) . the language supports a number of concepts to help.andtheJavacommunity needsaseriousupdateandaninjectionoffun. GototheClojurehomesiteat http://www. youcanaccessthetensofthousandsofJavalibrariestodojustabout anythingyouneed. I’m using a prerelease version of Clojure 1. Clojure and Java desperately need each other. and it should be fully ready by the time this book is in your hands.D AY 1: T RAINING L UKE 225 difference in the world.Clojureisfunctional. and in artifacts we create.2 Day1:T r a n in i gLuke In StarW o d aforadvancedtraina r s . 7. most operating systems come with Java Reporterratum thiscopyis (P1.Agentsallowencapsulatedaccesstomutableresources.

the console is working.and I’m off to the races. CallingBasicFunctions user=>(-1) -1 user=>(+11) 2 user=>( * 1010) 100 That’sjustbasicmath. you have a primitive console.Y o ucannestthem. Once that’s installed.com/technomancy/leiningen Reporterratum thiscopyis (P1. you’ll enclose any function call entirelyinparentheses. Y o u r installation may require you to start the repl some otherway.I’lljusttellyoutostarttherepl. In Clojure. Underneath.0printing.calledtherepl: seven-languagesbatate$leinrepl Copying2filesto/Users/batate/lein/seven-languages/lib user=> .youcanusethisrepl.IcanstarttheClojureconsole.D AY 1: T RAINING L UKE 2 installed..Let’sdemonstratethe conceptwithalittlemath..Thefirstelementisthefunctionname.October2010) .Thattoolletsmebuildaprojectandinsulates me from the Java details such as classpaths.Fromhereonout.too. I canthencreateanewproject: 226 batate$leinnewseven-languages Creatednewprojectin:seven-languages batate$cdseven-languages/ seven-languagesbatate$ Then.oryoucanuseoneofanynumber ofIDEsoreditorsthathaveClojuresupport. http://github. When I ask you to evaluatecode. I’m using the leiningen tool to manage my Clojure projects andJavaconfiguration. After all of that work.Divisionisalittlemoreinteresting: user=>(/13) 1/3 2.andthe restarethearguments. Let’stypesomecode: user=>(println"GivemesomeClojure!") GivemesomeClojure! nil So. leiningen is installing some dependencies and calling Java with a few Clojure Java archives (jars) and options.

It’salittleawkwarddoingmathinthisway.D AY 1: T RAINING L UKE user=>(/24) 1/2 user=>(/2.Afterwarmingup.04) 0.itis (-(-81)2) and (/(/82)2) .butitworks.youshouldbegettingintotheflowofprefixnotation.Y o ucanalsogetsomesurprisingly powerfulresultsoutofsimpleoperatorevaluation: user=>(<123) true user=>(<1324) false Reporterratum thiscopyis (P1. Languages to this point have supported infix notation. with the 4 + 1 .Ratio 227 Clojurehasabasicdatatypecalleda ratio. Prefix notation with parentheses does have advantages. though.ifyou’dliketoseetheClojureequivalentusingonlytwooperandsat atime.Y o ucaneasilycalculateremainders: user=>(mod54) 1 That’s short for modulus operator.Andcheckoutthisexpression: user=>(+2222) 8 Y o u can easily add elements to the calculation. Many people prefer infix operator between the operands. Y o u canevenusethisstylewhenworkingwithsubtractionordivision: user=>(-812) 5 user=>(/822) 2 W e v ’eevaluated(8-1)-2and(8/2)/2inconventional(infix)notation. if you so choose. like notationbecausewe’reusedtoit.2 . Or. Considerthisexpression: user=>(/(/122)(/62)) 2 There’snoambiguity.0printing. This notation is called prefix notation.Y o ucanstill easilyworkinfloatsifyousochoose.It’sanicefeaturethatwill allowdelayingcomputationtoavoidthelossofprecision.October2010) .Clojurewillevaluatethisstatementinparentheticalorder.W e r ’e usedtoseeingmathexpressed inthisway.5 user=>(class(/13)) clojure.lang.

likethis: user=>(str"yoda. we’ve used a single argument with println. because in Lisp. so far.05) 8. they are one and the same.Y o u l’enclosestringsindoublequotes.Ingeneral. Let’s get a little more focused and lookatsomeofClojure’sbasicbuildingblocks. Asidefromtheprefixnotationandtheextrawrinkleofmultipleparameter lists. sets.0printing.I’mnotgoingtodistinguishbetween code and data.Thisfunctiontakesmorethanoneargument.October2010) .youcanconvertthingstoastringwiththe user=>(str1) "1" str function: str will call the underlying If the target underneath is a Java class. Clojure’s syntax is very simple. Let’s try to push the typing systemalittle.probingforstrongtypingandcoercedtypes: user=>(+3. toString function.""luke. W e can see whether a list is in order with a single operator and anarbitrarynumberofarguments. Then.anduseC-styleescaping characters.D AY 1: T RAINING L UKE 228 Nice. As an aside. it first breaks the program down into pieces called forms.luke. InClojure. StringsandChars Y o u v ’e already been introduced to strings. darth" Reporterratum thiscopyis (P1. When Clojure parses code. but we can take it a little deeper.you’llfindthatClojure supports strong. maps. Booleans.0) 8. characters.0 Clojureworkstocoercetypesforus. and vectors are all examples of forms thatyou’llseethroughoutthischapter.0 user=>(+35.asinRuby: user=>(println"masteryoda\nlukeskywalker\ndarthvader") masteryoda lukeskywalker darthvader nil No surprises. strings. Clojure cancompileorinterpretthecode. Think of a form as a piece of syntax.called forms.butthefunctionalsoworkswellwithzeroormoreargumentsto printablanklineorseveralvaluesconcatenatedtogether. dynamic typing. ""darth") "yoda.

something else. you can precede it with a likethis: user=>\a \a Andasusual.lang. acter outside of double quotes. Clojure’s types are unified with the underlying Java class function.Recallthatdynamictypingmeans typesareevaluatedatruntime. but let’s focus that discussion a little bit.youcanconcatenateitemsthatarenotstrings: user=>(str"one:"1"two:"2) "one:1two:2" 229 Y o ucanevenconcatenatedifferenttypestogether. BooleansandExpressions Clojurehasstrong.October2010) .charactersarenotstringsoflength1. As a result. Y o u can get the underlying class with the Here’stheclassofaboolean: user=>(classtrue) java. user=>(=(str\a)"a") true But you can easily convert characters to strings.0printing. That’s enough string manipulationfornow.D AY 1: T RAINING L UKE str to concatenate strings together.0) true user=>(=12) false user=>(<12) true true isasymbol.lang.Butitisalso Aswithmostotherlanguagesinthisbook.Boolean user=>(class(=11)) java.Boolean Reporterratum thiscopyis (P1.Y o u v ’ealreadyseenafewofthetypes in action.dynamictyping.youcanconcatenatethemtogetherwith user=>(str\f\o\r\c\e) "force" str: Let’smakesomecomparisons: user=>(="a"\a) false So.Torepresentachar\ character. Clojure developers use Conveniently. type system. A boolean is the resultofanexpression: user=>(=11.Let’smoveontosomebooleanexpressions.

Reporterratum thiscopyis (P1. we passed in code as the second argument to the niently.Maps.whatpassesfor a nil inClojure? user=>(first()) nil Ah.Now. maps. W e can make it prettier by breakingthecodeacrossmultiplelines: user=>(if(<12) (println"Falseitisnot. ConveLike Io.")) Trueitis.W e l’introduceotherbooleanexpressions asweneedthem. Lisp lets us treat the data as code.let’slookatsomemorecomplexdatastructures.youcanseetheJVMpeekingthrough. nil user=>(if(>12)(println"Trueitis.Sets.First.coredatastructuressuchaslistsand tuples do the heavy lifting.0printing.D AY 1: T RAINING L UKE 230 So.Y o ucanusethe if: resultofbooleansinmanyexpressions. Lists.Thistypestrategywillmake thingsfarmoreconvenientforyouasyoumovealong.Hereisasimple user=>(iftrue(println"Trueitis.October2010) .andV ectors Aswithallfunctionallanguages.W e l’ startthingsoffwiththecollectionyou’vespentmost ofyourtimewithsofar.thelist. 0 and "" aretrue.")) Falseitisnot.That’ssimple.but nil isnot. three big ones are lists.Thesymbolcalled user=>(if0(println"true")) true nil user=>(ifnil(println"true")) nil user=>(if""(println"true")) true nil nil. In Clojure. nil W e canaddan else asthethirdargument: user=>(iffalse(println"true")(println"false")) false nil Now.")) nil if.let’sseewhatelsewecanuseasbooleans. andvectors.

topreventconfusion. Vectors Likealist.0printing. Now.instead: user=>(list123) (123) user=>'(123) (123) Then.IFn(NO_SOURCE_FILE:0) If you really want a list made up of 1.Y o u l’surroundvectorswithsquarebrackets.though. lists are used for code and vectors for data. Sincelistsevaluateasfunctions.youcancombinethesewithhigher-orderfunctions.Integer cannotbecasttoclojure. last (the last element).avectorisanorderedcollectionofelements. and 3.youcan’tdothis: user=>(123) java.V e c t o r s areoptimizedforrandomaccess. rest (the list minus the head).Thesecondformiscalled quoting. but in idiomatic Clojure.D AY 1: T RAINING L UKE 231 Lists Alistisanorderedcollectionofelements.lang.ClassCastException:java. you need to do one of thesethings. Y o u likethis: user=>(first[:hutt:wookie:ewok]) :hutt user=>(nth[:hutt:wookie:ewok]2) :ewok can get various elements Reporterratum thiscopyis (P1. let’s move to a close cousinofthelist.lang.butwe’ll wait to do so until we encounter sequences. 2. The four main operations for a list are first (the head).youcanmanipulatethelistsasusual.October2010) .lang. likethis: user=>[:hutt:wookie:ewok] [:hutt:wookie:ewok] Use lists for code and vectors for data.thevector.Theseelementscanbeanything. and cons (construct a new listgivenaheadandatail): user=>(first'(:r2d2:c3po)) :r2d2 user=>(last'(:r2d2:c3po)) :c3po user=>(rest'(:r2d2:c3po)) (:c3po) user=>(cons:battle-droid'(:r2d2:c3po)) (:battle-droid:r2d2:c3po) Ofcourse.I’llwalkyouthroughlistswithdata.

too. ManyofthefunctionsthatreturncollectionsuseaClojureabstraction called sequences.setsandmaps. For now. just understand that Clojure is returning a sequence and rendering it as a listintherepl.ofcourse: user=>(first[:hutt:wookie:ewok]) :hutt user=>(rest[:hutt:wookie:ewok]) (:wookie:ewok) W e l’ use both of these features as we do pattern matching.D AY 1: T RAINING L UKE user=>(nth[:hutt:wookie:ewok]0) :hutt user=>(last[:hutt:wookie:ewok]) :ewok user=>([:hutt:wookie:ewok]2) :ewok 232 Note that vectors are functions.Thecollectionhasastable order.October2010) . Y o ucancombinetwovectorslikethis: user=>(concat[:darth-vader][:darth-maul]) (:darth-vader:darth-maul) Y o u may have noticed that repl printed out a list instead of a vector.likethis: countonit. Clojureletsyougetthetypicalheadandtailofavector.Let’smoveontosomeoftheunorderedcollections.0printing. so you shouldn’t #{}. Both lists andvectorsareordered.Y o u l’wrapasetin user=>#{:x-wing:y-wing:tie-fighter} #{:x-wing:y-wing:tie-fighter} W ecanassignthosetoavariablecalled them: spacecraft andthenmanipulate user=>(defspacecraft#{:x-wing:y-wing:tie-fighter}) #'user/spacecraft user=>spacecraft #{:x-wing:y-wing:tie-fighter} user=>(countspacecraft) 3 user=>(sortspacecraft) (:tie-fighter:x-wing:y-wing) Reporterratum thiscopyis (P1. taking an index as an argument. W e l’ learn more about them in day 2. Sets Asetisanunorderedcollectionofelements. but that order is implementation-dependent.

Use else.Symbolspointtosomething true and m a p aresymbols.likesymbolsinRubyoratomsin PrologorErlang. key-value pairs.likethis: user=>(#{:jar-jar:chewbacca}:chewbacca) :chewbacca user=>(#{:jar-jar:chewbacca}:luke) nil When you use a set as a function.:luke"yoda"} {:darth-vader"obiwan". That covers the basicsforsets.set/union#{:skywalker}#{:vader}) #{:skywalker:vader} Orcomputethedifference: (clojure. Sets are also functions.lang.set/difference#{123}#{2}) I’ll give you one last convenient oddity before I move on. like this: user=>{:darth-vader"obiwan".leading toanerror: user=>{:jabba:hut:han} java. the function will return the first argument if that argument is a member of the set.andkeywordspointtothemselves.Clojurehastwokindsofformsthatareusedtoname thingsinthisway.:lea:human} These are examples of maps. Maps Asyouknow.ArrayIndexOutOfBoundsException:3 Clojure solves this problem by allowing commas as whitespace. but they are tough to read.October2010) .0printing.likethis: user=>(clojure.likethis: user=>{:chewie:wookie:lea:human} {:chewie:wookie.amapisakey-valuepair. Reporterratum thiscopyis (P1. The set #{:jar-jar.you’llrepresent amapwithcurlybraces.:luke"yoda"} Awordprecededwith : isakeyword. :chewbacca} is an element but also a function. keywords and symbols.Setstestmembership.D AY 1: T RAINING L UKE 233 W e can also create a sorted set that takes items in any order and returnstheminsortedorder: user=>(sorted-set231) #{123} Y o ucanmergetwosets.Itwouldbehardtoseeanoddnumberofkeysandvalues.UsingClojure.Let’smoveontomaps.

3:three} W e r ’e graduallyaddingmorestructuretodata.:luke"yoda"} Now. defn todefinea Reporterratum thiscopyis (P1.Use function.:one1} x- Y o u can create a sorted map that takes items in any order and spits themoutsorted.youcanuseanydatatypeasakeyorvalue.Andyoucanmerge twomapswith merge: user=>(merge{:y-wing2.:luke"yoda"}) #'user/mentors user=>mentors {:darth-vader"obiwan". DefiningFunctions FunctionsarethecenterpieceofallkindsofLisps.3:three.:y-wing2.October2010) .:x-wing4}{:tie-fighter2:x-wing3}) {:tie-fighter2.wecombinedthe wing keyswith +.likethis: user=>(assoc{:one1}:two2) {:two2.youcanretrieveavaluebypassingakeyasthefirstvalue: user=>(mentors:luke) "yoda" Mapsarealsofunctions.Keywordsarealsofunctions: user=>(:lukementors) "yoda" :luke.youcancreateanewassociation withanewkey-valuepair.wecanmoveonto theformthataddsbehavior.It’soddbutuseful.:y-wing2.2:two.likethis: user=>(sorted-map1:one.Givenanassociation.:x-wing4}{:tie-fighter2}) {:tie-fighter2.Aswith Ruby.:x-wing4} Y o u can also specify an operator to use when a hash exists in both maps: user=>(merge-with+{:y-wing2. Let’sdefineamapcalled mentors: m a p asyou user=>(defmentors{:darth-vader"obiwan".Now.thefunction.2:two) {1:one.:x-wing7} 4 andthe 3 valuesassociatedwiththe Inthiscase.D AY 1: T RAINING L UKE 234 keywordstonamedomainentitiessuchasapropertyina wouldusean atom inErlang.thefunction.0printing.looksitselfupinamap.

D AY 1: T RAINING L UKE user=>(defnforce-it[](str"Usetheforce.returnstheemptystring. you can use this specifiesadocumentationline: user=>(docstr) ------------------------clojure." Ifyouwant.""Luke.Luke" doc feature on any other function that By the way. The function simply concatenated two stringstogether.returns x.")) #'user/force-it 235 The simplest form is (defn [params] body).0printing.Withmorethan onearg.core/str ([][x][x&ys]) Withnoargs.returnstheconcatenationofthestrvaluesoftheargs.let’smoveontotheparameter list. W e defined a function called o fr c e t i with no parameters. nil Nowthatyoucandefineabasicfunction.Luke.youcanspecifyanextrastringdescribingthefunction: user=>(defnforce-it "ThefirstfunctionayoungJedineeds" [] (str"Usetheforce."jedi)) #'user/force-it user=>(force-it"Luke") "Usetheforce.toString().""Luke")) Then.October2010) . Reporterratum thiscopyis (P1.youcanrecalldocumentationforthefunctionwith user=>(docforce-it) ------------------------user/force-it ([]) ThefirstfunctionayoungJedineeds nil doc: Let’saddaparameter: user=>(defnforce-it "ThefirstfunctionayoungJedineeds" [jedi] (str"Usetheforce. (strnil)returnstheemptystring.Callthefunctionlikeanyother: user=>(force-it) "Usetheforce.Withoneargx.

Theouterbracketsdefinethe parametervector.InEnglish. likethis: user=>(defncenter[[_[_c_]_]]c) #'user/center Reporterratum thiscopyis (P1. say you had a line.October2010) . It would be nicer to bind our parametertothesecondelementoftheline.Theinnerbracketssaywe’regoingtobindtoindivid_ and second areindividualparameters.Let’stakeacloser lookatthebindings.theprocessof assigning parameters based on the inbound arguments is called ing.likethis: user=>(defboard[[:x:o:x][:o:x:o][:o:x:o]]) #'user/board Now. and we want to return the value of the middle square. ualelementsofalistorvector. butit’sidiomatictouse _ forthefirstelement we’resaying“Theparametersforthisfunctionare second for the second element of the first of the first argument.wewanttopickupthesecondelementofthesecondrowofthree.W e have [[_second ]].” W e canalsonestthesebindings.it’seasy: (defnline-end[[_second]]second) #'user/line-end user=>(line-endline) [1020] Theconceptiscalled destructuring.likethis: user=>(defnline-end[ln](last ln)) #'user/line-end user=>(line-endline) [1020] But we don’t really need the whole line.Let’ssaywehaveatic-tac-toeboard.W t i hClojure. _ forparametersyouwanttoignore. For example. and argument.D AY 1: T RAINING L UKE 236 Bindings Asinmostoftheotherlanguageswe’velookedatsofar.representedasavectorofpoints.likethis: user=>(defline[[00][1020]]) #'user/line user=>line [[00][1020]] bind- Y o ucouldbuildafunctiontoaccesstheendoftheline. W e l’ represent theboardasthreerowsofthree.W e r ’e takingadatastructureapart andgrabbingonlythepiecesthatareimportanttous. One of the nice things about Clojure is its ability to access any portion of any argument as a parameter.0printing.

whicharethetopandbottomrowsinour tic-tac-toe board.Bothformsproduceequivalentresults. by extension. Y o u can see the influence of Lisp on Prolog and. First.Italldependsonwhereyou wantthedestructuringtohappen. W e l’ bind one parameter to the inboundargument. you’ll use e center could use let to hide the destructuring from the clients of the function: (defncenter[board] (let[[_[_c]]board]c)) let takes two arguments. [_ [_c_ ] _].Thatparametersayswe’regoingtoignore thefirstandthirdelements. skipping the first and picking out the name of the second map. First is a vector with the symbol you want to board) that you want bound.0printing. Y o ucandestructureamap: user=>(defperson{:name"Jabba":profession"Gangster"}) #'user/person user=>(let[{name:name}person](str"Theperson'snameis"name)) "Theperson'snameisJabba" Y o ucanalsocombinemapsandvectors: user=>(defvillains[{:name"Godzilla":size"big"}{:name"Ebola":size"small"}]) #'user/villains user=>(let[[_{name:name}]villains](str"Nameofthesecondvillain:"name)) "Nameofthesecondvillain:Ebola" W e bound to a vector. which is e r ’e [ _ c _ ].Destructuringissimplyaformofpatternmatching. Let’s break it down.D AY 1: T RAINING L UKE 237 Beautiful! W e r ’e essentially nesting the same concept. we don’t have to list any of the wildcard arguments that come after the targetarguments: (defncenter[[_[_c]]]c) let Next. Next bind ( [[_ [_c]]]) followed by the value ( is some expression that presumably uses that value (we just returned c). The bindings are [[_ [_ c _ ] _]].Erlang. but understand that you could also use them within an argumentlist.October2010) . destructuring can happen in the argument list or also in a let to bind a variable to a value.I’llshowyouacoupleofbriefexamples using let. W e l’ focus on the middle row. W statement. W expectinganotherlistandgrabbingthecenterone: user=>(centerboard) :x W e can simplify that function in a couple of different ways. Reporterratum thiscopyis (P1. In any Lisp.

sotheformlookslike Let’stakeanexample."HanSolo"]) #'user/people W e cancomputethelengthofonewordlikethis: user=>(count"Lea") 3 W e canbuildalistofthelengthsofthenames.Let’ssaywehavealistofpeople’snames: user=>(defpeople["Lea". you’ll define a higher-order function with the (fn [parameters*] body). Typijure. Reporterratum thiscopyis (P1. . functions are just data.likethis: user=>(mapcountpeople) (38) Y o u v ’e seen these concepts before. In Clojure. In Clofn function. just like any other list element.D AY 1: T RAINING L UKE 238 AnonymousFunctions In Lisp.like this: user=>(defntwice-count[w]( #'user/twice-count user=>(twice-count"Lando") 10 user=>(maptwice-countpeople) (616) * 2(countw))) Sincethatfunctionissosimple.Anonymousfunctionsletyoucreateunnamedfunctions. It’s a fundamental capability for every language in this book. Let’suseahigher-orderfunctiontobuildalistofwordcounts.givena listofwords. that concept is easy because a function is a list.wecanwriteitasananonymousfunction.0printing.October2010) . Higher-order functions are built into the language from the ground up because code is just like any other kindofdata. with % bound # iscalleda r e a d e rmacro toeachitemofthesequence.likethis: user=>(map(fn[w]( (616) * 2(countw)))people) W e canalsouseashorterform: user=>(map#( (616) * 2(count%))people) W t i h the short form. Y o u can use the same building blockstocomputealisthavingtwicethelengthsofpersonnames.you’llomitthename. # defines an anonymous function. count in this context is a higherorder function. cally.

CreatorofClojure Rich Hickey answered some questions for the readers of this book.hastosay.withasolidconcurrencystory. xy) . we’re going to use a commonvector.Herearesomeofthefunctionsoncollectionsthatuse higher-order functions.dynamiclanguage.October2010) .extensible. apply apply appliesafunctiontoanargumentlist.Fornow.for theindustry-standardplatformsoftheJVMandCLRanddidn’tfindone. Bruce Tate: WhydidyouwriteClojure? Rich Hickey: I’mjustapractitionerwhowantedapredominantlyfunctional.0printing. Reporterratum thiscopyis (P1. so this interview is a little more extensive thanmost.IhopeyoufindhisanswersasfascinatingasIdid. For example.called v: user=>(defv[312]) #'user/v W e l’ use that list with several anonymous functions in the following examples. It takes a function that is a test and returns the sequence of elements that pass the test.D AY 1: T RAINING L UKE 239 Anonymous functions give you convenience and leverage to create a function that doesn’t need a name o u v ’e seen them in right now . Y otherlanguages.likethis: user=>(apply+v) 6 user=>(applymaxv) 3 (applyf’(xy)) workslike (f filter The filter function works like find_all in Ruby.let’stakeabreakandseewhat RichHickey. For all of these functions.use this: user=>(filterodd?v) (31) user=>(filter#(<%3)v) (12) W e l’ takeadeeperlookatsomeoftheanonymousfunctionsaswelook deeperintoClojuresequences.creatorofClojure.togetonlytheoddelementsortheelementslessthan3. He had a special interest in why this Lisp version could be more broadly successful than other Lisps. InterviewwithRichHickey.

http:// www.infoq.weplaywellwithotherlanguages.October2010) .D AY 1: T RAINING L UKE 240 Bruce Tate: Whatdoyoulikeaboutitthemost? Rich Hickey: Iliketheemphasisonabstractionsinthedatastructures and library and the simplicity. Bruce Tate: What’s the most interesting problem you’ve seen solved withClojure? Rich Hickey: IthinkFlightcaster 3 (aservicethatpredictsflightdelays inr e a ltime)leveragesmanyaspectsofClojure—fromusingthesyntactic abstraction of macros to make a DSL for the machine learning and statistical inference bits to the Java interop for working with infrastructure likeHadoopandCascading. W e work better in teams.isdesignedtobeapractical toolforgeneralpurposeproductionprogrammingbydevelopersinindustryandassuch adds these additional objectives to the Lisps of old.com/ articles/ flightcaster-clojure-rails Reporterratum thiscopyis (P1. Clojure. while Common Lisp strove tostandardizethemanyvariantdialectsofLispbeingusedinr e s e a r c h . but Clojure r e c o g n z ie s that 3. Bruce Tate: ButhowcanClojurebemorebroadlysuccessfulwhenso manyotherdialectsofLisphavefailed? Rich Hickey: Thisisanimportantquestion!I’mnotsureIwouldcharacterizethemajordialectsofLisp(SchemeandCommonLisp)ashaving failedattheirmissions.Boxednumbers are certainly a sore spot on the JVM.ontheotherhand. Maybe that’s two things. Bruce Tate: HowdoesClojureworkbetterinateamsetting? Rich Hickey: ThereisasenseinwhichsomeLispsareallaboutmaximally empowering the individual developer. This is an area I am actively workingon.Schemewasanattemptataverysmalllanguage that captured the essentials of computation. but they are r e a lt e d .0printing. Bruce Tate: What feature would you change if you could start over again? Rich Hickey: I’dexploreadifferentapproachtonumbers. They have failed to catch on as practical tools for general-purpose production programming by developers in industry.andwesolvesometraditional Lispproblems. something that neither wasdesignedtobe.

OlderLispsuseparenthesesforeverything. Clojure emphasizes language-on-platform ratherthanlanguage-is-platform.D AY 1: T RAINING L UKE 241 development is a team effort. Bruce Tate: Whydidyouchoosetorunonexistingvirtualmachines? Rich Hickey: The existence of large and valuable code bases written inotherlanguagesisafactoflifetodayandwasn’twhentheolderLisps were invented. we wanted to deal with the parentheses “problem. it doesn’t support user-defined r e a d e r macros.especiallyontheJVMandCLR.October2010) .ButhowisthisLispanymoreapproachable? Rich Hickey: Lots of r e a s o n s . The combination of fewer parentheses and almost no overloading of parentheses r e n d e r s Clojure much easier to scan.LikeScalaandErlang. than in Clojure mon in Java code. For example.Technically.avirtualmachineforthe. r baz) parentheses. and understandthanolderLisps. I don’t think moving from to (foo bar baz) is difficult for developers. which could lead to code being written in small incompatiblemicro-dialects. Itallowslimitedsideeffects.therearesimplytoomanyparentheses. The industryisordersofmagnitudelargernow.” Lisp programmers know the value of codeis-data.Clojuretakestheopposite approach. but it is wrong to simply dismiss those who are put off by the o fo ( b a .doingawaywiththegroupingparentheses. visually parse. So. WhatW eLearnedinDay1 ClojureisafunctionallanguageontheJVM. and it could.makingitslightly harderformacrowritersbuteasierforusers.thestratificationthatsupportsther e u s eofcoretechnologieslikesophisticatedgarbagecollectorsanddynamiccompilerslike HotSpot is a good thing. Microsoft’scommonlanguageruntime. The ability to call and be called by other languages is 4 critical. But I did take a hard look at the parentheses use in the older Lisps to see whether the story could be better.W edon’t.Andinolder Lisps.Clojureaddsa 4. For example.0printing.UnlikeotherLispdialects. the horrid code.Leadingdoubleparenthesesaremorecom((AType)athing). Bruce Tate: Fairenough. The whole idea of standard multilanguage platforms abstracting away the host OS barely existed when the older Lisps were invented.NETplatform Reporterratum thiscopyis (P1.amethod().anddefactostandardshave arisen.this Lispdialectisafunctionallanguagebutnotapurefunctionallanguage.

providing a name. Y o u canusecommasforwhitespaceandomitparenthesesinsomeplaces. and growing. Next. They were among the best that I found as I researchedthisbook. we’ll look at recursion in Clojure. numbers. Find: • ExamplesusingClojuresequences • TheformaldefinitionofaClojurefunction • Ascriptforquicklyinvokingthereplinyourenvironment Do: (bigstn) thatreturnstrueifastring • Implementafunctioncalled islongerthan n characters.Finally. Reporterratum thiscopyis (P1. Lists and vectors were ordered containers with vectors optimized for random access and lists optimized for ordered traversal.0printing.October2010) . preferring braces for maps and brackets for vectors.Thesimplerformsincluded booleans.whichwerekey-valuepairs. :map. a basic building block in most functional languages. W e also broke into the various collections. we used deconstruction with bindings. or unordered collections.D AY 1: T RAINING L UKE 242 little syntax. On day 2. The feature was reminiscent ofPrologorErlang.we’lltakeabreaktoputintopracticewhatyou’velearnedsofar.wedefinedsomeanonymousfunctionsand usedthemtoiterateoveralistwiththemapfunction. Now. and function body with an optional documentation string. and strings. •W r t i e a function called or :vector basedonthetypeofcollection col. Day1Self-Study Clojure is a new language. W e defined some named functions.somecornerstonesoftheClojuremodelsthathelplayera common. W e learnedtousethebasicClojureforms. parameter list. W e also used sets. W e l’ also look at sequences and lazy evaluations. but you’ll still find a surprisingly active. keywords. st (collection-type col) that returns :list. allowing us to bind any parameter to any part of an inbound argument. and maps. characters.powerfulabstractionontopofcollections. community.

theabstractionlayerthatunifiesallClojurecollectionsand tiesthemtoJavacollections. we get to the concepts fundamental to Clojure.thejustin-timestrategythatcomputessequencemembersonlywhenyouneed them.themacro. Y o d a trained apprentices to use and understand the Force. Here’s a recursive program toevaluatethesizeofavector: (defnsize[v] (if(empty?v) 0 (inc(size(restv))))) (size[123]) It’s not hard to understand.givenavector. so recursive algorithms will continue to consume memory until all memory is exhausted. The size of an empty list is zero. loop thevaluesintheoddpositions. Reporterratum thiscopyis (P1.Thinkofaloopasa (loop[xx-initial-value.ifyoudon’tspecifya worksexactlylikea let: user=>(loop[x1]x) 1 The function recur will invoke the loop again but this time pass new values.Infact. Recursionwithloopandrecur Asyou’velearnedinotherlanguagesinthisbook. Clojure does not support implicit tail recursion optimization because of limitations of the JVM. In this section.D AY 2: Y ODA AND THE F ORCE 243 7. Y o u must explicitly recur through let statement.yy-initial-value](do-something-withxy)) Initially.0printing. Y o u v ’e also learned that stacks can grow. the size of another list is one more than the size of the tail.October2010) . W e l’ talk about sequences. W e v ’e seen similar solutionsforotherlanguagesthroughoutthisbook.3 Day2:Y oda andtheForce As a Jedi master.functionallanguages depend on recursion rather than iteration. the unifying presence between all living things.Andthenwe’lllookatthatmysticallanguagefeaturethatisthe ForceforallLisps. loop bindsthevariablesintheevenpositionsto recur. theuseof loop and recur.W e l’ alsolookatlazyevaluation. Functional languages work around this limitation with tail recursion optimization.

Let’slookatthecommonsequencelibrary. Sequences wrap all Clojurecollections(sets.andthelike). rest.vectors. Clojure sometimes respondedwithalistintheconsolelikethis: user=>[123] [123] user=>(rest[123]) (23) Noticethatwestartedwithavector.butI’lltrytogive Reporterratum thiscopyis (P1. when you were working with vectors. including lazy sequences that we’ll get to later in this chapter.we’refreetoshifttomorepleasant matters. Sometimes. you won’t often need to use recur.includingJavacollections. Sequences A sequence is an implementation-independent abstraction around all the various containers in the Clojure ecosystem. and strings.It’stoorichand powerfultocoverentirelyinonesectionofachapter.youneedtodealwiththeproblems. c willmaintain acount.0printing.andeven file system structures (streams. Since we won’t actually return a value.we’llusethetail-recursion-optimized loop Inthesecondversionof and recur.strings. W t i hday2’sbadnewsoutoftheway.Thatmeanswecantreatallcollectionsina genericway. Sequences will start to take us into some of the features thatmakeClojurespecial. and cons.replactually respondedwithasequence. If youwantthecommunity.D AY 2: Y ODA AND THE F ORCE 244 Let’srefactorthe size functiontouse recur: (defnsize[v] (loop[lv.butwe’restuckwithmore kludgy lines of code. Also.c0] (if(empty?l) c (recur(restl)(incc))))) size. Earlier.maps.Butsince this function is built into some basic collection APIs. first. They also provide a commonabstractionforJavacontainers.October2010) .arrays. the JVM is a double-edged sword. Clojure gives you some excellent alternatives to recursion. we’ll maintain the resultinavariablecalledan accumulator.Inthiscase. Thisversionworkslikeatail-optimizedcall. In general. directories). if it supports the functions youcanwrapitinasequence.Theresultisnotalist.

Forexample. Y o u v ’e already seen filter. which calls a function on all the items in a And you’ve also seen m collectionandreturnstheresults. anyoftheitemsinthesequence: (somenil?[12nil]) true some istrueifthetestistruefor 5 Oneoftheitemsis nil. To grab only the wordswithalengthgreaterthanfour. T e s t s When you want to test a sequence.test. Reporterratum thiscopyis (P1.Y o ucanbuildasequenceofsquares ofallitemsinavector: user=>(map(fn[x]( (114925) * xx))[11235]) 5. some returnsthefirstvaluethatisnot nil or a fs le .Let’sshifttofunctionsthat changesequences. These take a sequence and a test function and return a v e r y ? boolean.D AY 2: Y ODA AND THE F ORCE 245 you a flavor of what’s available.0printing. I’m going to cover sequence functions thatchange.butI’mgoingtotouchonthem onlybriefly.oneoftheitemsisnotanumber. Moreprecisely. (some first [[ ] [1]]) returns 1.usethis: user=>(defwords["luke""chewie""han""lando"]) #'user/words user=>(filter (fn[word](>(countword)4))words) ("chewie""lando") a p .October2010) . not-every? and not-any? aretheinverses: user=>(not-every?odd?[135]) false user=>(not-any?number?[:one:two:three]) true Thesebehaveexactlyasyouwouldexpect.andcreatesequences. you will use a function called a predicate. e returns true if the test function is true for all items inthesequence: user=>(every?number?[123:four]) false So. ChangingaSequence The sequence library has a number of sequences that transform sequences in various ways.

theequivalentis reduce. W e applied the small-word? filter to y with :when (smallw o r d ?y) . o fd ll .October2010) . The is a member of toys. Let’s move on.Tocomputeaquicktotalorfactorial.let’stakeasimplecase.Recallthatalistcomprehensioncombinesmultiplelists and filters.:when(small-word?y)] (str"Ilike"x""y"s")) ("Ilikeredcars""Ilikebluecars") small-word?.Itgetsmoreinteresttraryfunctionthat’sappliedtoevery ingwhenyoubindtomorethanonelist: user=>(for[xcolors. taking the possible combinations of the lists and applying colors thefilters.AnywordthatislessthanfourcharW ewroteafiltercalled acters is small. y y is less than four characters.ytoys](str"Ilike"x""y"s")) ("Ilikeredblocks""Ilikeredcars" "Ilikeblueblocks""Ilikebluecars") The comprehension created every possible combination from the two :when keywordinthebindings: lists.First.Scala.y) . similartothewayamapworks: user=>(for[xcolors](str"Ilike"x)) ("Ilikered""Ilikeblue") [xcolors ] binds x toanelementfromthecolorslist. That’s an ideal combination.and inject inErlang.0printing.W ehaveacoupleoflists.InLisp.ytoys.W e canalsoapplyafilterwiththe user=>(defnsmall-word?[w](<(countw)4)) #'user/small-word? user=>(for[xcolors.usethis: user=>(reduce+[1234]) 10 user=>(reduce * [12345]) 120 Reporterratum thiscopyis (P1. o fd le lf t Y o u v ’eseen . and the size of code is dense but expressive.andRuby. and toys: user=>(defcolors["red""blue"]) #'user/colors user=>(deftoys["block""car"]) #'user/toys W e can apply a function to all the colors with a list comprehension. as you saw in ErlangandScala. (str"Ilike"x) isanarbix from colors.W e gotallpossibilitiesof (x.where x isamemberof colors.D AY 2: Y ODA AND THE F ORCE 246 The list comprehension combines maps and filters.

buttodothat. What if you wanted to create a sequence with no Thatwouldbeaninfinitesequence.Y o ucanspecifyanyincrement: user=>(range1103) (147) Y o udon’thavetospecifythelowerboundifthereisnoincrement: user=>(range10) (0123456789) Zeroisthedefaultlowerbound.D AY 2: Y ODA AND THE F ORCE 247 Y o ucansortalist: user=>(sort[3124]) (1234) andsortontheresultofafunction: user=>(defnabs[x](if(<x0)(-x)x)) #'user/abs user=>(sort-byabs[-1-432]) (-123-4) W e defineafunctioncalled abs tocomputeanabsolutevalueandthen use that function in our sort. Clojure supports ranges as functions.Theanswer is lazy evaluation.0printing. The sequence did not include10.Thesequencescreatedwithrangeare upper bound ? finite.you’regoingtohaveto getalittlelazier. In fact. Reporterratum thiscopyis (P1. FiniteSequenceswithrange Unlike Ruby. Let’s walk through creating some finite sequences andmoveintolazysequences. A range creates a sequence: user=>(range110) (123456789) Note that the upper bound is not inclusive. most sequences are lazy. infinite sequences of numbers are often easier to describe.butyoucan’tactually computeaninfinite sequence. LazyEvaluation In mathematics.you’doftenliketohavethesamebenefits. we’ll move on to functionsthatcreatesequences. These are some of the most important sequence transformation functions in Clojure. Clojure’ssequencelibrarycomputes values only when they are actually consumed.Let’sfindouthow. Using thisstrategy. Next.October2010) .Infunctionallanguages.

Fair enough.October2010) . and odd numbers are .dropthefirsttwo.Luke""UsetheForce.Asyoureadtheresult. If you try it in the repl. What if you wanted an interpose that took interposing interleave: membersfromasequence?That’s user=>(take20(interleave(cycle(range2))(cycle(range3)))) (00110210011200110210) W e r ’e interleaving two infinite sequences.drop2. andtakethefirstfiveafterthat. Clearly.wetakethefirst20. W e can specify (repeat 1) .Then.D AY 2: Y ODA AND THE F ORCE 248 InfiniteSequencesandtake Let’s start with the most basic of infinite sequences.Luke")) ("UsetheForce.evennum(0 1 2 0 1 2 0 1 2 0) bers are (0 1 0 1 0 1 0 1 0 1) .Luke""UsetheForce.Butyoudon’thavetoworkinsideout. ->>) to apply each function Y o u can use the new left-to-right operator ( toaresult: user=>(->>[:lather:rinse:repeat](cycle)(drop2)(take5)) (:repeat:lather:rinse:repeat:lather) So.weagainbuildacycle.wetakeavector.buildasequencewithcycle.andthentake 5.Thinkofthisfunctionlikeageneralizedversion of Ruby’s join.left-to-rightcodeiseasiertoread. W e user=>(take5(drop2(cycle[:lather:rinse:repeat]))) (:repeat:lather:rinse:repeat:lather) W o r k n ig fromtheinsideout. Beautiful.Y o ucanalsorepeattheelements y c e l : inalistwith c user=>(take5(cycle[:lather:rinse:repeat])) (:lather:rinse:repeat:lather:rinse) W e r ’e taking the first five elements of the cycle from the vector [:lather can drop the first few elements of a sequenceaswell: :rinse :repeat ]. Reporterratum thiscopyis (P1. So. we need take: somewaytograbonlyafinitesubset. you’ll get 1s until you kill the process.0printing.andthenwetookthefirstthree.Whatifyouwantedto interpose: addsomekindofseparatorbetweenwords?Y o u d ’ use user=>(take5(interpose:and(cycle[:lather:rinse:repeat]))) (:lather:and:rinse:and:repeat) W e r ’e taking the keyword :and and placing it between all the elements ofaninfinitesequence.Sometimes.wecreatedaninfinitesequenceoftherepeatedstring Luke".Luke") "UsetheForce. (cycle (range 2)) and (cycle (range3)) . an infinite sequence of one repeated element.Thatfunctionis user=>(take3(repeat"UsetheForce.

. W can generate an anonymous function to generate one pair..D AY 2: Y ODA AND THE F ORCE 249 The iterate functionprovidesanotherwayofcreatingsequences.likethis: (nth(mapfirst(iteratefib-pair[11]))500) (225.wecantakethefirst5: user=>(take5 (map first (iteratefib-pair[11]))) (11235) Orwecangrabthenumberatindex500. a + b ]. Using lazy sequences.Factorialisanotherexample: user=>(defnfactorial[n](apply #'user/factorial user=>(factorial5) 120 * (taken(iterateinc1)))) Reporterratum thiscopyis (P1. we called inc and dec. Given a pair. we can generate the next with e [b. Here’s an example that calculates consecutive pairs in the Fibonacci sequence.October2010) .Check outtheseexamples: user=>(take5(iterateinc1)) (12345) user=>(take5(iteratedec0)) (0-1-2-3-4) iterate takes a function and a starting value.eachnumberofasequenceisthesumofthelast two. given the previousvalue.626) The performance is excellent..likethis: user=>(defnfib-pair[[ab]] [b(+ab)]) #'user/fib-pair user=>(fib-pair[35]) [58] Next. you can often describerecursiveproblemslikeFibonacci. In these two examples. Don’t execute this yet: (iteratefib-pair[11]) W e l’ a p tograbthefirstelementfromallofthosepairs: use m (map first (iteratefib-pair[11])) That’saninfinitesequence.. [a b ].Remember. we’ll use iterate to build an infinite sequence. iterate then applies the function to the starting value repeatedly.morenumbers.0printing.Now.

and right with Reporterratum thiscopyis (P1.Let’sgetstarted. Now that we’ve spent some time with lazy sequences. timetoexplorenewClojurefunctionscalled 250 defrecordandprotocols So far. and the worst parts are implementation inheritance.0printing.we’lldefineaprotocol. but you haven’t seen much of the JVM bleed through to the Clojure language. AsClojurepickedupmorespeedandbegantoproveitselfasaneffective JVM language.fields.) To make Clojure integrate well with the JVM. cofounder of Relevance and author of Programming Clojure [Hal09]. I’m going to lean hard on Stuart Halloway. First. left.Here’sa protocol describinga Compass: Download clojure/compass. Think of interfaces as Java classes without implementations. W e r ’e going to go back to another functional language on the JVM. Clojure’s defrecord and protocol preserve the good parts of OO and leave therest. to help walk through a practical implementation.Types ofthisprotocolwillsupportaspecificsetoffunctions. Whenallissaidanddone.October2010) . the original implementation has a significantamountofJavainit. there was a strong thrust to implement more of Clojure in Clojure itself. Clojure developers needed a way to build platform-fast open extensions by programming to abstractions defrecord for types and rather than implementations.(For you non-Java programmers.clj (defprotocolCompass (direction[c]) (left[c]) (right[c])) Compass and enumerates This protocol defines an abstraction called thefunctionsthata Compass mustsupport— direction. Then we W e grab n elements from the infinite sequence apply *. As this book is being written. From a Clojureperspective.AClojure protocol islikeacontract. think of types as Java classes. The results are protocol.andarguments. these language features are important. we’ve talked about Java integration at a high level.D AY 2: Y ODA AND THE F ORCE (iterate inc 1) . which groups functions together around a type. but they are evolving. Scala.thebestpartsofOOaretypesandprotocols(suchas interfaces).theJVMisabouttypesandinterfaces. To do so. W e l’ rewrite the CompassprograminClojure.Thesolutionis takenofthemandmultiplythemtogetherwith dead simple. it’s defrecord and protocol.

Next. W e l’ take the remainder of the base/number-of-directions) so that we’ll wrap around correctly from :west to :north. :south. W e do that with defrecord. For example.likethis: (defnturn [baseamount] (rem(+baseamount)(countdirections))) Theturnworks. W e l’ do defrecord todeclarewe’reimplementingthe thatinpieces.weuse protocol. but we’re a reference to the instance (e.Ithasonefieldcalled Compass protocol.soweadd (left[_](SimpleCompass.turningrightoncefrom rightoncefrom :west givesyou :north.ontoleftandright: notusingit.likethis: (defrecordSimpleCompass[bearing] Compass W e r ’e defininganewrecordcalled SimpleCompass.and 3 represent :north. It’stime to implement the protocol.Next.D AY 2: Y ODA AND THE F ORCE 251 the specified number of arguments. Next. Each argument list has self in Ruby or this in Java). W e are now free to implement the protocolwith defrecord.justasyou’dexpect.andturningrightthreetimesfrom :south givesyou :east.(turnbearing3))) (right[_](SimpleCompass.First.October2010) . we will implement the the direction function: (direction[_](directionsbearing)) directions at the bearing The direction function looks up the element of index. to the right.turning Saidanotherway.I’llloadthecompassfileandthen usethe turn functions: user=>(turn11) 2 user=>(turn31) 0 user=>(turn23) 1 :east givesyou :south.Recallthatourbasedirectionis aninteger. (directions 3) returns :west.respectively.Every 1 youaddtothebasewillmovethecompassninetydegrees base/4 (more precisely.we’llneedthefourdirections: (defdirections[:north:east:south:west]) W e l’ needafunctiontohandleaturn. 2.g. beginning with bearing. _ toourargumentlist.(turnbearing1))) Reporterratum thiscopyis (P1. 1.and :west.. 0.0printing. :east.

the left and right functions are easy.Object.Sincewe’redefiningaJVM type.0printing.Thatmeansthat turningwillreturnanew.That’seasyenoughtoaddtoourtype.inClojure.Y o ucanverifythatentering (String. Object (toString[this](str "[" (directionthis) "]" ))) Object protocolwiththe toString method.usingthe turn function we defined earlier.we’reusingimmutablevalues. right turns right ninety degrees once.originalcompassunchanged #:SimpleCompass{:bearing0} Noticethattheoldcompassisunchanged. and left turns right ninety degrees three times. So far. arg) means fire the constructor for Compass.binding arg tothefirstparameter.thetypeiscomplete. Y o u can also replace types as maps in your tests as stubs or mocks. W e thenimplementpartofthe SimpleCompass [:north]. Thereareotherbenefitsaswell: • TypesplaynicewithotherClojureconcurrencyconstructs. So.D AY 2: Y ODA AND THE F ORCE 252 Remember.0)) #'user/c Turnsreturnanewcompass: user=>(leftc). (SomeType.Inday 3.youcaneasilyprototypenewtypes asmapsanditerativelyconvertthemtotypesasyourdesignstabilizes. Each returns a new compass withtheappropriatebearing."newstring") intothereplreturnsthenewstring "newstring" . W e just need a toString is a method function that returns a string representation.lang. returningastringthatlookslike Now. you can access all fields as Java fields.Createanewcompass: user=>(defc(SimpleCompass.returnsanewcompass #:SimpleCompass{:bearing3} user=>c. we have a type SimpleCompass that implements the Compass protocol.modifiedcompassratherthanchangingthe left and right use syntax that you have existing compass in place. Both Simplenot seen before. But you can also access thefieldsinthetypeasClojuremapkeywords: user=>(:bearingc) 0 Becausethesetypesworklikemaps.October2010) . we’ll learn how to create mutable references of Clojure objects Reporterratum thiscopyis (P1.configuredforthenewbearing. but on java.

we’ll put a quote in front of theexpressionwewanttoexpand: user=>(macroexpand''something-we-do-not-want-interpreted) (quotesomething-we-do-not-want-interpreted) Reporterratum thiscopyis (P1. Now that you’ve learned to extend Java.October2010) .dangerWillRobinson nil W e discussed this problem in Io. including Java classes or interfaces.withoutJava.Thiscodecanfullyinteractwithother types on the JVM.andanumbersign( function.muchlikerelational databasesdo. In Io. Most languages execute parameters first and then put the results on the call stack.Theformis test o fr m 1 ) o fr m 1 fs le . •W e implementeda protocol. Messages.onpage79. The function will execute if the test is a e can’t simplydesignafunction. W . In Lisp. Since we’re building JVM types. let’s learn how to extend the Clojure language itself with macros. To prevent premature execution.Macroexpansiontranslates allmacrosinthelanguagetotheirexpandedform.Macrostotherescue.butyou’renotlimitedtothenewway of doing things. we can use macros. Macros Forthissection.3.this is not the entireJava interop story.a e a d e rmacros #)isananonymous singlequotemark( ’)isaquote.called r .W e v ’e already used a coupleofmacros. we don’t want to evaluate the block unless the condition is false.dangerWillRobinson")) Danger. message.we’regoingtorefertotheIochapter. the types can interoperatewithJavaclassesandinterfaces.0printing. When we type (if(nottest)body) .Brokenunless user=>(defnunless[testbody](if(nottest)body)) #'user/unless user=>(unlesstrue(println"Danger.becauseeachparameterwillexecute: user=>.)isacomment.Asemicolon( .W e implemented (unless theRuby unless inSection3.Javaclassescan also build on your Clojure types.Y o ucanseewhat’s m a c r o e x p a n d happening with a command called . W t i h defrecord and protocol. Clojure offers the ability to build native codefortheJVM. the lanunless guagecircumventedthisproblembydelayingtheexecutionofthe (unless test body) . Of course. Y o u can use themtosubclassJavatypesorimplementinterfaces. In this case. wewantLisptotranslatethatto AClojureprogramexecutesintwostages. but it’s an important part.D AY 2: Y ODA AND THE F ORCE 253 inwaysthatmaintaintransactionalintegrity.

quote it. Let’swrapupday2. macro expansion will let you treat code like lists.welearnedtouserecursion.0printing. If you don’t want a function to execute right away.W butwehavetoquote e alsohavetopackagetheminlists. Reporterratum thiscopyis (P1. W e r ’e buildingalistofcodeintheexactformthatClojurewillexecute.October2010) . W e are adding our own control structure. First.")) Now.Thatloopingconrecursionoptimization. Y o u v ’e added a tremendous set of abstractionstoyourexpandingbagoftricks. The secret sauce is the expression of data as code.W e whatwe’velearned. shouldpausetouse WhatW eLearnedinDay2 It’s been another packed day.wehadtouse struct allowed us to implement many algorithms you would usually implement with recursive function calls. unless willlooklikethis: Clojurewillreplacetheargumentsintact.There’salotofmeathere. The code is alreadyinahigher-orderdatastructure. and few languages can do it.D AY 2: Y ODA AND THE F ORCE user=>(macroexpand'#(count%)) (fn* [p1__97](countp1__97)) 254 These are macros. In general.Let’sreview.SincetheJVMdoesn’tsupporttailloop and recur.Will. though the syntax was more invasive.THISisTheFORCE.THISisTheFORCE. nil What we’ve done is change the base definition of the language.")) nil user=>(unlessfalse(println"Now. a c r o e x p a n d W e can m it: user=>(macroexpand'(unlessconditionbody)) (if(notcondition)body) Andwecanexecuteit: user=>(unlesstrue(println"Nomoredanger. without requiring the language designers to add their own keywords. Macro expansion is perhaps the most powerful feature ofLisp. if and not.Our user=>(defmacrounless[testbody] (list'if(list'nottest)body)) #'user/unless Note that Clojure substitutes test and body without evaluating them. not just a string.

•W r t i eatypeusing defrecord thatimplementsaprotocol.October2010) .Lazysequencessimplifiedalgorithms. Find: • Theimplementationofsomeofthecommonlyusedmacrosinthe Clojurelanguage • Anexampleofdefiningyourownlazysequence defrecord and protocol features(thesefea• Thecurrentstatusofthe tures were still under development as this book was being developed) Do: • Implementan unless withan else conditionusingmacros. Day2Self-Study This day was packed with some of the most sophisticated and powerful elements of the Clojure language.0printing. we could apply common strategies for dealing with collections. we used macros to add features to the language. we were able to implement types that were full citizens on the JVM. transform. potentially significantly improving performance and looseningcoupling. we were able to add another powerful layer to sequences. W e learned thatthereisastep. we spent some time implementing types. Reporterratum thiscopyis (P1. W t i h them. W t i h a common library. and search sequences.called macroexpansion .Theyalsooffereddelayed execution. W e used different functions to mutate.Takesometimetousewhatyou’velearned. Take some time to explore and understandthosefeatures.thatoccursbeforeClojure implements or interprets code. defrecord and proNext. There’salottodigest. W t i h lazy sequences. Higher-order functions addedpowerandsimplicitytothesequencelibraries. Clojure encapsulates access to all of its collections. W e implemented unless by using an if functionwithinmacroexpansion.D AY 2: Y ODA AND THE F ORCE 255 W e also used sequences. Finally. W t i h tocols.

IoandScalausedtheactor-basedmodelandprovided immutable constructs that gave the programmer the power to solve those problems without mutable state. Erlang provided actors with lightweight processes. All access must conform to specified rules. Toseehowitworks.let’screateareference: user=>(ref"AttackoftheClones") #<Ref@ffdadcd:"AttackoftheClones"> Reporterratum thiscopyis (P1. The Clojure approach to concurrency is different. Locks prevent two competing transactions from accessing the same row at the same time. are Languages like Clojure use software transactional memory (STM).whenyouwanttochangethestateofareferenceinClojure.Ruby.W e v ’e saidfrequentlythatmutablestateistheevilthatlurksintheheartsofobjectoriented programs. It uses software transactionalmemory (STM).Inthissection.October2010) .orIo. the databaseenginesimplyrerunsthattransaction. allowing unprecedented reliability.4 Day3:AnEyeo f rEvil In Star W o d a was the first to detect the evil in Darth V a d e r . W e rapidlylearningthatthisburdenistoomuchtobear. ReferencesandT r a n s a c o t in a lMemory Databasesusetransactionstoensuredataintegrity. and a virtual machine that allowed effective monitoring and communication.Moderndatabases use at least two types of concurrency control. In this case.RichHickeyhasidentifiedthecoreproblemsthatplague thedevelopmentofconcurrentobject-orientedsystems. a r s .youmustdosowithinthescopeofatransaction. Locking basically puts the burden of concurrency control on the programmer. Y o u cannot change a reference outside of a transaction.0printing. a r e f (short for reference) is a wrapped piece of data. LanguageslikeJavauselockingtoprotecttheresourcesofonethread from competing threads that might corrupt them. If any transaction interferes with another. W e v ’e shown several different approaches to handlingmutablestate. References In Clojure.Let’s seehowitworks.we’lllookatSTMandalso severaltoolstosharestateacrossthreadedapplications.Y W t i hClojure. UnlikeScala. V e r s o in n ig uses multiple versions to allow each transaction to have a private copy of its data. This strategy uses multiple versions to maintain consistency and integrity. the rules are to support STM.D AY 3: A N E YE FOR E VIL 256 7.

The dereferencedrefwillbepassedasthefirstargumentofthefunction: user=>(altermoviestr":TheEmpireStrikesBack") java.likethis: user=>(dosync(altermoviestr":TheEmpireStrikesBack")) "StarWars:TheEmpireStrikesBack" W e couldalsosetsomeinitialvaluewith ref-set: user=>(dosync(ref-setmovie"StarWars:TheRevengeoftheSith")) "StarWars:TheRevengeoftheSith" Y o ucanseethatthereferencechanged: user=>@movie "StarWars:TheRevengeoftheSith" That’swhatweexpected.D AY 3: A N E YE FOR E VIL 257 That’s not too interesting.likethis: user=>movie #<Ref@579d75ee:"StarWars"> Butwe’rereallyworriedaboutthevalueinthereference. W e likethis: user=>(defmovie(ref"StarWars")) #'user/movie should assign the reference to a value.0printing. W e know that programs that behave in this manner will absolutely execute correctly. and we’ll save STMfor the problemsthatcould benefitthe mostfrommutability.youcanusetheshortformof user=>@movie "StarWars" deref: That’sbetter.Now. Most of our code will use functional paradigms. Y o ucangetthereferenceback.W t i h Clojure.Thereferenceisdifferent. with respect to race conditions and deadlock.lang.October2010) . Reporterratum thiscopyis (P1.Itmayseempainful to modify mutable variables in this way.Use user=>(derefmovie) "StarWars" deref: Or.Doso withthe dosync function.Thepreferredwaytomodifyareferenceisto alteritwithsometransformingfunction. W e haven’ttriedtochangethestateofthereferenceyet. we’ll send a function that will mutate the value. but Clojure is enforcing a little policy now to save a lot of pain later.wecaneasilyaccessthevaluewithinourreference.Let’stry.youcanmutatestateonlywithinatransaction.IllegalStateException:Notransactionrunning(NO_SOURCE_FILE:0) Asyoucansee.

October2010) .you’llwanttocreateavalueonceandthenchange thatvaluewith swap!.:author"Halloway"}] Aswithareference.Createanatom: user=>(atom"Splitatyourownrisk.0printing." Y o ucanbind danger toanewvaluewith reset!: user=>(reset!danger"Splitwithimpunity") "Splitwithimpunity" user=>danger #<Atom@455fc40c:"Splitwithimpunity"> user=>@danger "Splitwithimpunity" reset! replaces the entire atom.D AY 3: A N E YE FOR E VIL 258 W o r k n i gwithAtoms If you want thread safety for a single reference. It’saperfectproblemforanatom. While references required transactions. atoms do not.:author"Tate"} {:title"ProgrammingClojure". Y o u l’see the same general philosophy when we work with Haskell."> user=>@danger "Splitatyourownrisk.:author"Tate"}] user=>(swap!top-sellersconj{:title"ProgrammingClojure":author"Halloway"}) [{:title"SevenLanguagesinSevenWeeks".Let’stryit. but the preferred usage is to provide a function to transform the atom. you’ve seen both references and atoms.W e l’ simplyusehashestoassociate Reporterratum thiscopyis (P1. Let’s build a simple atom cache. If you’re changing a large vector.Thesedataelementsallow changeoutsidethecontextofatransaction. BuildinganAtomCache Now.")) #'user/danger user=>danger #<Atom@3a56860b:"Splitatyourownrisk.Likeareference.") #<Atom@53f64158:"Splitatyourownrisk.thenyoucanuseatoms. you swap! likethis: canmodifyanatominplacewith user=>(deftop-sellers(atom[])) #'user/top-sellers user=>(swap!top-sellersconj{:title"SevenLanguages"."> Now.aClojure atom isanencapsulatedbitofstate.Let’slookatapracticalexample.bindanatom: user=>(defdanger(atom"Splitatyourownrisk. uncoordinated with anyotheractivity. Y o u wrap a bit of state in a package that you can later mutate with functions.:author"Tate"}) [{:title"SevenLanguagesinSevenWeeks".

Atomsandrefsaresimpleandsafewaystohandlemutablestate.Luke.0printing. W e l’ let the client of this class bind it. http://www. Next. Thesecondversionuses assoc toaddakeyandvalue.we’ll createthecache: Download clojure/atomcache.synchronously.clj (defncreate [] (atom{})) W e r ’e simply creating an atom. 6.thinkrelevance.weneedtobeabletogetacachekey: (defnget [cachekey] (@cachekey)) W e take the cache and a key as arguments.First. Finally. we’ll look at a couple of asynchronousexamples.Here’sthecache inuse.Luke. In the next few sections. 6 a consultancy that provides Clojure training and consulting. The first version uses W e defined two different functions called merge to allow us to add all of the associations in a map to our cache.D AY 3: A N E YE FOR E VIL 259 names with values." ) (println(str "Cacheditem:" (getac:quote))) Andtheoutput: Cacheditem:I'myourfather. This example is provided courtesy of Stuart Halloway of Relevance. W e l’ need to create the cache.October2010) . so we dereference it and return the item associated with the key.W e addanitemtothecacheandthenreturnit: (defac(create)) (putac:quote "I'myourfather. and then we’ll need functions to add elementstothecacheandremoveelementsfromthecache. weneedtoputaniteminthecache: (defnput ([cachevalue-map] (swap!cachemergevalue-map)) ([cachekeyvalue] (swap!cacheassockeyvalue))) put.com Reporterratum thiscopyis (P1. The cache is an atom.

agent.dothisfivesecondslater user=>@tribbles 4 (Thread/sleep 5000) simply invokes Don’t get hung up in the syntax.W t i hthisfunction. Java’s sleep methodon Thread.October2010) .Fornow. or atom will never lock and never block.wecanmutate tribbles bysendingtheagentavalue: user=>(sendtribblestwice) #<Agent@554d7745:1> Thisfunctionwillruninanotherthread. Giveitatry.0printing.D AY 3: A N E YE FOR E VIL 260 W o r k n i gwithAgents Likean atom.we’lldefineanagentcalled user=>(deftribbles(agent1)) #'user/tribbles tribbles thathasaninitialvalueofone: Now.Let’sdefineafunctioncalled ofwhateveryoupassin: user=>(defntwice[x]( #'user/twice * 2x)) twice thatdoublesthevalue Next. Reporterratum thiscopyis (P1. Reads should be fast.the stateofadereferencedagentwillblockuntilavalueisavailable. and with the right abstractions around them.Let’sgetthevalueoftheagent: user=>@tribbles 2 Reading a value from a ref.LikeanIofuture.focusonthevalueoftheagent.Users canmutatethedataasynchronouslyusingfunctions.andtheupdates willoccurinanotherthread.anagentisawrappedpieceofdata.theycanbe.Onlyonefunctioncanmutatethestateof anagentatatime.youcanseethedifferenceinthe valuesthatyoureadfromeachagent: user=>(defnslow-twice[x] (do (Thread/sleep5000) (* 2x))) #'user/slow-twice user=>@tribbles 2 user=>(sendtribblesslow-twice) #<Agent@554d7745:16> user=>@tribbles 2 user=>.

Itwould Reporterratum thiscopyis (P1.thefuturewillblockuntilthevaluebecomesavailable. It’sbased onthe JVM. Keep in mind that await and await-for block only until actions from your thread are dispatched.Ifyou dereferenceit. a future is a concurrency construct that allows an asynchronous return before computation is complete. Thelanguagealsomixesinsomenewandpowerfulconcepts. This says nothing about what other threads mayhaveaskedthethreadtodo. you may have had to wait for the result. enoughtimetoseethedifferencesin 261 So.Afuturetakesabodyofoneormoreexpressions. Certainly.whichisanextremelyrichlanguageinitsownright. Y o u could use an agent. W e can use futures to allow severallong-runningfunctionstoruninparallel.Sayyouwantedtocreateathreadtohandle a complex computation around a bit of encapsulated state. you would start threads directly to solve a specific task. First. Or say you wanted to start the computation of a value.That’sexactlyhowversioningdatabasesworkforfast concurrencycontrol. As with Io. you can use Java integration to start a thread in this way. That was W e defined a slower version of @tribbles overtimeintherepl. where timeout is a timeout in milliseconds. but there’softenabetterway.Thefuturereturnsareferenceimmediately: user=>(deffiner-things(future(Thread/sleep5000)"taketime")) #'user/finer-things user=>@finer-things "taketime" Depending on how fast you type. which hasmore thana decade ofdevelopment.Ifyouthinkyouwantthelatestvalue of something.0printing. but you did not want to await the result. you can call (await tribbles) or (awaitwith r e s p e c t to your own thread o f r timeout tribbles) . WhatW e v ’eMissed ClojureisaLisp.Y o umightnotgetthelatestchanges from your own thread.Thefuturestartsinanotherthread. So. you could use a future.returningthe valueofthelastexpression.Let’stakealook. Futures In Java. you have already failed.let’screateafuture. If you want to be sure to get the latest value .D AY 3: A N E YE FOR E VIL twice that took five seconds. Clojure’s tools involve working with a snapshot whose value is instantaneous and potentially out-ofdateimmediately.October2010) .youwillget a valueof tribbles.

or software transactional memory.toUpperCase "Fred") calls the .Clojureallows v a r s .Therearesome piecesthatyoushouldknowabout. expressedusinga dosync function. we placed all mutations to refs within transactions. (.) wouldbind name to "value" onlyforthecurrentthread .youneedtostoredataperthreadinstance. For example.toUpperCase memberfunctiononthestring "Fred". Y o u could implement.0printing. Metadata Sometimes. W e used STM. prototype inheritance.October2010) .. W e did not use the existingJavalibrariesatall. (with-meta v a u l e metadata) a u le gives you a new v associated with the metadata. Refs allowed us to implement mutable state while maintaining consistency across threads.W eencountered severalinterestingconcurrencyconstructsalongtheway.Clojureallowsyoutobuildyourowncodeorganizationwith multimethods.. wewalkedthroughtheconcurrencystructures. J a v aIntegration ClojurehasexcellentJavaintegration.refs. For our part.metadata. or something entirelydifferent. for example.usuallyimplementedasamap.Y o ucanassociatealibraryoffunctionswithatype. WhatW eLearnedinDay3 Today.D AY 3: A N E YE FOR E VIL 262 beimpossibletocoverClojureinonechapterofabook. Clojure allows you to attach and access metadata on both symbols and collections. it’s nice to associate metadata to a type. Multimethods Object-oriented languages allow one style of organization for behavior anddata.andevenattributes. (binding [name"value" ] you to do so quite simply with . and we also built a type on the JVM.W e alsodidnotextensivelycovertheJava compatibility forms. For example.The concept is powerful and extremely flexible. Java-style inheritance.arguments. Reporterratum thiscopyis (P1.andagentsforvariousconcurrencymodels.W e touchedonJavaintegration very loosely.Y o u canalsoimplementpolymorphismbyusingmultimethodstodomethod dispatchbasedontype. ThreadState Clojureoffersatoms. Sometimes.



Next,weusedatoms,lightweightconcurrencyconstructswithlessprotection but a simpler usage model. W e modified an atom outside of a transaction. Finally, we used agents to implement a pool that could be used to do long-running computations. Agents were different from Io actors, becausewecouldmutatethevalueoftheagentwithanarbitraryfunction. Agents also returned a snapshot in time, a value that may be changedatanytime.

Onday2,yourfocuswasonadvancedprogrammingabstractions.Day 3 brought the concurrency constructs of Clojure. In these exercises, you’llputsomeofwhatyou’velearnedtothetest. Find: • Aqueueimplementationthatblockswhenthequeueisemptyand waitsforanewiteminthequeue Do: • Use refs to create a vector of accounts in memory. Create debit andcreditfunctionstochangethebalanceofanaccount. In this section, I’m going to outline a single problem called sleeping barber.ItwascreatedbyEdsgerDijkstrain1965.Ithasthesecharacteristics: • Abarbershoptakescustomers. • Customersarriveatrandomintervals,fromtentothirtymilliseconds. • Thebarbershophasthreechairsinthewaitingroom. • Thebarbershophasonebarberandonebarberchair. • When the barber’s chair is empty, a customer sits in the chair, wakesupthebarber,andgetsahaircut. • Ifthechairsareoccupied,allnewcustomerswillturnaway. • Haircutstaketwentymilliseconds. • Afteracustomerreceivesahaircut,hegetsupandleaves. W r t i eamultithreadedprogramtodeterminehowmanyhaircutsabarbercangiveintenseconds.
Reporterratum thiscopyis (P1.0printing,October2010)



7.5 WrappingUpClojure
Clojure combines the power of a Lisp dialect with the convenience of the JVM. From the JVM, Clojure benefits from the existing community,deploymentplatform,andcodelibraries.AsaLispdialect,Clojure comeswiththecorrespondingstrengthsandlimitations.

TheLispP a r a d o x
Clojureisperhapsthemostpowerfulandflexiblelanguageinthisbook. Multimethods allow multiparadigm code, and macros let you redefine the language on the fly. No other language in this book provides this powerful combination. That flexibility has proven to be an incredible strength. In Hackers and Painters , Graham chronicles a start-up that leveraged productivity with Lisp to achieve productivity that no other vendors could match. Some emerging consultancies are taking the same approach, betting that Clojure will provide a productivity and qualityadvantagethatotherlanguagessimplycannotmatch. Lisp’sflexibilitycanalsobeaweakness.Macroexpansionisapowerful feature in the hands of an expert but will lead to unmitigated disaster without the proper thought and care. The same ability to effortlessly apply many powerful abstractions in a few lines of code makes Lisp especiallydemandingforallbutthemostskilledprogrammers. To successfully evaluate Clojure, you needto look at Lisp but also the other unique aspects of the Java ecosystem and the new unique features.Let’stakeadeeperlookatthefundamentalstrengthsofClojure.

Clojure is one of a handful of languages vying for the position as the next great popular language on the Java virtual machine. There are manyreasonsthatitisapowerfulcandidate. AGoodLisp Tim Bray,programming language expert and superblogger, called Clo7 jure a good Lisp in a post called “Eleven Theses on Clojure.” In fact, hecallsClojure“thebestLispever.”IwouldagreethatClojureisavery goodLisp.
7. http://www.tbray.org/ongoing/When/200x/2009/12/01/Clojure-Theses

Reporterratum thiscopyis (P1.0printing,October2010)



In this chapter, you saw RichHickey’sdiscussiononwhat makesClojuresuchagoodLisp: • Reducedparentheses. Clojureimprovesreadabilitybyopeningup thesyntaxalittle,includingbracketsforvectors,bracesformaps, andacombinationofcharactersforsets. • Theecosystem. Lisp’smanydialectswaterdownthesupportand librarysetthatyoucanhaveforanysingledialect.Ironically,havingonemoredialectcanhelpsolvethatproblem.Bybeingonthe JVM, Clojure can take advantage of Java programmers who are lookingformoreandthefabuloussetoflibraries. • Restraint. ByexercisingrestraintandlimitingClojure’ssyntaxto avoidreadermacros,HickeyeffectivelylimitedClojure’spowerbut alsodecreasedthelikelihoodthatharmfulsplinterdialectsmight emerge. Y o umightappreciateLispasaprogramminglanguageinitsownright. Bythatmeasure,youcanlookatClojurepurelyasanewLisp.Onthat level,itsucceeds. Concurrency Clojure’sapproachtoconcurrencyhasthepotentialtochangetheway we design concurrent systems completely. STM does place some additionalburdenondevelopersbecauseofitsnovelty,butforthefirsttime, it protects developers by detecting whether state mutations happen within appropriately protected functions. If you’re not within a transaction,youcan’tmutatestate. J a v aIntegration ClojurehasgreatintegrationwithJava.Itusessomenativetypessuch asstringsandnumberstransparentlyandofferstypehintsforperformance.ButClojureshinesbyallowingtightJVMintegration,soClojure types can fully participate in Java applications. Y o u l’ soon see much moreofClojureitselfimplementedwithintheJVM. LazyEvaluation Clojure adds powerful lazy evaluation features. Lazy evaluation can simplifyproblems.Y o uhaveseenonlyatasteofhowlazysequencescan shapethewayyouattackaproblem.Lazysequencescanreducecomputation overhead significantly by delaying execution until it is actuallyneededorbypreventingexecutionaltogether.Finally,lazyproblem
Reporterratum thiscopyis (P1.0printing,October2010)



solving offers just one more tool to solve difficult problems. Y o u often use lazy sequences to replace recursion, iteration, or realized collections. DataasCode Programs are lists. As with any Lisp, you can represent data as code. W o r k n ig withRubyhashelpedmeseethevalueofwritingprogramsin programs.Ithinkthisisthemostimportantcapabilityofanyprogramminglanguage.Functionalprogramsallowmetaprogrammingthrough higher-orderfunctions.Lispextendsthisideathroughevaluatingdata ascode.


CoreW e a k n e s s e s
Clojure is a language that’s firmly targeted as a general-purpose programming language. Whether it can actually be broadly successful on the JVM is yet to be determined. Clojure has wonderful abstractions butmany ofthem.Totrulyembrace anduse thosefeatureseffectively andsafely,aprogrammerwillneedtobehighlyeducatedandextremely talented.Herearesomeofmyconcerns. PrefixNotation Representing code in list form is one of the most powerful features in 8 any Lisp, but there is a cost—prefix notation. Typical object-oriented languageshaveawildlydifferentsyntax.Theadjustmenttoprefixnotation is not easy. It requires a better memory and requires a developer tocomprehendcodefromtheinsideout,ratherthanoutsidein.Sometimes,IfindthatreadingClojurepushesmetowardunderstandingtoo muchdetailtoosoon.Atbest,Lispsyntaxpushesmyshort-termmemory. W t i h experience, I’m told this improves. I’ve not yet turned that corner. Readability Anothercosttodataascodeistheoppressivenumberofparentheses. Optimizing for people and computers is not at all the same thing. The locationandnumberofparenthesesisstillaproblem.Lispdevelopers leanheavilyontheireditorstoprovidethefeedbackformatchingparentheses, but tools can never fully mask readability problems. Kudos to Richforimprovingthisproblem,butitwillstillbeaproblem.
Clojure does have left-to-right macros, little.
8. ->> and ->, which mitigate these problems a

Reporterratum thiscopyis (P1.0printing,October2010)



LearningCurve Clojureis rich, and the learning curve is oppressive. Y o u needtohave an extremely talented and experienced team to make Lisp work. Lazy sequences, functional programming, macro expansion, transactional memory,andthesophisticationoftheapproachesareallpowerfulconceptsthattaketimetomaster. LimitedLisp All compromises have some cost. By being on the JVM, Clojure limits tail-recursion optimization. Clojure programmers must use the awkwardrecursyntax.Try implementing (sizex) thatcomputesthesizeofa sequence x withrecursionandwith loop/recur. The elimination of user-defined reader macros is also significant. The benefitisclear.Readermacros,whenabused,canleadtothesplinteringofthelanguage.Thecost,too,isclear.Y o uloseonemoremetaprogrammingtool. Accessibility OneofthemostbeautifulaspectsofRubyoranearlyJavaisitsaccessibilityasaprogramminglanguage.Bothofthoselanguageswererelativelyeasytopickup.Clojureplacestremendousdemandsonadeveloper.Ithassomanyabstractiontoolsandconceptsthattheresultcan beoverwhelming.

Most of Clojure’s strengths and weaknesses are related to the power and flexibility. True, you might work hard to learn Clojure. In fact, if you’reaJavadeveloper,you’realreadyworkinghard.Y o u r ’ejustspending your time on Java application-level abstractions. Y o u are looking forloosercouplingthroughSpringoraspect-orientedprogramming,for example. Y o u r ’e just not getting the full benefits of additional flexibility at the language level. For many, that trade-off has worked. I will humblysuggestthatthenewdemandsofconcurrencyandcomplexity willcontinuetomaketheJavaplatformlessandlessviable. If you need an extreme programming model and are willing to pay the price of learning the language, Clojure is a great fit. I think this is a greatlanguagefordisciplined,educatedteamslookingforleverage.Y o u canbuildbettersoftwarefasterwithClojure.

Reporterratum thiscopyis (P1.0printing,October2010)

Logicislittletweetingbirdchirpinginmeadow. Spock

Chapter 8

Haskell represents purity and freedom for many functional programming purists. It’s rich and powerful, but the power comes at a price. Y o u can’t eat just a couple of bites. Haskell will force you to eat the whole functional programming burrito. Think Spock from Star Trek . The quote above 1 is typical, embracing logic and truth. His character has a single-minded purity that has endeared him to generations. Where Scala, Erlang, and Clojure let you use imperative concepts in small doses, Haskell leaves no such wiggle room. This pure functional language will challenge you when it’s time to do I/O or accumulate state.

8.1 IntroducingHaskell
As always, to understand why a language embraces a certain set of compromises, you should start with the history. In the early and mid1980s, pure functional programming splintered across several languages.Thekeyconceptsdrivingnewresearchwerelazyprocessing,as weencounteredinClojure,andpurefunctionalprogramming.Agroup from the Functional Programming Languages and Computer Architectureconferencein1987formedanddecidedtobuildanopenstandard forapurefunctionallanguage.Outofthatgroup,Haskellwasbornin 1990 and revised again in 1998. The current standard, called Haskell 98, has been revised several times, including a revision of Haskell 98 and the definition of a new version of Haskell called Haskell Prime.
StarTrek: TheOriginalSeries ,Episodes41and42:“I,Mudd”/“TheTrouble withTribbles.”DirectedbyMarcDaniels.1967;Burbank,CA:20thCBSParamountInternational Television,2001.

Loadingpackagebase. The type model is mostly inferred and is widely considered to be one of the most effective type systems of any functional language.done. Reporterratum thiscopyis (P1.Haskelldoesnotdosideeffects..linking.done. Given the same input parameters.1. and then you’re ready to type commands.12. such as expressions....1:http://www.Asalways. Y o u l’ see that the type system allowsforpolymorphismandverycleandesigns.. Y o u l’ an example of this in day 3.It’swidely available across many platforms.Let’sgetstarted.andthelike. Y o u l’also find Clojure-style lazy evaluation and list comprehensions from both Clojure andErlang.withspecial emphasisonlazyprocessing.Instead.haskell..linking. but you can find other implementaghci: tionsaswell. defining functions.D AY 1: L OGICAL 269 So.. Asapurefunctionallanguage.0. like Scala. Loadingpackageffi-1. see 8. higher-order functions. as well as an example of preserving state usingaconceptcalled monads.linking..done. a function can return a side effect.12.W e l’lookatthe parameterizedtypesystemandmonads.October2010) .version6.ortheGlasgowHaskellCompiler.0printing.done.version6. you’ll find that Haskell’s core concepts are easy to grasp.org/ghc/ :?forhelp Loadingpackageghc-prim.Type GHCi. I’m going touseGHC. Y o u l’ work strictly with defining functions.which willgiveyousomenewconcepts.W e l’alsogetintoHaskell’stypingmodel.I’mgoingtostartintheconsole.. Haskell has strong.linking. static typing..whicharesometimesdifficult conceptstograsp. you’ll get the same output parameters..2 Day1:Logical Like Spock.combiningideasfromthebestfunctionallanguages... Loadingpackageinteger-gmp.Day3willstretchyou. which is later executed. Y o u l’ see Haskell load a few packages. Thefirstcoupleofdayswillgetyouthroughtypicalfunctionalprogramming concepts... Haskellalsosupportsotherconceptsyou’veseeninthisbook. every time.. Haskell was built from the ground up to be a pure functional language.Haskell allows Erlang-style pattern matching and guards.

Y o ucanrepresent Reporterratum thiscopyis (P1.0 * 5 Orderofoperationsworksjustaboutlikeyou’dexpect: Prelude>4 21 Prelude>4 24 * 5+1 * (5+1) Noticeyoucangroupoperationswithparentheses.we’llstartwithnumbersandsomesimpleexpressions.W e l’ movequicklyintomoreadvancedtypessuchasfunctions.Typeafewexpressions: Prelude>4 4 Prelude>4+1 5 Prelude>4+1.Y o u v ’eseenacouple oftypesofnumbers. Numbers Bynow.0 14. In this section.we’llfocusonusingprimitivetypes.D AY 1: L OGICAL 270 ExpressionsandPrimitiveTypes W e r ’e going to talk about Haskell’s type system a little later. CharacterData Stringsarerepresentedwithdoublequotes.October2010) .'b'] "ab" ++ insteadof +.0 5.Aswithmanyoftheother languages.youknowthedrill.Let’slookatsomecharacterdata.0printing.likethis: Prelude>"hello" "hello" Prelude>"hello"+"world" <interactive>:1:0: Noinstancefor(Num[Char]) arisingfromauseof`+'at<interactive>:1:0-17 Possiblefix:addaninstancedeclarationfor(Num[Char]) Intheexpression:"hello"+"world" Inthedefinitionof`it':it="hello"+"world" Prelude>"hello"++"world" "helloworld" Noticethatyou’llconcatenatewith singlecharacterslikethis: Prelude>'a' 'a' Prelude>['a'.0 Prelude>4+2.

October2010) .Let’strytoforce <interactive>:1:0: Noinstancefor(Num[Char]) arisingfromauseof`+'at<interactive>:1:0-8 .Let’sbrieflylookatsome booleanvalues. meaning it returns avaluejustlikeanyotherfunction. indentation is significant. Haskellisstronglytyped.D AY 1: L OGICAL 271 Noticethatastringisjustalistofcharacters.0printing.. Booleans Abooleanisanotherprimitivetypethatworksmuchastheydoinmost oftheotherinfixnotationlanguagesinthisbook. Haskell is guessing that there’s a follow-up line that is not indented correctly.Let’stryafewtrue/falsevalues: Prelude>if1then"true"else"false" <interactive>:1:3: Noinstancefor(NumBool) arisingfromtheliteral`1'at<interactive>:1:3 . ThiserrormessagegivesusthefirstglimpseintoHaskell’stypesystem.whichcontrolindentation patterns.andyouwillbeOK. + that takes a Num argument folIt says “There is no function called Reporterratum thiscopyis (P1. not a control structure.returningbooleans: Prelude>(4+5)==9 True Prelude>(5+5)/=10 False Try an if/then statement: Prelude>if(5==5)then"true" <interactive>:1:23:parseerror(possiblyincorrectindentation) That’s the first major departure from other languages in the book. if is a function. W e l’ see some indented structureslater..followpredictableindentationstrategiesthatmimicwhatyou if/then/else statement: seehere. anothertypecollision: Prelude>"one"+1 if takesstrictlybooleantypes.W ewon’ttalkaboutlayouts.Theseareequaland not-equalexpressions...Let’sdoafull Prelude>if(5==5)then"true"else"false" "true" In Haskell. In Haskell.

The language is inferring types based on clues.W e r ’e goingtogoquicklythroughconceptsyou’veseeninother languages.That returns. Reporterratum thiscopyis (P1. canuse :t.onpage299.oryoucanturnonthe likethis: Prelude>:set+t Prelude>5 5 it::Integer Prelude>5. Since Haskell has strong. Rather than a pure descriptionofabunchofsimilartypes.October2010) .4.Letmewarnyouthatusing has to do with the interplay between numbers and the console. unless you type. Try to usethe :t function: Prelude>:t5 5::(Numt)=>t it :: Integer . you can see what Haskell’s type inference is doing.0 it::Double Prelude>"hello" "hello" it::[Char] Prelude>(5==(2+3)) True it::Bool Now.aftereveryexpression. you’ll specify each functionintwoparts:anoptionaltypespecificationandtheimplementation. DefiningBasicFunctions AHaskellfunctiontraditionallyhastwoparts:thetypedeclarationand thefunctiondeclaration. sole will try to treat numbers as generically as possible. static typing. The conThat is not the same as the type we got before. Classes. Y o u :t optionthatdoessomethingsimilar.”Noticethatwehaven’ttoldHaskell what types things are. which is a have done a :set t . At any point. you get a class.sohangontight.alistofcharacters.youcanseethetypethateachexpression :t withnumbersisconfusing.W e l’ learnmoreinSection8.0 5. Functions The centerpiece of the whole Haskell programming paradigm is the function.D AY 1: L OGICAL 272 lowedby [Char].0printing.

Prelude>letx=10 Prelude>x 10 Whenyou’recodingaHaskellmodule.modulesloaded:Main.hs moduleMainwhere doublex=x+x Noticethatweaddeda module called Main.wehaven’tenforcedatype. The double functionfornow. we’ll switch to using files with programs.hs moduleMainwhere double::Integer->Integer doublex=x+x Reporterratum thiscopyis (P1. Using wouldlooklikethis: Download haskell/double.Beforedefining let binds a variable to a a function.you’lldeclarefunctionslikethis: doublex=x * 2 let toassignthefunctioninlocalscope. *Main>double5 10 (double.hs.October2010) .anduseitlikethis: Prelude>:loaddouble.interpreted) Sofar. the full double definition work with multiline definitions.Load Main into top-levelmodule.hs [1of1]CompilingMain Ok.0printing.Focusonthe theconsole. in Haskell.Here’sanexampleofasimpledoublefunction: Prelude>letdoublex=x Prelude>double2 4 * 2 At this point. There’s definitely an underlying type definition for each function.Here’sanexampleofadefinitionwithatypedefinition: Download haskell/double_with_type.Haskellisbeingforgivingbyinferring a type for us. W e l’ usethe let functiontobindvaluestoimplementations. It is the related code into a similar scope.modulescollect Main module is special.D AY 1: L OGICAL 273 Initially. functioninalocalscope. W e can then GHC. try let.InHaskell. we’re going to be defining functions within the console. As with Lisp.though.we’lluse sowecanuseit. Intheconsole.

+ function. a fc t o a r il Reporterratum thiscopyis (P1. Actually.1) * x That’s a start. we can use this function with any type that supports the Let’sstarttocrankupthepower.interpreted) Y o ucanseetheassociatedtypeofthenewfunction: *Main>:tdouble double::Integer->Integer double takes an Integer arguThis definition means that the function ment(thefirst Integer)andreturnsan Integer. The factorial of otherwise.thissyntaxlooksandactsalotlikeErlang’spatternmatching: Download haskell/factorial. This type definition is limited.October2010) . If you went back to the earlier.modulesloaded:Main.afactorial. that’s different! In this case.Let’slookatimplementingsomething slightlymoreinteresting. The first declares the type of the argumentandreturnvalue.Here’sarecursiveone-linerthatimplementsafactorialwithintheconsole: Prelude>letfactx=ifx==0then1elsefact(x-1) Prelude>fact3 6 * x x is 1 if x is 0. Recursion Let’sstartwithalittlerecursion. W e can do a little better by introducing pattern matching.you’dseesomethingelseentirely: *Main>:tdouble double::(Numa)=>a->a a is a type variable. and it’s a fc t (x .Thenexttwoaredifferentfunctionaldefinitions that depend on the pattern match of the inbound arguments. *Main>double5 10 (double_with_type.hs. a means “The function double takes a single argument of some type a.0printing.D AY 1: L OGICAL 274 Andwecanloaditanduseitasbefore: [1of1]CompilingMain Ok.”W andreturnsavalueofthatsametype t i hthisimproveddefinition. typeless versionof double.hs moduleMainwhere factorial::Integer->Integer factorial0=1 factorialx=x * factorial(x-1) The definition has three lines. The definition Now.

A tuple isacollectionofafixednumberofitems.0) fibTuple(x.First.hs 275 moduleMainwhere factorial::Integer->Integer factorialx |x>1=x * factorial(x-1) |otherwise=1 In this case.Guardsoftenreplacepatternmatching. ProgrammingwithT u p e ls W e can use tuples to provide a more efficient implementation. If youwantedtoreversetheorder. When a guard is satisfied. That definition looks exactly like the mathematical definition.InHaskell.index-1) .you’dhavetouseaguard.hs moduleMainwhere fib::Integer->Integer fib0=1 fib1=1 fibx=fib(x-1)+fib(x-2) That’ssimpleenough. Asingleparameterthatisathree-tupleisnotthesameastakingthree Reporterratum thiscopyis (P1.index)=fibTuple(y.y.Let’sseeseveralversions ofaFibonaccisequencewithHaskell. Haskell will take the first match.Integer.we’llseeasimplecase: Download haskell/fib. In this case.But fibTuple takes a three-tuple and returns a three-tuple.0printing.Here’sthebasesolution: fibTuple::(Integer. the order of the patterns is important.andwe’re usingittoinitiatethebaseconditionforourrecursion. Haskell calls the appropriatefunction.y.Integer)->(Integer. the guards have boolean values on the left and the function to apply on the right.Integer) fibTuple(x. Haskell depends on tail-recursion optimizationtoefficientlydealwithrecursion.October2010) .D AY 1: L OGICAL fc t o a r il fc t o a r i l (x . fib0 or fib1 is 1.x+y. guardsareconditionsthatrestrictthevalueofthearguments.1) of 0 is 1. Be careful here. and a of n is factorial x = x * a .0)=(x.Integer.and fibx is fib(x-1)+fib(x-2) thatsolutionisinefficient. T u p e l sandLists As you’ve seen in other languages.y.TuplesinHaskellarecommaseparated items in parentheses.likethis: Download haskell/fact_with_guard.Let’sbuildamoreefficientsolution. This implementation creates a tuple with consecutive Fibonacci numbers and uses a counter to assist in recursion.

likethis: Prelude>:loadfib_tuple.y.Integer)->(Integer.index-1) fibResult::(Integer.y.1.0) (fib_tuple.x)) Reporterratum thiscopyis (P1.1.x+y.0) Y o ucanruntheprogram.4) • fibTuple(1.4) (3.5.Integer.D AY 1: L OGICAL 276 parameters.Integer.0) fibTuple(x.1) • fibTuple(3.hs.z)=x can grab the answer like W e justusepatternmatchingtograbthefirstposition.2.y.0printing.2) • fibTuple(2.0)=(x. W e this: fibResult::(Integer.y.1.Integer.y.Integer.index)=fibTuple(y.3) • fibTuple(1. we’ll start recursion with two numbers.interpreted) The answer will be in the first position.z)=x fib::Integer->Integer fibx=fibResult(fibTuple(0. W e will also provide a counter.x)) cansimplify That function uses the two helper functions to build a quite fast Fibonaccigenerator.1.Integer) fibTuple(x. As the counter counts down.Successivecallsto fibTuple(0.1.Integer)->Integer fibResult(x.5.hs moduleMainwhere fibTuple::(Integer.hs [1of1]CompilingMain Ok. *Main>fibTuple(0. the first two numbers get successively larger numbers in the sequence.W e theusagemodellikethis: fib::Integer->Integer fibx=fibResult(fibTuple(0.Hereisthewholeprogramtogether: Download haskell/fib_tuple. 0 and 1.modulesloaded:Main.3.October2010) .4) wouldlooklikethis: • fibTuple(0. To use the function.Integer)->Integer fibResult(x.1.

it is simple.34) *Main>fibNthPair(9) (34. we can always compute the next one.butwithoutacounter: fibNextPair::(Integer. The base case is the value W e just compute the next item of the sequence based on the last one. W e l’ computeasinglepair. alentto secondlst=head(taillst) .October2010) . From there.Integer)->(Integer.5] 4 second=head.1) fibNthPairn=fibNextPair(fibNthPair(n-1)) (1.89) Reporterratum thiscopyis (P1.2] 2 *Main>second[3.y)=(y.55) *Main>fibNthPair(10) (55.asbefore. The next job is to recursively compute the next item in the sequence: fibNthPair::Integer->(Integer. UsingT u p e l sandComposition Sometimes.0printing.4.Integer) fibNthPair1=(1.x+y) Given two numbers in the sequence. you need to combine functions by chaining them together by passing the results of one function to another.Let’susethisfeaturewithyetanotherFibonaccisequence. 1) for an n of 1.D AY 1: L OGICAL 277 Andherearetheresults(whichappearinstantaneously): *Main>fib100 354224848179261915075 *Main>fib1000 43466557686937456435688527675040625802564660517371780 40248172908953655541794905189040387984007925516929592 25930803226347752096896232398733224711616429964409065 33187938298969649928516003704476137795166849228875 Let’stryanotherapproachwithfunctioncomposition.tail *Main>second[1.Integer) fibNextPair(x.tail isequivW e r ’ejustdefiningafunctionintheconsole. W e cangetanypairinthesequence: *Main>fibNthPair(8) (21. Here’s an example head ofthe tail thatcomputestheseconditemofalistbymatchingthe ofalist: *Main>letsecond=head.W e r ’e feedingtheresultofonefunction intoanother.

3.wetakethefirstelementofthenthtuple. but I will go over a basic recursion example and then introduceafewfunctionsyouhaven’tseenyet.y)=(y.Integer) fibNextPair(x.fibNthPair Saidanotherway.W t i halittleworkdonefortuples.1) fibNthPairn=fibNextPair(fibNthPair(n-1)) fib::Integer->Integer fib=fst. Erlang.Breakingalistintothe let statementorapattern headandtailcanworkinanybinding.allthatremainsistomatchthefirstitemofeachpairandcombine them into a sequence.likea match: let(h:t)=[1. 3.3.hs moduleMainwhere fibNextPair::(Integer. 2. W e l’ use a convenient function composition of fst tograbthefirstelementand fibNthPair tobuildapair: Download haskell/fib_pair.4] *Main>h 1 *Main>t [2.x+y) fibNthPair::Integer->(Integer.Andwe’re done. and Scala. Here are size and prod functionsforalist: Download haskell/lists.D AY 1: L OGICAL 278 Now. W t i h this tool.October2010) .Integer) fibNthPair1=(1. we can do a few simple recursive definitions.Integer)->(Integer.2. Think of this construct as the various head|tail constructs you’ve seen in Prolog. 4 ] to (h:t).let’ssolveafewproblemswith lists.4] W e r ’e binding the list [1. T r a v e r s n i gLists Y o u v ’e seen lists in many different languages.0printing.hs moduleMainwhere size[]=0 size(h:t)=1+sizet prod[]=1 prod(h:t)=h * prodt Reporterratum thiscopyis (P1. I’m not going to fully rehash them.

*Main>size"Fascinating."reliant"] [("kirk"."reliant")] It’saneffectivewaytocombinetwolists.W e l’lookatadvancedlistsincludingranges andlistcomprehensions.ranges. whichcombinesaheadandtailtomakealist. Sofar. In thissection. let: Here’s : ontheleftsideofa Prelude>leth:t=[1." 12 zip isapowerfulwaytocombinelists.interpreted) Ok. GeneratingLists W e v ’e already looked at a few ways to process lists with recursion.insteadofdeconstruction.D AY 1: L OGICAL 279 I’m going to use Haskell’s type inference to handle the types of these functions.hs. Reporterratum thiscopyis (P1.2.("spock". Prelude>:loadlists.hs [1of1]CompilingMain (lists.modulesloaded:Main.andlistcomprehensions.Now.like this: Prelude>zip["kirk".webuiltatupleofthetwoitems.Thesizeofalistis1+thesizeofa tail.0printing.we’lllookatafewoptionsforgeneratingnewlists.Y o u v ’eseentheoperator in reverse used in pattern matching as we call a recursive function. Recursion The most basic building block for list construction is the : operator.buttheintentionisclear.we’llstartworkingwithsome moreadvancedconstructs.we’lllookatrecursion.thefeaturesyou’veseeninHaskellhavebeenremarkablysimilar tothosecoveredinotherlanguages.Inparticular.Here’sthefunctioninaction: *Main>zip"kirk""spock" [('kirk'."enterprise").3] W e canalsouse : todoconstruction.Y o ucanalsozipliststogether.October2010) .'spock')] So.3] Prelude>h 1 Prelude>t [2."spock"]["enterprise".

Ifthereisalist.2] Prelude>[1. Let’s look at we discard it by applying someotherwaystobuildlists.4]] [[1]. Haskell provides a simple form.4]] Prelude>[1]:[] [[1]] Here’slistconstructioninaction. If the head is odd.listsarehomogeneous.Thedefault incrementis1.Y o ucan’taddalisttoalistofintegers. RangesandComposition As with Ruby and Scala.WhatifHaskellcan’treachtheendpointwiththedefault increment? Reporterratum thiscopyis (P1.3] [1. No problem. Haskell includes first-class ranges and some syntactic sugar to support them.3] Remember.addalisttoalistoflistsorevenanemptylist: Prelude>[1]:[[2].October2010) . One way to write that functioniswithlistconstruction: Download haskell/all_even.3] <interactive>:1:8: Noinstancefor(Num[t]) arisingfromtheliteral`3'at<interactive>:1:8 Y o ucould.2.[3.4] Y o uspecifytheendpoints.D AY 1: L OGICAL 280 Here’showthatmightlook: Prelude>1:[2. consistingoftheendpointsofarange: Prelude>[1. even.2] [1.3.0printing.. we add the head to allEven to the tail.[3.. allEven foranemptylistisanemptylist.4] [1.2.[2].forexample: Prelude>[1]:[2.Let’ssaywewantedtocreateafunction that returns the even numbers from a list.however.hs moduleMainwhere allEven::[Integer]->[Integer] allEven[]=[] allEven(h:t)=ifevenhthenh:allEventelseallEvent Ourfunctiontakesalistofintegersandreturnsalistofevenintegers.andHaskellcomputestherange.iftheheadis allEven applied to the tail.

thelistcomprehensionmeans“Collect fromthelist [] Y o ucanalsoworkinfractionalnumbers: Prelude>[10.Y o ucanspecifyanincrementbyspecifyingthe nextiteminthelist: Prelude>[10. On the right side.] [0.(3.3.4] [10.D AY 1: L OGICAL Prelude>[ ListComprehensions W efirstlookedatlistcomprehensionsintheErlangchapter.1).3 ].2.To doubleallitems inalist. let’s look at anotherwaytoautomaticallygeneratelists.toflipthepolygonhorizontally.likethis: Reporterratum thiscopyis (P1.8.wecanalsousepatternmatchingwithinourlistcomprehensions. likethis: Prelude>[(y.thelistcomprehension.4.2). just asyoudidwithErlang.October2010) .” x*2 where x istaken AswithErlang.5.9. For now.2.(2. a list comprehension works the same way.4..5.3)] Or. Say we had a list of points representing a polygon and wantedtoflipthepolygondiagonally.7.2).2).wedothis: Prelude>[x [2.AswithClojure.] W e l’ talk more about lazy sequence in day 2..8.6.youcantakesomeoftheelementsofa sequence: Prelude>take5[<-[(1.5.1)] x from4.3).(] []] [(3.wecouldsubtract Prelude>[(4-x.0.0] Rangesaresyntacticsugarforcreatingsequences..4. On the left side.InHaskell.y)|(x.Thesequencesneed notbebound.5...3).9.(1.3).2).1)]] [(2. you’ll see generators and filters.0printing.0.y)<-[(1.W e couldjusttranspose x and y.(2.5.Let’slookatafewexamples.(1.x)|(x.2. you’ll see an expression.6] * 2|x<-[1.(] [] 281 Y o u l’getanemptylist.3]] InEnglish.4] [10.5] Prelude>take5[0.(2.

whichyoucanfindontheW e b .Chalmers."Spock").("Kirk"."Kirk")."Spock".anduptoindustrialuses.b)|a<-crew. Bruce Tate: WhydidyourteamcreateHaskell? Philip Wadler: Inthelate1980stherewerealargenumberofdifferent groups creating designs and implementations of functional languages.The entire history is covered in detail in a paper we wrote for the History of ProgrammingLanguagesconference. ("McCoy". AnInterviewwithPhilipW a d e lr Now that you’ve seen some of the core features of Haskell.("Kirk"."Spock").("Spock".D AY 1: L OGICAL 282 W e can also compute combinations.b<-crew.The original goals were not modest: we wanted the language to be a foundationforr e s e a r c h .b)|a<-crew."McCoy").Spock.a<b] [("Kirk".suitableforteaching.("Kirk". ("Spock".W e candoalittlebetter by including only the options that appear in sorted order. let’s see whatsomeonefromthecommitteethatdesignedHaskellhastosay.("Spock"."Spock")] W t i hashort."Spock")."Kirk")."McCoy"] Prelude>[(a.butorderdoesn’tmatter."McCoy").simplelistcomprehension.wehavetheanswer.BellLabs.W ecan addconditionstofilterthelistcomprehensionlikethis: Prelude>[(a.("McCoy"."McCoy").Oxford.("McCoy"."Kirk"). discarding therest: Prelude>[(a.CMU.Previously."McCoy").or McCoy: Prelude>letcrew=["Kirk".Listcomprehensionsareagreattoolforrapidlybuildingandtransforminglists.XeroxParc. PhilipW a d e lr isanactivecontributorofnotonlyHaskellbutalsoJava andXQuery.b<-crew] [("Kirk". Glasgow. Let’s say we wanted to find all of thepossiblelandingpartiesoftwotakenfromacrewofKirk.heworkedorstudiedatAvayaLabs.b<-crew."Kirk").October2010) ."Spock").("McCoy".("Spock".("McCoy"."Kirk"). http:// www.a/=b] [("Kirk".A theoreticalcomputerscienceprofessorattheUniversityofEdinburgh."McCoy")] Thatcompositionalmostworkedbutdidnotremoveduplicates. ("Spock"."Spock")."McCoy").b)|a<-crew.org/ haskellwiki/ History_of_Haskell 2 Reporterratum thiscopyis (P1.andStanford."Spock")] Thatisalittlebetter.("Kirk".0printing. 2. andwer e a z i le dwewouldbestrongerworkingtogetherthanapart.haskell.("McCoy".

CreditSuisse.andsoon. tocomparevalues.Laziness.toconvertvaluestoandfromstrings. Any good programming language r e a y l becomes a means of extending itself to embed other programming languages specialized to the task at hand.FacebookusesHaskellforan in-house tool to update code in PHP.youcangetroutines datatype.monadandarrownotation.in thedistributedworld. you probably want it to be the value itself (eager evaluation). the expressive type system.lambdaexpressions.October2010) ..programmingenginestobeusedingarbagetrucks! Reporterratum thiscopyis (P1.. rather than a program (and the values of all the free variables of the program) that can be evaluated to yield the value.0printing. likePython. Typeclassesprovideasimpleformofgenericprogramming. One of my favorites is the use of Haskell for garbage collection—not the kind we do in software but r e a l garbagecollection. It’snicetoseethatthey’vefinallymadetheirwayintootherlanguages.andStandardChartered. and it lists forty industrial applications of Haskell. we need to focus on programs that run on multiple machines.andjustbyaddingonekeyword. DeutscheBank.D AY 1: L OGICAL 283 Bruce Tate: Whatarethethingsyoulikeaboutitthemost? Philip Wadler: I r e a y l enjoy programming with list comprehensions.type classes. Bruce Tate: What’s the most interesting problem you’ve seen solved withHaskell? Philip Wadler: I’m always blown away by the uses folks find for Haskell.So. Ithink itwouldbe bettertobe eager bydefaultbutmakeiteasytobelazywhenyouwant.Therearenowmanyusersinfinance:ABNAmro. When you senda value. sending values from one to the other. I just had a look at the Haskell Community page.Ifind thatveryconvenientandmissitwhenI’musingotherlanguages. and template Haskell all support extendingthelanguageinvariousways. Bruce Tate: What are the things you’d change if you had it to do all overagain? Philip Wadler: With distribution becoming so important.Y o u definea derived. Haskell is particularly good as a tool for embedding other languages. I r e m e m b e r years ago being amazed at uses of Haskell for natural-language processing and years after that when it was used for protein folding with an application to fighting AIDS.

Map Coloring .Note (black.W e sawpattern matching and guards as we found in Erlang and Scala. W e first covered basic expressions and simple data types. ranges.W e spentmostofday1coveringfeaturesyouhaveseenin otherlanguagesinthisbook.weusedrecursiontodefinesome simple math functions and to deal with lists.D AY 1: L OGICAL 284 WhatW eLearnedinDay1 Haskell is a functional programming language. Its first distinguishing characteristic is that it is a pure functional language.blue. on Reporterratum thiscopyis (P1.2.I’mgoingtopushyoualittleharder. W e worked with basic Haskellexpressionsandrolledthoseupintofunctions. Since there arenomutablevariableassignments.wetookalookatbuildingliststhattookusintolistcomprehensions. In thissection.white. Finally. thatyoushouldincludeonlyoneof •W r t i e a list comprehension to build a childhood multiplication table.andred. A function with thesameargumentswillalwaysproducethesameresult. Let’s put some of those ideas intopractice. W e used lists andtuplesasthebasiccollectionsasyoufoundinErlang.0printing. page101)usingHaskell.black) . writing functional programs should be getting easier if you’ve been working through all of the other functional languages. • Solve the map-coloring problem (Section 4.yellow.Thetablewouldbealistofthree-tupleswherethefirsttwo areintegersfrom1–12andthethirdistheproductofthefirsttwo.October2010) . and even lazy sequences. Day1Self-Study By this time. •W r t i eafunctionthatbuildstwo-tupleswithallpossiblecombinationsoftwoofthecolorsblack.Thereareno sideeffects.blue) and (blue. Find: • TheHaskellwiki • AHaskellonlinegroupsupportingyourcompilerofchoice Do: • Howmanydifferentwayscanyoufindtowrite allEven? •W r t i e a function that takes a list and returns the same list in reverse.

" Taken alone.Combinedwithotherfunctions. The form is Try it.3 Day2:Spock’sGreatStrength W t i h some characters. we’ll dig into the practical concepts that lead tobetterpredictability. paramn -> function_body) . In this section. anonymous functions in Haskell have a ridicu(\param1 . W t i h Spock.Haskell’sgreat strengthisalsothatpredictabilityandsimplicityoflogic.October2010) .0printing. we’lltalkaboutHaskell’sstrategyforcombiningthem.solet’sgetstarted." "Logical.Then. W e will work quickly through anonymous functions and then apply them with the many prebuilt functions that work on lists." "Logical. W e l’ start things with anonymousfunctions. and there’s so much ground to cover.2.becauseyou’veseentheconcepts before.Haskell hasamap: map(\x->x * x)[1.ManyuniversitiesteachHaskellinthecontextofreasoningaboutprograms.they becomeextremelypowerful. Next.Haskell makescreatingproofsforcorrectnessfareasierthanimperativecounterparts. we append a string.W e willstartwithhigher-orderfunctions. you might not notice their best qualities for quite some time.alwayslogical. mapandwhere First.likethis: Prelude>(\x->x)"Logical.webuiltananonymousfunctionthatjustreturnsthefirstparameter.. W e l’ finally look at lazy computation.D AY 2: S POCK ’ S G REAT S TRENGTH 285 8.theydon’taddmuch. anonymousfunctionsareanimportantfeatureforlistlibraries. AnonymousFunctions As you might expect. As you’ve seen in other languages. it’s easy to grasp his great strengths.captain.")"Logical.andcompletelypredictable. Haskell depends on the concept extensively." Prelude>(\x->x++"captain.3] Reporterratum thiscopyis (P1.It’sgoingtobeafullday. He’sbrilliant. I will move much faster thanIhavewiththeotherlanguages.Thatwilltakeus into partially applied functions and currying. Higher-OrderFunctions Every language in this book addresses the idea of higher-order programming. lously simple syntax.

October2010) .0printing.5] [1. W e l’ see some examples of where throughout the rest of thechapter. The + function takes two parameters..todeclarealocalversionof square.Y where.hs [1of1]CompilingMain Ok. m a p applies the anonymous function to each item in the list and collectstheresults.withasingleparameter filter.interpreted) Y o ucanalsouse m a p withpartofafunction. just as you did in Clojure and Scala.youcanalsobind o udon’thavetobindfunctionswith any variable.hs.4.2.weuseanewfeature. like this: Download haskell/map.There’snosurprisehere.5] filter. *Main>squareAll[1.9] (map.2.called where.3] [1.3.likethis: Prelude>map(+1)[1.2. functionlike (x+1) .3.likethis: Prelude>odd5 True Prelude>filterodd[1. o fd l l and o fd lr : Thefunctionsyouwillusearevariationsof Prelude>foldl(\xcarryOver->carryOver+x)0[1. The result is that we get a x. W e can package it all up as a function and break out the anonymous function as a locally scoped function.butthatformmightbeabit much to digest all at once.Then.4. lo fd lr The next common function is list. which applies a test to items in a Y o u can also fold left and right.10] 55 Reporterratum thiscopyis (P1.Here’stheresult: *Main>:loadmap.3.modulesloaded:Main.weuse m a p toapplyafunctioncalled square toalltheitemsin list.Next.D AY 2: S POCK ’ S G REAT S TRENGTH 286 W e r ’e applyingthemapfunctiontoananonymousfunctionandalist.3] [2. and we’ve supplied only one.calleda section.4] (+ 1) is actually a partially applied function.hs moduleMainwhere squareAlllist=mapsquarelist wheresquarex=x * x W e v ’e declaredafunctioncalled squareAll thattakesaparametercalled list.o fd l.

TheseconceptsareimportantandcentralenoughtoHaskell thatweshouldspendalittlemoretimehere.0printing. Y o u might ask yourself. how could you write a function like numberstogether?” In fact.with o fd lr 1 . + that adds two “If that’s true. Asyoumightimagine.it’stimetosettherecordstraight.let’screateafunctioncalled prod: Prelude>letprodxy=x Prelude>prod34 12 * y W e createdafunction. To simplify thetypesyntax.October2010) . and many of them use higher-order functions.Now.Let’sgetthetype ofthefunction: Prelude>:tprod prod::(Numa)=>a->a->a a isatype Theportion Numa=> means“Inthefollowingtypedefinition. P a r a t iy l AppliedFunctionsandCurrying W e v ’e talked briefly about function composition and partially applied functions.Anotherformoffoldis convenientwhenyouarefoldingwithanoperator: Prelude>foldl1(+)[1. of Num.D AY 2: S POCK ’ S G REAT S TRENGTH 287 W e tookaninitialcarry-overvalueof0andthenappliedthefunctionto carryOver every item in the list. using the result of the function as the argumentandeachitemofthelistastheother.”Y o u v ’eseentherestbefore.Theresultgivesyouthesamethingasevaluatingthis: Prelude>1+2+3 6 Y o ucanalsofoldrighttoleft. it is true. Every function in Haskell has one parameter.3] 6 This is using the + operator as a pure function taking two parameters andreturninganinteger. I’ll let you do your own discovery.andIliedtoyouaboutthemeaning tosimplifythings. Rather than spend a whole chapter on dealing with them. I want to move on to the ways Haskell combinesfunctionstoworktogether.andyoucanseethatitworks.Haskelluses Reporterratum thiscopyis (P1..Haskelloffersmanyotherfunctionsinthelibrary of list functions. Every function does have one parameter. Now.

each with one argument. prod 2 4 .andjustabouteverymultiple-argument function in Haskell gets curried.givingyou8. we can partially apply createsomeotherfunctions: Prelude>letdouble=prod2 Prelude>lettriple=prod3 some of the prod to Look at the left side of these functions first.startingat Download haskell/my_range. andyouhave prody=2*y . So. Thatprocessiscalled currying.Thatreturnsthefunction • Next.Justtaketheoriginalfunctionof . Haskell makes extensive use of lazy evaluation.substitute2for x. it is really (\y->2*y) . Often.apply prod2 .October2010) .or 2*4 . W e use list composition to build a list with start as the head Reporterratum thiscopyis (P1.D AY 2: S POCK ’ S G REAT S TRENGTH 288 a concept to split one function on multiple arguments into multiple functions.instepsof y: examplethatbuildsaninfiniterange. you can build functions that return infinite lists. When Haskell computes computing (prod2)4 . you’ll use list construction to form an infinite list. That leads to greater flexibility and simpler syntax. you don’t really have to think about it. LazyEvaluation Like Clojure’s sequence library.Thefunctionsworkjustasyou’dexpect: Prelude>double3 6 Prelude>triple4 12 So. the mystery is solved. but we applied only the first one. W e defined prod with two prod 2 is parameters. Haskell does this job with partial application.becausethevalueofcurriedanduncurriedfunctionsisequivalent.hs moduleMainwhere myRangestartstep=start:(myRange(start+step)step) Thesyntaxisstrange. Don’t let the term confuse you. taking a starting point and a step for our range.apply (\y->2*y)4 . Partial application binds arguments.likethis: • First. Take this x. but not all.buttheoveralleffectisbeautiful.W e r ’e building y R a n g e a function called m . computing prodxy=x*y easy.0printing. W t i h it. For example. Most of the time.

18. so we’ll typically use the function m y _ r a n g e .28657. as the tail.5] *Main>take5(drop20(lazyFib01)) [10946.W eeffectivelyhaveasequence.17.To beaproperFibonaccisequence.1.11.so have one more helper function that allows the user to grab just one drop and take.2.13.hs moduleMainwhere lazyFibxy=x:(lazyFiby(x+y)) fib=lazyFib11 fibNthx=head(drop(x-1)(take(x)fib)) Thefirstfunctionbuildsasequencewhereeverynumberisthesumof theprevioustwo.46368.10.wemuststartthesequence fib seeds lazyFib withthefirsttwonumbers.butwecanimproveon theAPI.October2010) . h s withothersthatwilllimittherecursion.] Somerecursivefunctionsworkmoreefficientlyusinglistconstruction.75025] *Main>fibNth3 2 *Main>fibNth6 8 Reporterratum thiscopyis (P1.] *Main>take5(fib) [1. These are the successive This recursion will go on infinitely.5.3.usinglazyevaluationwith composition: Download haskell/lazy_fib. Here are the functions in number of the sequence with action: *Main>take5(lazyFib01) [1.we with1and1.16.15.D AY 2: S POCK ’ S G REAT S TRENGTH 289 and (myRange (start + step) step) y R a n g e11 evaluationsfor m : • 1:myRange(21) • 1:2:myRange(31) • 1:2:3:myRange(41) .Finally..Makesureyouload first: *Main>take10(myRange101) [10.0printing. Here’sanexampleoftheFibonaccisequence.19] *Main>take5(myRange05) [0.andsoon..17711.

6. flip it vertically and then flip it horizontally. g x is shorthand for just pass one function to the next.30.beginningwith The nice thing about functional languages is that you can compose them in unexpected ways..8. ].10.4.wefirsthave Whatever we pass into the function will be multiplied by five. When you’re building functions in this way. you might want to .October2010) . Reporterratum thiscopyis (P1. W e pass (* 2) .Or.solet’stakeitapart. W e get a Fibonacci sequence.( * 5))fib) Thatcodepacksapunch. W e pass that infinite result to generate the first five elements of a Fibonacci sequence.andthenwe’reusingtheinfiniterange. W that result into another partially applied function..8. For example. we can use function compositioninconjunctionwithpartiallyappliedfunctionsandlazysequences effortlessly: *Main>take5(map(( [10. (flipHorizontally . range [1. andworkingout. offsetbyone: *Main>take5(zipWith(+)fib(drop1fib)) [2. multiplied by fiveandthenagainby2. f(g x) . Y o u can easily see how you’d compose the solutions to problems.W ecalled listbyindex.5.D AY 2: S POCK ’ S G REAT S TRENGTH 290 The three functions are beautiful and concise.flipVertically an image processor might do something like . operator. W e define an infinite sequence.Startingfromtheinside (*5) . In Haskell.That’sapartiallyappliedfunction.20. to invert an image.13] Surprise.]) *2 totheinfinite W e r ’eusingmaptoapplythepartiallyappliedfunction 1.3.10] *2)[1.invert)image .W e passeditthe + function. let’s add two Fibonacci sequences together. First.wecoulddoublearange: *Main>take5(map( [2.50] * 2). Y o u f .Forexamapplythemfromfirsttolast. These higher-order functions zipWith.whichpairseachitemoftheinfinite playwelltogether. Y o u can really start to have fun when you start to combine infinite sequences together.Y o u d ’ dosowiththe ple.0printing. e pass that a p and apply the function to every element composed function into m take 5 and in the infinite fib sequence.andHaskellcomputesonlythepartnecessarytodothejob.

From day 1 Haskell’s type system was unusually expressive. let’s hear from another person on the committee that created Haskell.implicitparameters. higher-ranktypes. and compilers check them every time they compile the program. and the chances are that it was originally developed by one person or averysmallteam.0printing. Think of any successful language. Haskellhasservedasalaboratoryinwhichtoexplorenewtypesystem ideas. Simon Peyton Jones spent seven years as a lecturer at University College London and nine years as a professor at Glasgow University. probably the most unusual andinterestingfeatureofHaskellisitstypesystem.Statictypesareby farthemostwidelyusedprogramverificationtechniqueavailabletoday: millionsofprogrammerswritetypes(whicharejustpartialspecifications) every day. is an unfamiliar discipline that has prevented Haskell frombeingamainstreamlanguage.Multiparametertypeclasses. Reporterratum thiscopyis (P1.GADTs. I believe they will have strong mechanisms for controllingsideeffects.somethingIhaveenjoyedverymuch. Languages usually succeed or (mostly) fail in the first few years of their lives. Bruce Tate: TellmeaboutthecreationofHaskell. Bruce Tate: Whatarethethingsyoulikeaboutitthemost? Simon Peyton-Jones: Apart from purity.W ehadenoughagreement about the core principles of the language—and Haskell is a very principledlanguage—tokeepthedesigncoherent. Since then. Also.Heistheleaddesignerofthecompilerusedinthisbook.Thoselong-termbenefitsaregraduallybecomingapparent. the absence of side effects. Simon Peyton-Jones: A very unusual thing about Haskell is that it is a successful committee language.Types aretheUMLoffunctionalprogramming: adesignlanguage thatformsanintimateandpermanentpartoftheprogram. so what is going on? I believe that it is because Haskell’s principled adherence to purity.October2010) .Haskellisdifferent:itwasoriginallydesignedbyan internationalgroupoftwenty-ishr e s e a r c h e r s .Haskellisenjoyingasubstantialupsurgeinpopularitysometwenty years after it was designed. before moving to Microsoft Research (Cambridge) in 1998 where his research focus is the implementation and applicationoffunctionalprogramminglanguagesforuniprocessorandparallel machines.first-classpolymorphism.Whetherornotthemainstreamlanguagesofthe future look like Haskell.D AY 2: S POCK ’ S G REAT S TRENGTH 291 AnInterviewwithSimonP e y t o n J o n e s To take a quick break. mainly because of type classes and higher-kinded type variables.

0printing. it is quite common to find that Haskell is a medium in which people have been able to dream up particularly elegantandunusualwaystosolveproblems. WhatW eLearnedinDay2 Inday2. which is a strength but also a weakness because it has no single “killer app.we’lllookintomonads.anditwillofferinterfaceK. such as dealing with I/O. which r e w r i e d my brain by making me think of a “time-varying value” as a single value that could be manipulated by a functional program.W estartedwiththesame kinds oflist libraries that you’ve seen in almost every language in this Reporterratum thiscopyis (P1.October2010) . for example.Jean-MarcEbershowedmehowtodesign acombinatorylibrarytodescribefinancialderivatives. I want to be able to ship a HaskellpackagePtosomeoneelse. These problems will take us into some advancedtheory. but you can’t do some easy stuff...Onday3. the medium (Haskell) has allowed a new level of expressiveness that would be much harder to achieve in a mainstream language.D AY 2: S POCK ’ S G REAT S TRENGTH 292 and type families.welookedathigher-orderfunctions. more importantly.” That said. By now.Inathirddomain. In each case. we are extending the range of properties that can be statically checked by the typesystem.we are having fun! And.LookatConalElliot’sworkon functional r e a c t v ie animation.somethingIwould neverhavethoughtofonmyown.eachencapsulatinggreatintellectualclevernessbehindsimple interfaces. and error handling. On a more mundane (but very useful)level. Bruce Tate: What’s the most interesting problem you’ve seen solved withHaskell? Simon Peyton-Jones: Haskellisatrulygeneral-purposeprogramming language.therearelotsoflibrariesofparserandpretty-printingcombinators.saying“Pneedstoimportinterfaces IandJfromsomewhere:youprovidethem.Therearer e a s o n s thatHaskell’sr e c o r dsystemissosimple.butit’sstillaweakpoint. Specifically. Bruce Tate: What are the things you’d change if you had it to do all overagain? Simon Peyton-Jones: I’dlikeabetterr e c o r dsystem.” Haskellhasnoformalwaytosaythis. you have enough knowledge to tackle some hard problems in Haskell. state. I’d like a better module system.

99 andcanpossiblyhaveleading shouldbeintheformof zeros. W function that took arguments one at a time ( e learned that in Haskell.whichwouldbeprocessedondemand.ortuples • Awaytosortlists Do: •W r t i easortthattakesalistandreturnsasortedlist.Afterworkingwiththemonfixedlists. beginning with Combine these functions through composition to return every eighthnumber. we learned to take a functionandapplysomeoftheparameters. the type signatureofthefunction fxy=x+y is f::(Numa)=>a->a->a .678. 293 As we worked through advanced functions.write sequencethathaseverythirdnumber. Day2Self-Study Find: • Functionsthatyoucanuseonlists.Thistechniquewascalled partially applied functions .345.W e defined a Fibonacci sequence in this way and also used composition withlazysequencestoeffortlesslyproducenewlazysequences. x and returns a lazy •W r t i e a function that takes an argument x.strings.severalversionsof o fd l .whichexplainedthetypesignatures of Haskell functions taking multiple arguments.October2010) . Reporterratum thiscopyis (P1. a process that used the return from one function as the input of another.Y o usaw tionslike zip and zipWith. W e also learned function composition. a function that includes every fifth number.beginningwith x+y . •W r t i easortthattakesalistandafunctionthatcomparesitstwo argumentsandthenreturnsasortedlist. For example.Then.0printing. •W r t i eaHaskellfunctiontoconvertastringtoanumber.Thestring $2.andsomeadditionalfuncbook. W e could effectively string functionstogetherthisway.wethen workedwithsomelazytechniquessuchastheonesyouusedwithClojure. Finally.allfunctionsarecurried. W e were able to define functionsthatbuiltinfinitelists. we worked with lazy evaluation. we used partially applied functions to f (x. y) ) to a translate a function that took multiple arguments at once ( f(x)(y)).startingwith y.D AY 2: S POCK ’ S G REAT S TRENGTH m a p . Then.

Thetypesystemisflexibleandrichenoughtoinfermostofmyintent. 8. It allows type inference. In this section. BasicTypes Let’s review what you’ve learned so far with some basic types. we’ll look at a few examples of types and then buildsomeofourowntypes.andfullyjustify thetextwithspaces(makingbothmarginsstraight). • Addlinenumberstothepreviousexercise.D AY 3: T HE M IND M ELD 294 • Use a partially applied function to define a function that will re\n totheend turnhalfofanumberandanotherthatwillappend ofanystring.Haskellenthusiastsoftenclaim such a connection to their language. For many of them. stayingoutofmywayunlessIneedit.right. I can easily see why this is true. the language featurethatengendersthemostrespectisthetypesystem.IalsogetasanitycheckasIbuild myfunctions.4 Day3:TheMindMeld In Star Trek .addfunctionstoleft. ClassesandTypes Haskell’s type system is one of its strongest features. we’llturnonthetypeoptionintheshell: Prelude>:set+t Reporterratum thiscopyis (P1.October2010) . meaning you can treat different forms of the same type the same.0printing. • Break a long string into individual lines at proper word boundaries. so programmers do not have heavier responsibilities. It is alsorobustenoughtocatchevensubtleprogrammingerrors.especiallytheabstractonesthatcomposefunctions.Itispolymorphic. Here are some more demanding problems if you’re looking for somethingevenmoreinteresting: •W r t i e a function to determine the greatest common denominator oftwointegers.Afterspending so much time with the language. Spock had a special talent of connecting with a characterwithwhathecalledthe mindmeld . • Createalazysequenceofprimenumbers. • Totheaboveexercise. First.

we’llseethetypesthateachstatementreturns.withanarrayorwiththedoublequotes.the valuesarethesame: Prelude>"abc"==['a'.ToHaskell. for example.Itdoesn’tmatterhowyourepresentthearray ofcharacters. wouldbedefinedlikethis: dataBoolean=True|False Boolean will have a single value.ToHaskell.'c'] True Thereareafewotherprimitivetypes.D AY 3: T HE M IND M ELD 295 Now.hs T r u e moduleMainwhere dataSuit=Spades|Hearts dataRank=Ten|Jack|Queen|King|Ace Reporterratum thiscopyis (P1. User-DefinedTypes data keyword. these ideas will help us see what’s really goingon.Thesimplest W e candefineourowndatatypeswiththe of type declarations uses a finite list of values. Consider this simplifieddeckofcards.'b'. either That means that the type a s le .October2010) .Try somecharactersandstrings: Prelude>'c' 'c' it::Char Prelude>"abc" "abc" it::[Char] Prelude>['a'. W or F e can define our own types in the same way.likethis: Prelude>True True it::Bool Prelude>False False it::Bool As we dig deeper into typing. Boolean.withtwosuitsandfiveranks: Download haskell/cards.Let’sdefinesomeofourowntypes.'c'] "abc" it::[Char] it always gives you the value of the last thing you typed. and you can read :: as isoftype .acharacterisaprimitivetype.0printing.'b'.Astring isanarrayofcharacters.

Suit and Rank are type constructors .hs [1of1]CompilingMain Ok.0printing.modulesloaded:Main. That’seasy.D AY 3: T HE M IND M ELD 296 In this example.interpreted) Reporterratum thiscopyis (P1.anda e tobuildnewfunctions: value::Rank->Integer valueTen=1 valueJack=2 valueQueen=3 valueKing=4 valueAce=5 cardValue::Card->Integer cardValue(rank.interpreted) <interactive>:1:0: Noinstancefor(ShowSuit) arisingfromauseof`print'at<interactive>:1:0-5 Argh!Whathappened?Haskellisbasicallytellingusthattheconsoleis tryingtoshowthesevaluesbutdoesn’tknowhow.Hearts) 1 (cards-with-show.There’sashorthand waytoderivethe show functionasyoudeclareuser-defineddatatypes.hs.Y o ucanloadthemodulelikethis: *Main>:loadcards.Suit) typeHand=[Card] Noticeweaddedafewaliastypestooursystem. W e used data to buildanewuser-definedtype.October2010) .modulesloaded:Main.hs. *Main>cardValue(Ten.W e simplydefineafunca u l e ofa Rank andthenanotherthatcomputes tionthatcomputesthe v a cardValue.suit)=valuerank Card isatuplewith canusethesetypes For any card game. Itworkslikethis: Download haskell/cards-with-show.W arankandasuit.hs moduleMainwhere dataSuit=Spades|Heartsderiving(Show) dataRank=Ten|Jack|Queen|King|Acederiving(Show) typeCard=(Rank.Here’sthefunctioninaction: *Main>:loadcards-with-show.A Hand isalistofcards.hs [1of1]CompilingMain Ok. we need to be able to assign the ranks of a card.Thesuitreallydoesn’tplayarole. *Main>Hearts (cards.

Sonow. FunctionsandP o y lm o r p h s im Earlier.W type a andreturnsalistofthatsametype t i h [a] -> [a].hs. the function is polymorphic.hs moduleMainwhere dataTripleta=Trioaaaderiving(Show) dataT p r ie l ta Ontheleftsidewehave .yousawafewfunctiontypes. It means that we can define a function that takes a list of some a. That would restrict the backwards function to working with only one cards. Let’sbuildapolymorphicdatatype.we’vetold Integers.anythree-tuplewithelementsofthesametypewillbeof p r ie l ta type T . *Main>:tTrio'a''b''c' Trio'a''b''c'::TripletChar (triplet. W e l’ talk more aboutthedataconstructorsinthenextsection.hs [1of1]CompilingMain Ok.Here’sonethatbuildsathree-tuple havingthreepointsofthesametype: Download haskell/triplet.Basedonourtypedec- Reporterratum thiscopyis (P1.Let’slookatasimplefunction: backwards[]=[] backwards(h:t)=backwardst++[h] W e couldaddatypetothatfunctionthatlookslikethis: backwards::Hand->Hand . a isatypevariable. this function will the compiler that if you start with a list of return a list of Integers.soit’seasiertoreasonaboutwhat’s happening.Whatwereallywantisthis: kindoflist.we’vebuilt atemplateoftypesthatwillworkwithourfunction.Takealook: *Main>:loadtriplet..Inthisinstance. Haskell now has enough information to keep youhonest.October2010) . [a] means we can use a list of any type.0printing.D AY 3: T HE M IND M ELD 297 W e r ’e working with a complex tuple of user-defined types.modulesloaded:Main. The type systemkeepsourintentionsclear.interpreted) o r i I used the data constructor T to build a three-tuple.alistof backwards::[a]->[a] backwards[]=[] backwards(h:t)=backwardst++[h] Now.Further..

hs [1of1]CompilingMain Ok.W So. we build a tree having a single leaf.Leaf2] *Main>lettree=Children[Leaf1.interpreted) First. *Main>letleaf=Leaf1 *Main>leaf Leaf1 (tree.iseitheraleaforalistoftrees.describinganythreeelementswhosetypeisthesame. W e can use all of those together to represent trees.D AY 3: T HE M IND M ELD T p r ie l ta T p r ie l tchar laration.then. Reporterratum thiscopyis (P1.October2010) . so we can go as deep as we need through let andpatternmatching.wehaveonetypeconstructor.Y o ucandothisinseveralways.Anode. a leaf and a right tree. Children and Leaf.Children[Leaf2.a T p r ie l ta willsatisfyanyfunctionthatrequiresa .hs could moduleMainwhere dataTreea=Children[Treea]|Leafaderiving(Show) T r e e . e alsohavetwodataconstructors.Leaf3]] *Main>tree Children[Leaf1. 298 and RecursiveTypes Y o ucanalsohavetypesthatarerecursive.W e describethetreelikethis: Download haskell/tree.Forexample. Once again.ormorespecifically.Next.hs. W e can access each piece through pattern matching.likethis: Prelude>:loadtree. The only job of the data constructor ues together with the type.Children[Leaf2.Leaf3]] W e buildatreewithtwochildren.thinkabouta tree.eachonebeingaleaf.modulesloaded:Main. The definition is recursive.W e v ’ebuiltawholetemplateoftypes. *Main>Children[Leaf1. W e assign the new leaf to a Leaf is to hold the valvariable.likethis: *Main>let(Leafvalue)=leaf *Main>value 1 Let’sbuildsomemorecomplextrees.thevaluesareon theleafnodes.theresultwasa .Leaf2] Children[Leaf1.webuild a tree with two nodes.W e cangetmorecomplexfrom there.0printing. we can use patternmatchingtopickoffeachpiece.butinourtree.

youcan’taddtwobooleanstogether.Children[Leaf2. It’s not an object-oriented class.Thisdesignstrategy obviouslycomeswithanoverhead.thedepthofthetreeisone.we’vebeenthroughthetypesystemandhowitworksinacouple of areas.Forexample.Ifwecalldepthon a x m iu m(mapdepthc) a x m iu m weaddoneto m .Inthiscase. and you’ve seen that will compute a list of the depths of all the children. Here’showitworks. Thenextpatternisalittlemorecomplicated.butyoucanaddtwo numberstogether.0printing. Children.InHaskell.Aclassprovidessomefunctionsignatures.butasyoudiveintodeeperabstractions. you can see how we use the data constructors to help us match the exact piecesofthedatastructurethatwillhelpusdothejob.but relatedtotypes. Classes Sofar.there’saclasscalled Reporterratum thiscopyis (P1. intheHaskelllibrary.Ifit’saleaf.Atype isaninstanceofaclassifitsupportsallthosefunctions.Theconceptiscalledthe be careful. .sometimestheextraoverheadisworththehassles.Haskellallowsclassesforthispurpose.andit’sabigone.Specifically. Eq.classesletuscarefullycontrolpolymorphismand overloading. Think of it a class defines which operations can work on which inputs likeaClojure protocol. W e v ’e built user-defined type constructors and got templates that would allow us to define data types and declare functions that would work with them.Leaf3]] *Main>let(fst:tail)=ch *Main>fst Leaf1 299 W e canclearlyseetheintentofthedesignerofthetypesystem. thetypesystemallowsustoattachfunctionstoeachspecifictypeconstructor.regardlessofthe contentoftheleaf. because there’s no data involved.Thefunction m computes m a p depth c the maximum element in an array. Haskell has one more important concept class.D AY 3: T HE M IND M ELD *Main>let(Childrench)=tree *Main>ch [Leaf1. In this case.October2010) .andwe canpeeloffthepiecesthatweneedtodothejob. Forexample.Let’slookatafunctiontodeterminethedepthofatree: depth(Leaf_)=1 depth(Childrenc)=1+maximum(mapdepthc) Thefirstpatterninourfunctionissimple.

not data objects! Reporterratum thiscopyis (P1.anditbehaveslikeyouthinkitshould. etc) Ord (sequential) Num (numbers) Enum (ordering) Real (numbers) Fractional (numbers) Integral (integers) RealFrac (numbers) Floating (numbers) Figure8. if an instance definesone of thosefunctions.D AY 3: T HE M IND M ELD 300 Read Eval Show Support for most types  ¡ (equality) Bounded (tuples.the Num classhassubclasses Fractional and Real.atypeisaninstanceof o ucanalso specify boilerplate implementations.theotherwillbeprovidedforfree. Also. Classesdosupportinheritance. instances of these classes are types.(/=)::a->a->Bool --Minimalcompletedefinition: -(==)or(/=) x/=y = not(x==y) x==y = not(x/=y) Eq ifitsupportsboth == and /=.0printing.Thehierarchy of the most important Haskell classesin Haskell 98 is shown in Figure 8.1:ImportantHaskellclasses Here’swhatitlookslike: class Eqa where (==).October2010) . Forexample. Remember.Y So.1.

youwill v isthevaluethat havestatementsstrungtogethersequentially.October2010) . In this section.Inanimperativelanguage. http://www.D AY 3: T HE M IND M ELD 301 Monads FromthetimeIdecidedtowritethisbook.0printing.I’vedreadedwritingthesection on monads.the have mutable state.haskell. A staggermovestwo steps.org/wiki/Haskell/Understanding_monads Reporterratum thiscopyis (P1. I’ll walk you through the intuitive description of why we need monads.Finally.html http://en. like this: Download haskell/drunken-pirate.likethis: deftreasure_map(v) v=stagger(v) v=stagger(v) v=crawl(v) return(v) end treasure_map thatsequenW e haveseveralfunctionsthatwecallwithin distance traveled.Theproblemisthatwe tiallytransformourstate.wikibooks. 4. He’s drunk.we’llintroducesomesyntacticsugarthatshouldreallybringhomehowtheywork. But you’ll probably find that you need to wade through several examples from many differentsourcestocometoanunderstandingofwhatmonadscando foryou. The Haskell wiki 3 has several good examples that I read. I’ve learned that the concepts are not all that difficult. I leaned on a couple of tutorials to help shape my understanding. Then.andacrawlmovesonestep. so he picks up a known point and a known direction and makes his way to the treasure with a series ofstaggersand crawls. TheProblem:DrunkenPirate Let’s say you have a pirate making a treasure map.org/tutorial/monads. W e could do the problem in a functional way. and also Understanding Monads 4 has some good practical examples.hs moduleMainwhere stagger::(Numt)=>t->t staggerd=d+2 crawld=d+1 3. we’ll look at a high-level descriptionofhowmonadsarebuilt.where holdsdistancefromtheoriginalpoint. After some study.

W e canusea let expressioninstead: letTreasureMap(v. Finally. Also. Instead.amonadletsuscomposefunctionsinwaysthathavespecific properties. First.Rather than stagger.0printing.forexample. The container could be a simple variable. Haskell provides a specialsyntax. a function should deliver the same results when given the same inputs. ComponentsofaMonad Atitsbasiclevel.That’samonad. The inputs and outputs are the same. Y o u can see that this version is almost as unsatisfying as the first. or anything that can Reporterratum thiscopyis (P1. we’ll use monads for several purposes. we’d like a strategy that will let us chain several functions together sequentially.amonadhasthreebasicthings: • A type constructor that’s based on some type of container. Inshort.D AY 3: T HE M IND M ELD treasureMapd= crawl( stagger( staggerd)) 302 Y o ucanseethatthefunctionaldefinitionisinconvenienttoread. In Haskell. Dosyntaxdependsonmonadstowork. Haskell provides the Maybe monad for this purpose. we must read crawl. but for I/O. stagger. where · is function composition. Let’sdigalittledeeper. and crawl.d)=letd1=staggerd d2=staggerd1 d3=crawld2 ind3 let expressions together and express the Haskell allows us to chain final form in an in statement. Monads let you simulate program state. W e want to translate stagger(crawl(x)) into stagger(x) · crawl(x). and the arguments are awkwardly placed. and stagger.called dosyntax . so it should be easier to compose these kinds of functions. stagger. dealingwiththingssuchasI/Oisdifficultbecauseinapurefunctional language. you would want your functions to change basedonthestateofthecontentsofafile. code like the drunken pirate earlier works because it preserves state. a list.October2010) .toallowprogramsintheimperativestyle. something as simple as an error condition is difficult because the type of thing returned is different based on whether the function was successful.

October2010) .I’lltrytoleaveyouplentyofreferences. BuildingaMonadfromScratch The first thing we’ll need is a type constructor.D AY 3: T HE M IND M ELD 303 holdavalue. and a bind. but the reasons are pretty simple.W • Abindfunctioncalled e l’ tochainfunctionstogether.Justrememberthat return wrapsupafunctionintoa monad.Forsomemonad m. use bind All monads will need to satisfy three rules.whenwemoveinto do notation.W ewillusethecontainertoholdafunction. I’ll mention them briefly here.( (m>>=f)>>=g=m>>=(\x->fx>>=g) ) W e won’t spend a lot of time on these laws. >>= thatunwrapsafunction. Our monad is the simplest possible.likethis: Download haskell/drunken-monad. Enoughofthetheory.Thecontainer you choose will vary based on what you want your monad todo. a return.andthenI’llclosethechapterwithafewusefulmonads. They allow many useful transformations without losing information.0printing. Our monad will have a functionandavalue. The type container is Reporterratum thiscopyis (P1.Thenamewillmakesenselater.andsomevalue x: •Y o u should be able to use a type constructor to create a monad thatwillworkwithsometypethatcanholdavalue.somefunction f.W e l’ buildonefrom scratch.( monad>>=return=monad ) • Nesting bind functions should be the same as calling them sequentially. •Y o u should be able to unwrap and wrap values without loss of information. • A function called return that wraps up a function and puts it in thecontainer.Ifyoureallywanttodivein.Let’sbuildasimplemonad.hs moduleMainwhere dataPositiont=Positiontderiving(Show) stagger(Positiond)=Position(d+2) crawl(Positiond)=Position(d+1) rtnx=x x>>==f=fx The three main elements of a monad were a type container.

Oursiscalled x it to just call the associated function with the value in the monad ( >>==f=fx ).0printing. All it a simple type constructor that looks like does is define a basic type.Finally. sugar to improve it some more.Sinceourmonad is so simple. Remember. butwe’reactuallyusingmonads.W ecantakeourmonadoutforatestdrive. Haskell’s The do syntax comes in handy especially for problems like I/O. weneeda return thatwrapsupafunctionasavalue. we just have to return the value of the monad itself.butyoucaneasilyimaginesomesyntactic do syntax does exactly that.Therevisedtreasuremaplookslikethis: treasureMappos=pos>>== stagger>>== stagger>>== crawl>>== rtn 304 Anditworksasexpected: *Main>treasureMap(Position0) Position5 MonadsanddoNotation Thatsyntaxismuchbetter.using do notation: Download haskell/io.D AY 3: T HE M IND M ELD data P o s o t in t=P o s o t in t. based on an arbitrary type template.October2010) . and rtn x=x ).hs moduleMainwhere tryIo=do putStr "Enteryourname:" .Y o u l’wanttobeawareofafewsyntax rules. return( "Hello. Reporterratum thiscopyis (P1.wereadalinefromtheconsoleandprintoutthesame lineinreverse.W e r ’e using >>== and rtn insteadof >>= and return toprevent collisionswithHaskell’sbuilt-inmonadfunctions.Thatmakesourprogramfeelstatefulandimperative. line<-getLine. In the followingcode. let{backwards=reverseline}. stagger and crawl to use our homegrown Notice that we also rewrote monadinsteadofnakedintegers. do notation to give us the syntactic sugar Then.with( >>==. we use the simple aroundmonads.Yournamebackwardsis" ++backwards) Notice that the beginning of this program is a function declaration. we were after a syntax that translates from nesting tocomposition. Next.andwedefine thatallowsustocomposefunctions.weneededabind it’swrappedupappropriately.

ourpasswordcrackeriseasy..takealookatthefollowing script. butwecouldhaveeasilyused To giveyouafeelforthelistmonadinaction.2]. and let expressions therein.Fromthatpoint.. constructor. Reporterratum thiscopyis (P1.alistisalsoamonad.Tounwrapit.(2. This code return value in a tidy form that the behaves as if it were in a stateful imperative language.y<-ys. It neatly packages a we called our monad’s wrapping construct do syntax can absorb.Strangeasitmayseem. concat and m often enough that there’s a function that does both for convenience.y) Main>cartesian([1.(1. which we used in the drunken-monad example.andwetook y fromalistof xy. and a bind method that unwrapsit.in do notation: Main>letcartesian(xs.W e usedit toconverta nestedprogram structure to a sequential program structure.Andnow. but it’s using monads to manage the stateful interactions. The identity monad.return(x.givingusourtype return. All I/O is tightly encapdo sulated and must be captured using one of the I/O monads in a block.ourbind calls the function on every element of the list with m a p and then cona p areappliedinsequence catenatestheresultstogether.Then. and include the body of withinbraces.youshouldwrapyourcodein :{ and }: witheachonaseparateline.Ifyouhavemultiplelines.with (>>=)definedlikethis: instanceMonad[]where m>>=f =concatMapfm returnx=[x] Recall that a monad needs some container and a type constructor.Amonadisaclass. Let’s take another examreturn andbind ple.(2.4]) [(1. W W e created a simple function with e took x fromalistof xs.October2010) . DifferentComputationalStrategies Every monad has an associated computational strategy.3).ys)=dox<-xs.4)] do notation and monads.4).InGHCI.wereturnedeach combinationof x and y. a return method that wraps up a function.3).and [ ] instantiatesit. just parrots back the thingyouputinto it.youmustseparatelineswithsemicolons do expressions.[3.D AY 3: T HE M IND M ELD 305 Assignmentuses <-.0printing.youcanfinallyseewhy return. concat(mapfm) .wewrapupthefunctioninthelist.W e nextneedafunctiontowrapuparesultas Forthelist.

In Maybe monad. Thinkastringsearchthatreturnstheindexofastring.Ifthestringis Integer..thebody withinthatpage...we’veseenthe t i hthelatter.Therearemanycomputationalstrategiesthatwecouldhaveused to solve this problem such as list comprehensions. htmlXmlDoc->XmlDoc .andthefirstparagraphwithinthatbody.we’reusingthelistmonadtocomputeallpossiblecombinations.True) elsereturn(password.hs moduleMainwhere crack=dox<-[ 'a'... x <.y<-[ 'a'. welearnedthatmonadssupportedacentralcomputationalstrategy. bodyXmlDoc->XmlDoc .[lst] means “for each x taken from [lst].. Let’s say you have a functionthatisparsingawebpage. MaybeMonad Identity monadandthe List monad...D AY 3: T HE M IND M ELD 306 Download haskell/password. present.y. "cab" thenTrueelseFalse Here.z]}.'c' ]. W e let Haskell do the heavy lifting.W Sofar.we’lllookatthe e l’ usethisonetohandle acommonprogrammingproblem:somefunctionsmightfail.W thissection.z<-[ let{password=[x. ifattemptpassword thenreturn(password. At that point.thereturntypeisan Stringing together such computations is tedious.Y o uwanttheHTMLpage. Theywillsupportafunctionthatlookssomethinglikethis: paragraphbody(htmldoc) Reporterratum thiscopyis (P1.Y o umight thinkwe’retalkingabouttherealmofdatabasesandcommunications. but this problem showedthecomputationalstrategybehindlistmonads.'c' ].Otherwise.0printing.False) attemptpw=ifpw== 'a'.Y o uwantto codefunctionsthathavesignaturesthatlooksomethinglikethis: paragraphXmlDoc->XmlDoc .thetypeis Nothing. all you need to do is attempt functryeachpassword.Ourpasswordishard-codedintothe tion. but other far simpler APIs often need to support the idea of failure..” Notice that in this context.October2010) .'c' ].

Thebindisalsoeasy. Justx canwrap Nothing.wecancombinetheelementsflawlessly..0printing. Either will be wrapped by the return. For Just x . Reporterratum thiscopyis (P1.gettingbacktoour Y o ucanstripoffthe example.Itworksbecausethemonad takes care of the decision making through the functions that we compose. considering we wanted to code paragraph 2 body (html doc) .so Theproblemisthatthe Nothing.For Nothing. Here’sthedefinition: dataMaybea=Nothing|Justa instanceMonadMaybewhere return =Just Nothing >>=f=Nothing (Justx)>>=f=fx . return iseasy.Haskellhassuchatype. and html documentscanreturn JustXmlDoc.likethis: Prelude>Just"somestring" Just"somestring" Prelude>JustNothing JustNothing 307 Just withpatternmatching. the paragraph. it returns a function returning Maybea .October2010) . Now.Then. youneedtoallowatypethatmaybe called Just.D AY 3: T HE M IND M ELD paragraph.youcouldusetheHaskell case statement(whichworkslike theErlangcasestatement)andpatternmatchingtogiveyousomething likethis: case(htmldoc)of Nothing->Nothing Justx ->casebodyxof Nothing->Nothing Justy ->paragraph2y And that result is deeply unsatisfying. What we really need is the Maybe monad.orsometype.So. Thetypewe’rewrappingisatypeconstructorthatis canwrap Nothing or Justa ..Itjustwrapstheresultin Nothing.and html functionscanfail. body. you canchaintogethertheseoperationseasily: JustsomeWebPage>>=html>>=body>>=paragraph>>=return So. it returns a function returning x. body.Thattype Just.

W elearnedhowtoparameterizetypesandevenuserecursive typedefinitions. we took on three demanding concepts: Haskell types. Then.W e startedwithtypes. booleans. it can be difficult to express problemsinanimperativestyleoraccumulatestateasaprogramexecutes. 5 ) 5.bylookingattheinferred types of existing functions.Since Haskell is a purely functional language. Thenodeshouldhavealistofexitstoothernodes.October2010) .0printing.A monadisatypeconstructorwithafewfunctionstowrapupfunctions andchainthemtogether. Day3Self-Study Find: • Afewmonadtutorials • AlistofthemonadsinHaskell Do: •W r t i e a function that looks up a hash table value that uses the Maybe monad. • Implement a Monad in a nonfunctional language.W r t i eahashthatstoresotherhashes. numbers. Maze type and a Node • Represent a maze in Haskell. W e then moved on to some user-defined types. we usedtypestodefineplayingcardsmadeupofsuitsandranksforplayingcards.Haskell’sdesignersleanedonmonadstosolvebothproblems. classes. As a basic example.W eused monadstoprovideamorenaturalimperativestyleforourprogramand toprocessmultiplepossibilities. (See the article seriesonmonadsinRuby. • UseaListmonadtosolvethemaze. and characters.Y o ucancombinemonadswithdifferenttype containerstoallowdifferentkindsofcomputationalstrategies.aswell asafunctiontoreturna nodegivenitscoordinates.rydia.severallevels deep.wewrappedupthelanguagewithadiscussionofmonads. Use the Maybe monad to retrieve an element for a hash keyseverallevelsdeep. Y o u l’need a type. http://moonbase.andmonads.D AY 3: T HE M IND M ELD 308 WhatW eLearnedinDay3 In this section.net/mental/writings/programming/monads-in-ruby/00introduction.html Reporterratum thiscopyis (P1.

0printing. It is there when you need it but not when you don’t. Haskell was the only one created by committee.bydefault. This syntactic sugar allowsimperative-styleprogramswithcertainlimitations. The Haskell type system provides an excellent balance of type safety and flexibility. providing do syntax . The type system can add a helpful level of protection from common errors.0 defined in 1990.lazycomputingstrategies.October2010) . Haskellsupportsawidevarietyoffunctionalcapabilitiesincludinglist comprehensions.Thesefunctionsallowprogrammerstochaintogether monads in interesting ways. Haskell developers can rely on monads for that purpose. Fortunately. A monad is a type constructor and a container that supports basic functions to wrap and unwrap functions as values.Infact. a committee was formed to build an open standard that would consolidate existing capabilities and future research.Haskelldevelopersmustbecreative to deal with imperative-style programs and accumulated state.5 WrappingUpHaskell Of all the languages in this book. Let’sbreakthemdown. TypeSystem If you like strong typing (and maybe even if you don’t).partiallyappliedfunctions.but thetypesystemprotectsusersfromallkindsoftypeerrors. I/O can also be a challenge. Aswithanypurefunctionallanguage.usingcurryingtosupportmultiplearguments. Reporterratum thiscopyis (P1. the Haskell programmer is notburdenedwithtypedetailsexceptinthefunctiondeclarations. you’ll love Haskell’s typing system. The language and communityhavegrownsincethen. Haskell was born. Different container types provide different computationalstrategies. CoreStrengths Since Haskell takes the absolute approach of pure functions with no compromise.Buttheextrasafetyisonlypartofthestory.W RAPPING U P H ASKELL 309 8. Usually.Haskellfunctionsprocessoneparameteratatime. and they can be caught at compile time rather than runtime. After the proliferation of purely functional languages with lazy semantics. with version 1. The fully polymorphic template system allows sophisticated support for user-defined types and even type classes that fully support inheritance of interface. andcurrying. the advantages and disadvantages can be often extreme.

Y o u can also be free of many of the problems thatcomefromdependingonsideeffects. This property makes it much easiertoreasonaboutprograms.benefittinggreatlyfromresearchanduseinthat setting. AcademicSupport Some of the most important and influential languages such as Pascal grewupinacademia.W RAPPING U P H ASKELL 310 PerhapsthemostinterestingpartofaHaskelltypeishoweasyitisto associatenewtypeswithnewbehaviors.W t i htypeconstructorsandclasses.Giventhesameinputs. or not.youcan even customize extremely complex types and classes such as Monads effortlessly. The ideas extend to data types where you can create types. As the primary teaching language for functional techniques. Though it is not fully a main- Reporterratum thiscopyis (P1. Y o u can often build programs that perform better and take a fraction of the total lines of code that another strategymighttake.yournewcustomtypescantakeadvantageof existingHaskelllibraries.Purefunctionallanguages giveyousomethingyoucandependon.Y o ucanbuildupsophisticated typesfromthegroundup. Expressiveness The Haskell language has fantastic power. From an abstract sense. PurityofProgrammingModel Pureprogrammingmodelscanradicallychangethewayyouapproach problems.suchasaccidentalcomplexityandunstableorslowbehaviorinconcurrentsituations. Haskell continues to improve and grow.Y o ucansometimesprovethataprogram is correct.W t i hclasses. dealing with functional languages meant dealing with recursion. They force you to leave old programming paradigms behind andembracedifferentwaysofdoingthings. it has everything you need to express powerful ideas concisely.afunction will always return the same values.October2010) . Those ideasencompassbehaviorthrougharichfunctionallibraryandapowerful syntax. Everythingyouwillneedisinthere.0printing.youcanfindno stronger language for teaching functional programming than Haskell. even recursive types that bind the right functions to the right datawithoutexcessivesyntax. LazySemantics Once upon a time.Inanacademicsetting. Lazy computing strategies offer a whole new set of strategies to deal with data.

Haskell’sstrengthstypicallyhaveaflipsideaswell.0printing. When you’re building a step-by-step algorithm. The concepts are intellectually demanding. CoreW e a k n e s s e s Y o u know by now that no programming language is perfect for every task.Most basic functions have parameterized types.October2010) .W RAPPING U P H ASKELL 311 streamlanguage. But we used monads to do some things that were trivial in other languages. Reporterratum thiscopyis (P1.ThoughHaskell makessomehardthingseasy. Though you can’t measure success by the size of a programming community. and rightfully so. Scala is all about compromise.italsomakessomeeasythingshard. Community Speaking of compromise. Certain styles lend themselves to certain programming paradigms. InflexibilityofProgrammingModel Being a pure functional language offers some advantages but also a setofheadaches. imperative languages work well.Bymakingcompromises.Y o umighthavenoticedthatprogrammingwithmonadswasthelastpartofthelastchapterinabookaboutprogramming languages. and functions on numbers often use a type class. LearningCurve ThemonadisnottheonlyintellectuallydemandingconceptinHaskell.I’vesaidit beforeaboutotherlanguages. Though the payoff may be well worth it in the end. Though both are strongly typed. such as write imperative-style programs.Scalahasinitially attracted a much bigger community than Haskell. and evenhandlelistfunctionsthatmayormaynotfindavalue. andHaskellisallaboutpurity. you can really see the differences in the approach of Scala and Haskell.you’llalwaysbeabletofindpocketsofprogrammers todoimportanttasks. Curryingisusedineveryfunctionwithmorethanoneargument.butI’llsayitagainhere.youmustbeastrongprogrammerwithfirmtheoreticalfootingto haveafightingchanceofsucceedingwithHaskell. you musthavesufficientnumberstosucceed. process I/O.andhavingmoreuserslends moreopportunityandcommunityresources. both have radically different philosophies. Heavy I/O and scripting do not lend themselves to functional languages. Purity in one man’s eyes may seem like failure to compromiseinanother.

W RAPPING U P H ASKELL 312 FinalThoughts Ofthefunctionallanguagesinthebook. Reporterratum thiscopyis (P1.October2010) .anditbecamethemostrewardinglanguageIlearned.Theemphasisonmonadsandthetypesystemmadethelearning curve steep. The best of the next generation of functional programmers in many placeswillcuttheirteethonHaskell. Once I mastered some of the key concepts. too. The purity of the approach and the academic focus will both improve our understanding of programming.0printing. things got easier.Haskellwasthemostdifficult tolearn.Basedon thetypesystemandtheeleganceoftheapplicationofmonads.oneday we’ll look back at this language as one of the most important in this book. Haskell plays another role.

1 ProgrammingModels Programming models change extremely slowly. I learned a more structured approach with Pascal. I was like a 1970s movie loverinasmalltownwithonetheater. In college. Just as independent films are advancing the state of the art in movie making. we’ve seen new modelsemergeeverytwentyyearsorso. but I’m not naive enough to think Ruby has all of the answers. emerging programming languages are changing the way we think about program organization and construction. Let’s review what we’ve seenthroughoutthebook. and I’ve seen only two major programming . Perhapsyou’reexpectingmetopickwinnersandlosersinthischapter. Basic and Fortran. In such a world. I’ve been able to make a living coding Ruby. I started to code C and C++ commerciallyandwasintroducedtoJavaforthefirsttime. So far. my exposure to programming languages was extremely limited.gettingonlythebig-moneyblockbusters.Ialsobegan writingobject-orientedcode. I feel like I’ve just discovered independent films.Mytrainingstartedwithsome procedural languages. It’s about discovering newideas. Since I started building software for myself.Y o umayhavebeenlikemeearlyinmycareer.Myprogrammingexperiencehasspanned more than thirty years. At IBM.burieddeeply in commercial projects in large teams with little imagination. 9. but this book is not about winners and losers. the software factories of our generation.Chapter 9 Wrap-Up Congratulations on making it through seven programming languages.

W e learned that Ruby supported several functionalconceptsthroughcodeblocks. ObjectOrientation(Ruby.Whenyou findyourselffightingaprogrammingparadigm.Somespecially designated instances serve as prototypes for other object instances.itismuchlessverbosethanJava. Though programming paradigms change slowly.Simpleandexpressive.andbothrepresentsignificantadvancesinlanguagedesigncompared to mainstream languages such as Java. Like a tornado’s path. Rather than enforcing a contract based on the definitionofaclassorobjects. W t i h Ruby.allprototypesareobjectinstances. Concurrency and reliability are starting to nudge us in the direction of a higher-level programming language. they do change.0printing.Rubyenforcedtypingbasedonthemethods an object could support. Both of these languages run in widespread production applications today.buttheyarejustdifferentenoughinpracticethatI introducedthemasadifferentprogrammingmodel. Though it supports statictyping.Scala) Thecurrent“kingofthehill”isobjectorientation. It’s a fair question. I think we’re going to start to see more specialized languages to solve specific problems. we experienced dynamic duck typing. taking the formofbrokencareersandcompaniesthatinvestedpoorly. PrototypeProgramming(Io) Y o ucouldactuallysaythatprototypelanguagesareasubsetofobjectorientedlanguages. Scala automatically deduces the type of variables based on clues in syntax and usage.October2010) . including the next programming paradigm.ScalagoesbeyondRubytointroducefunctionalconcepts.offeringfeaturessuch as type inference to simplify the syntax.youneedtostartpaying attention.prototypelanguagesaretypicallydynamicallytypedandworkwell Reporterratum thiscopyis (P1.prototypelanguages. offered object-oriented programming.typicallyintheJava language.P ROGRAMMING M ODELS 314 paradigms. and polymorphism. inheritance. they can leave behind some devastation.Ratherthanworkingthroughaclass. too. Y o u might be asking yourself why I am so enthusiastic about introducing a few other programming paradigms. Scala. Minimally. ThisfamilyoflanguagesincludesJavaScriptandIo. There are many variations of object-oriented languages. W t i h this feature. This programming paradigm has three major ideas: encapsulation.Thesearetheprogrammingmodelsweencountered.

consistent syntax can be a powerful combination. The degree of purity found in functional programming languages differs. we were able to get results with a fraction of the lines of code that it would take in other languages. When the programming model fit this paradigm.Butthisprototypeprogrammingwasnotthemostspecializedparadigmthatweencountered.Y o ucanalsofindcrudelogicalrulesenginesinotherlanguagessuchasCandJava.Erlang.P ROGRAMMING M ODELS 315 for scripting and application development. Y o ucancomposethosefunctionsinavarietyofways. but the concepts are consistent throughout. This family of language supports many of the most critical applicationsintheworldindomainssuchasairtrafficcontrolandcivil engineering. Y o u v ’e seen that functional programming languages are usually more expressive than object-oriented languages. Y o u r examples were often shorterandsimplerthantheobject-orientedcounterpartsbecauseyou had a broader range of tools for composing programs than you did intheobject-orientedparadigm.Haskell) Perhaps the most widely anticipated programming paradigm in this book is functional programming. especially for user interfaces.Callingthesamefunctionmorethanoncewillgiveyouthesame result each time.0printing. Functional programs are made up of mathematical functions.PrologservedastheinspirationofErlang.October2010) . As you learned within Io. but the results were often spectacular. As you learned in Haskell. and side effects are either frowned on or forbidden. fromanotherfamilyoflanguagesinthisbook. FunctionalProgramming(Scala.W edefinedlogicalconstraintsthatweknewaboutouruniverseandhadPrologfindthesolution.ThedifferentapplicationswebuiltwithProlog solved a fairly narrow type of problem. a simple programming model with a small.Oneclearwinforthefunctionallanguageswasthe Reporterratum thiscopyis (P1. different levels of purity lead to different sets of advantages anddisadvantages. W e used the Io language in broadly different contexts ranging from scripting concurrent programstogethertocodingourownDSL.W e introducedhigher-orderfunctions and also complex concepts such as currying as two examples that you can’t always find in object-oriented languages. Constraint-LogicProgramming(Prolog) Prolog comes from a family of programming languages built for constraint-logicprogramming.Clojure.

you’ll be better for knowing what’s out there.ThemodernJavadeveloper knows much more.W t i hScala. Philosophically.TheScalaprogrammer canconstructanobject-orientedprogramusingstrongfunctionaltendencies. Y o u can make a clean break from OOP. I hope you can appreciate the evolution of programming languages as well. Y o u saw three distinctly different approaches to evolving paradigms. mainlybecause peoplelike mewere uneducated and did not scream loud enough for them. and my eyesbledbecauseIhadtoreadthatstuff. there are several different ways to get there.UnlikeScala. Whetherornotyouchoosetoadoptoneofthelanguagesinthisbook.ClojureJava Interop is provided to leverage frameworks existing on the Java virtual machine.Take your pick. Clojure takes the approach of compatibility. but the Clojure philosophy is that certainelementsofOOParefundamentallyflawed. The very nature of the language is that both programming paradigms are first-class. making concurrent programming easier. allowing Clojure applications to use Java objects directly. so do many of the traditional concurrency problems.P ROGRAMMING M ODELS 316 absence of side effects. The language is built on the JVM. they donotembraceobject-orientedprogramminginanyform. Haskell and Erlang are basically stand-alone languages. My fingers bled from the oppressive amount of typing. I hadtowait a decade for closures.yousawlanguages spanning four decades and at least as many programming paradigms.0printing.October2010) . Aswewadedthrougheachofthesevenlanguages. Reporterratum thiscopyis (P1.So. make a clean break.theapproachiscoexistence. ChangingP a r a d g im s If you do decide that you want to do more functional programming. As a Java developer.youcan embrace both paradigms. or you can pick an approach that is slightly more evolutionary. partially because people such as Martin Odersky andRichHickeygaveusalternativesthatarenowpushingthestateof theartandforcingJavatoadvanceorgetleftbehind. not to broaden the programming language.mainstreamframeworkslikeSpringwerestuckwithanonymous inner classes to solve problems that could have used closures extensively. In the meantime. When mutable state goes away. or embrace object-orientedlibrariesbutdecidetoleavetheOOPparadigmbehind.

When side effects go away.October2010) .wesaw tangible techniques that went beyond the basic programming model.C ONCURRENCY 317 9.~n" ).Still. The functional programming language adds structure through an importantrule. It takes unstructured interprocess communication across any object boundaryandtransformsitontostructuredmessagepassingbetween first-class constructs. programs got much more complicated.at.erl -module(roulette). Let’stakeacloserlook. the approaches were often strikingly different but extremely effective.2 Concurrency Arepeatedthemeinthisbookistheneedforbetterlanguageconstructs andprogrammingmodelstohandleconcurrency. page181.erlang:time()}). V a r a ib e ls havea single assignment. on messages and conditionally execute them. The Erlang and Scala languages use pattern matching to match inbound Erlang. each one supporting a message queue.Whenyoumixinmultiplethreadsandprocesses.thecomplexity gottoogreattomanage. %sendanumber. In Chapter 6.Erlang.Multipleinvocationsofthesamefunctionleadtothesame result.loop() Reporterratum thiscopyis (P1.1-6 loop()-> receive 3->io:format( _->io:format( end.Recallthatweputthebulletinchamber3: Download erlang/roulette.Acrossthelanguages. raceconditionsandallrelatedcomplexitiesalsogoaway. Object-oriented programming allows side effects and mutable state.die. -export([loop/0]).andScala Whetherusinganobjectoraprocess. "click~n" ).webuiltanexamplearoundRussianroulettetodemonstrate adyingprocess. ControllingMutableState Byfar.themostcommonthemeintheconcurrencydiscussionwasthe programming model. ActorsinIo.theactorapproachisthesame. Let’swalkthroughsomeoftheapproacheswesaw. Taken together. "bang.0printing.exit({roulette.

assigning the ID to e could kill the process with Gun ! 3. with each relinquishing control at the appropriate time.Thissameapproach.Thoughtheresultwasnotimmediatelyavailable.Userscanuse differentprogrammingparadigmswhentheymakesensewiththeconfidence that the application will maintain integrity and performance. W e executed the statement futureResult := URL with("http://google. The Erlang virtual machine and language supportedrobustmonitoring.0printing. T r a n s a c o t in a lMemory In Clojure. Recallthatfutureswereplaceholdersforlong-runningconcurrentcomputations.allowingnotificationandevenrestartingprocessesatthefirstsignoftrouble. blocking only when we attempted to access the future. maintains database integrity across concurrent dosync function. An Io future actually morphs into a result when the result becomesavailable. As a Lisp derivative. The next generation of programmers will demand more out of his language.October2010) . It may be that the need for concurrency renders whole programming paradigms obsolete.com/") @fetch.but for database objects. or it may be that older languages will Reporterratum thiscopyis (P1.C ONCURRENCY Gun. Clojure developers can break away from strict functional designs where it makes sense and still have integrity across multiple threadsandprocesses. STM is a relatively new idea that is just creeping into more popular languages. eventhroughhighlyconcurrentaccesses.programcontrol returned immediately. we saw a number of interesting approaches to concurrency.Thesimplewheelandstickthatletyoustartathreadandwait on a semaphore are no longer good enough. 318 Futures To the actor model. A newer language must have a coherent philosophy supporting concurrency and the tools to match.Softwaretransactionalmemory(STM)wrappedeachdistributed accessofasharedresourceinatransaction. Coroutines allowed two objects to multitask cooperatively. W W e then started a process. W invocations. Io added two additional concurrency constructs: coroutines and futures. W e wrapped each access in a t i h this approach. Clojure is an ideal language for such anapproachbecauseLispisamultiparadigmlanguage.

W e used the Maybe monad to handle failure conditions.2.2.096}.1.032}] Severaldifferentlanguagecreatorsmentionlistcomprehensionsasone oftheirfavoritefeatures.W t i hpurefunctionallanguages.Quantity.1.20} ]. Scalaalsosupportslistcomprehensions.{paper.P ROGRAMMING C ONSTRUCTS 319 adaptbyusingstrictercontrolsformutablevariablesandsmarterconcurrencyconstructssuchasactorsandfutures.wecouldnotbuildprogramswith mutablestate. To add tax to the list.Price. Monads Perhapsthebiggestintellectualgrowthformewasintheareaofmonads. These are some of the programming constructs that you’re likely to see in other new languagesyoumightdiscover.3 ProgrammingConstructs One of the most exciting parts of writing this book was the exposure to the basic building blocks in the various languages of this book. thelistcomprehensionis acompactstructurethatcombinesseveralideasintoasinglepowerful construct.andHaskell. For each new language.Price * Quantity * 0. ListComprehensions 1 AsyousawinErlang.0.Quantity. a map. Haskell has do notation.October2010) . 0.Price}<-Cart].webuiltmonadsthatletuscomposefunctions in a way that helped us structure problems as if they allowed mutable state.4.1. I introduced major new concepts. supportedby monads. W e first encountered list comprehensions in Erlang. such as a List search that 1.25.{pen. Each of our monads supported a computational strategy.2. and a Cartesian product.0.Theyareamongmyfavoritediscoveries. 2.25}.{paper.0.Clojure.0. W e started with a shoppingcartofitemssuchas Cart= [{pencil.0.08}. A list comprehension has a filter.0.0printing.20}. Reporterratum thiscopyis (P1. to solve this problem.4.Instead.08}|| 8> {Product.butwedidnotusethem.likethis: 8> WithTax=[{Product. W e alsofoundthatmonadsallowustosimplify complexcomputation. we built a single list comprehension to solvetheproblematonce.1. [{pencil.Iagreewiththissentiment.{pen. 9.

Clojure. {From.Eachofthese languages leaned on pattern matching to significantly simplify code. From)followedbyaword( TheloopfunctionmatchedaprocessID( or blanca) or a wildcard.unification." loop() end.October2010) . W e used the List monad to compute a Cartesianproductandunlockacombination. casa Unification Prologusesunification.recallthetranslateservice: Download erlang/translate_service.andmore. loop(). W e first encountered this programming construct in Prolog. translate(To. Matching One of the more common programming features we saw was pattern matching.0printing. loop()-> receive {From.translate/2])._}-> From! "Idon'tunderstand.andHaskell.P ROGRAMMING C ONSTRUCTS 320 could potentially return Nothing. The problem domains included parsing. loop().erl -module(translate_service). "blanca" }-> From! "white" . destructuring.Y o ulearned thatPrologwouldsubstitutepossiblevaluesintoaruletoforcetheleft Reporterratum thiscopyis (P1.aclosecousinofpatternmatching. distributed message passing.Word)-> To!{self().XMLprocessing.Word}.Erlang. -export([loop/0. . ForatypicalErlangpatternmatch. The pattern match allows the programmer to quicklypickouttheimportantpiecesofthemessagewithoutrequiring anyparsingfromtheprogrammer. butwealsosawitinScala. receive Translation->Translation end. {From. "casa" }-> From! "house" .

I hope this book has helped you find your voice.Ihopeyouhadfun. matching the left side. W e learned that unification makes this program so powerful because it could work in three ways: testing truth. Everything you do goes into pleasing your audience. sets. Prolog would keep trying values until possibilities were exhausted. or matchingtherightside. 9.List. Reporterratum thiscopyis (P1.pl concatenate([].List.havean audience. I’m not talking about the users of our applications.youneedtowritetoyouraudienceandfindthevoicethatpleases them.Tobeagreatprogrammer. I’mtalkingaboutthepeoplewhoreadourcode.Tail2). Mostofall. Y o u l’ have more room to find that voice and let it evolve if you learnwhatotherlanguageshavetooffer. The joyofmoviemakingmeanscombiningyourexperienceswiththeactors. though.F INDING Y OUR V OICE 321 and right sides to match.List). concatenate([Head|Tail1]. W e looked at a simple Prolog program called concatenate asanexampleofunification: Download prolog/concat.4 FindingY our Voice W e v ’e talked about movies and characters throughout this book.W e . W eneedtothinkaboutprogramminginthesameway. and locations that tell the story you want to tell.Y o u rvoiceisyouruniqueway ofexpressingyourselfincode.October2010) . The more you know. the better yourmoviescanbe.0printing.too.Itwillneverbeanybetterthanthesum of your experience.[Head|Tail2]):concatenate(Tail1.List.

andDallas.CA.TX. .Inc. r e n tW o r d l andDallas.third edition. HackersandPainters:BigIdeasfromtheComputerAge . O’Reilly&Associates.2004. Chad Fowler. e iw .MountainV Programming [Gra04] [Hal09] [OSV08] [TFH08] David Thomas.Inc. MartinOdersky.andBillV e n n e r s . ProgrammingErlang:SoftwareforaConcur. Artima. Program. and Andrew Hunt.Raleigh. The Pragmatic Programmers.LexSpoon.2008.Appendix A Bibliography [Arm07] JoeArmstrong. Programming Clojure .TX. The Pragming Ruby: The Pragmatic Programmers’ Guide maticProgrammers.LLC.NC..2008.andDallas.LLC. PaulGraham. Stuart Halloway.Raleigh. Raleigh.2009.2007.CA.NC. inScala .Sebastopol. ThePragmaticProgrammers.TX.NC.LLC.

260–261 anonymousfunctions Clojure.233–234 mathematicaloperations.265 B C Bueller.317–319 Clojure.267 lists.238–239 atoms.264.224.318 infinitesequences.256–257 repl.228–229 threadstate.261.247–250.Alain.147–152 seealso objects Clojure.lists. see Io classes Haskell. see arrays.319 macros.250.253–254 maps.62 codeblocks.vectors Colmerauer.hashes.243–244 references.234–239 futures.229–230 forms.20.183 Io.320 prefixnotation.265 lazyevaluation.266 recursion.266–267 clonemessage.236 expressions.229–230 concurrency.258–259 bindings.262.258–259 installing.141 concurrency.225 Javaintegration.315 protocols.228 vectors.96 Scalaas.256–262.sets.224.36–37 atoms.Ferris.248–250 .262 patternmatching.239–241 destructuring.266 programmingmodel.226 creatorof.39–41 collections.41–44 Scala.226–228 metadata.171–175 agents.181.231–232 weaknessesof.262 multimethods.228 functions.198 Haskell.226 sequences.Io.223–267 agents.Ruby.285 Armstrong.Joe.256–257.244–250 sets.Clojure.236–237 booleans.262 transactionalmemory.318 typingmodel.265 console. maps.265 leiningen.264–266 strings.Ruby.256–262.89 Scala.250–253 readabilityof.299–300 Ruby.tuples.317–318 Erlang.Clojure.186 Prologas.Index A actors.260–261 anonymousfunctions.183–185 arrays.232–233 strengthsof.96 compiledlanguages Erlangas.231.238–239 Erlang.226 Lispand.

Ruby.164 forms.270–272 filtering.Haskell.18 decisionconstructs.183.320 programmingmodel.35 Scala.Steve.177 conditions Io.282–283.141–143 currying Haskell.207–213 patternmatching.261 Io.90 G H E games.182.281–282 lists.272–274.188–189.286–288 patternmatching.221 expressions.228 Erlang.60.186–188 weaknessesof.72–73 domain-specificlanguages withIo.95 Dekorte.154–155 functions Clojure.191–194.297–298 higher-orderfunctions.191 variables.133 Erlang.318 Clojure.228 forwardmessage.186–188 functions.268–312 anonymousfunctions.287–288 expressions.182.319 partiallyappliedfunctions.220 linkedprocesses.171–175.188–189 typingmodel.278–282.198–202 iteration.20.183.183–185 expressions.70–72 Scala.277–278 functions.287–288 Scala.160–166 futures.Haskell.198–202 Haskell.299–300 creatorsof.182–183.280–281 .189–191.165 F D datastructures.285–286 monads.319 messages.181–222 actors. 315 ranges.286–287 folding.139.93 Ruby.219–220 tuples.20.185–186.315 reliability.182–183.301–307.320 polymorphism.311 Scalaas.191.317–318 anonymousfunctions.311.310.297–298 programmingmodel.268.319 mapping.220 lightweightprocesses.234–239 Erlang.272–274.83–86 withScala.297–298 Ruby.Haskell.Io.181.207–213 Io.241 concurrencyand.88–91.58 Scala.213–218 lists.286–287 foldLeftmethod.18 declarativelanguages.310.185–186 Haskellas.191–194.196–198 creatorof.Clojure.291–292 currying.285–287 lazyevaluation.CONDITIONS H ASKELL Erlang. 315–316 Clojureas.Scala.198–205.198 atoms.86–88 functionalprogramminglanguages.38–39 Haskell.Ruby.32–34 dynamictyping Clojure.288–290 listcomprehensions.213–219 strengthsof.178 ducktyping.270–272 hashes.199 libraries.286–287 folding.155.268.194 Ruby.207–213 controlstructures.33 filtering.286–287 functioncomposition.Prologas.139 Erlangas.285 classes.Prologfor.188–189 concurrency.

Ruby.60.Prolog.274––159 Matsumoto.89.93 conditionalstatements.318 inheritance.44–47 modules.95 inferences.61.62.278–282 Io.267 lists.79–81 methods. 83–86 forwardmessage.75–77 maps.Ruby.68–70 Prolog.90.294–300 typingmodel.288–290 lightweightprocesses.Prolog.161–166 logicprogramminglanguages.68 operators.142–145.96.Clojure.253–254 maps Clojure.68.77 clonemessage.60–94 actors.86–88 futures.198–205 Haskell.68 K L knowledgebase.48–55 method_missingbehavior.309–311 tuples.63–66 Scala.135–137 strengthsof.220 linkedprocesses.317–318 assignment.279–280 recursivetypes.Ruby.264.44–47.Io.319 Clojure.224.224.81 slotsinobjects.Rich.265 Scalaand.Scalaas.Y u k h ir io(Matz).94 programmingmodel.66–68 mixins. see iteration M macros.Haskell.61.136–137.270–272.68 reflection.66–68 objects.111–116 Scala.177 I imperativelanguages.298–299 starting.61 interpretedmodelfor.75–77 Scala.233–234 Haskell.H ICKEY MONADS recursion.188–189.18 interpretedlanguages Ioas.72–73 domain-specificlanguageswith.199 Io.301–307.151 interactionmodel.75–77 lists.262 metaprogramming.275–278 types.Erlang.315 loops.93–94 iteration Erlang.160 hybridlanguages.19.269.285–286 Io.51–55 monads.26–27 messages.319 .75–77 conditions.69 messages.231 Erlang.285–287 Scala.88–91.79–81 metadata.Erlang.Io.96.239–241 higher-orderfunctions Haskell.Clojureand.61–66.161–163 J Java Clojureand.77–78 performance.70–72 creatorof.213–218 Lisp.28 Io.61 iteration.Prolog as.64 weaknessesof.68–70 loops.314 prototypes.309 Hickey.156–157.50–51 methods.Clojure.265 Haskell.269 strengthsof.Ruby.97 lazyevaluation Clojure.62 concurrency.61 Rubyas.92–93 typingmodel.63–66 installing.69 Scala.250.98–99 inheritance Io.

see Ruby programminglanguages installing.Haskell.126–131 inferences.18.168–171 performance Io.Clojure.49–50 Q R queries.45 strengthsof.56–58 stringhandling.109–111.23 learning.137–138 openclasses.61.17–19.96.314 runningfromafile.297–298 Poppins. 286–288 patternmatching.68 seealso classes Odersky.315 queries.314 Scalaas.58 creatorof.116–119 capitalizationin.96 Ruby.81 Roussel.133 O Sudokuexample.280–281 recursion Clojure.19.25–59 arrays.28 metaprogramming.68 object-orientedlanguages.111–114.105–108 strengthsof.98–99 knowledgebase. see Prolog ranges.Martin.Io.114–116 Scala.50–51 mixins.49–50 performance.250–253 prototypeprogramminglanguages.21–22 programmingmodel.Clojure.Ruby.97 creatorsof.291–292 polymorphism.41–44 codeblocks.56 spaceshipoperator.Io.111–114 unification.58 .29.51–55 openclasses.320 Erlang.30–32 functions.114–116 schedulingexample.298–299 references.29.44–47.26 installing.314 Ioas.Mary.101–103 math.26–27 decisionconstructs.162 recursivetypes.313–316 Prolog.317 N natural-languageprocessing.279–280 Prolog.44–47 modules.97 lists.controlling.109–111.57 typesafety.Simon.274–275.28 interactiveconsolefor.189–191 Scala.58 programmingmodel.Prolog for.95–134 appendrule.243–244 Haskell.Clojure.Prolog.320 weaknessesof.Phillipe.Haskell.262 mutablestate.121–126 tuples.19.41 scripting.Io as.111–116 mapcoloringexample.99–101 recursion.MULTIMETHODS R UBY multimethods.96 EightQueensexample.36–37 classes.38–39 historyof.39–41 concurrency.28 interpretedmodelfor.320 programmingmodel.114–116 patternmatching.Haskell.314 objects Io.29 timetomarket.48–55 method_missingbehavior.61 Rubyas.133 protocols.94 Ruby.132–133 RainMan.58 Peyton-Jones.99–101 P partiallyappliedfunctions.Haskell.103–105.35 hashes.314–315 prototypes.256–257 reflection.

W a d e lr .Ruby.56 semanticW e b .62.151 iteration.Clojure.159 auxiliaryconstructors.170.Clojure.282–283 webdevelopment.140–141 typingmodel. 256–257.Philip.159 patternmatching.179 weaknessesof.156–157.244–250 sets Clojure.32 Scala. 177 conditions.191 Haskell.58 webdevelopment.162 sets.57 XML.Ruby.Edward.Io.58 typingmodel.158–159 Nothingtype.228 Erlang.188–189 Haskell.111–114 typesafety.45 Spock.275–278 Prolog.68 Smith(Agent).137–138 currying.155 inheritance.Prologfor.177 lists.29 stronglytypedlanguages Clojure.140–141 U V unification.171–175.178 see Clojure .232–233 Scala.228–229 Ruby’shandlingof.315 ranges.178–179 XMLand.Brian.155.64 Ruby.25 T Tarbox.Ruby. see Erlang spaceshipoperator.83 tuples Erlang.111–114.314.168–171.228 Erlang.141–143 creatorof.309 Io.32–34 Scala.143.147–152 collections.142–145. see Scala scripting.161–166 maps.103–105. Jeremy.318 Tregunna.146–147 types.167–168.269. see Haskell statictyping Haskell.20.155–166 concurrency.133 sequences.178 expressions.317–318 Anyclass.139.157–158 slotsinobjects.32–34 weaknessesof.151 tuples.309 Ruby.145–147 recursion.269 Scala.171–175.320 programmingmodel.Clojure.136–137.177–178 traits.135–180 actors.157–158 strengthsof.170.165 domain-specificlanguageswith.167–168. 320 vectors.57 S Scala.108 threadstate.141 syntacticsugar.178 Scissorhands.141–143 foldLeftmethod.151 transactionalmemory.164 functions.Scala.S CALA Y ODA typingmodel.Ruby.231–232 W X Y Y o d a .194 Haskell.161–163 Javaand.Prolog.262 traits.179 strings Clojure.160 immutablevariables.143.149 classes.Clojure.18 Clojure.160–166 higher-orderfunctions.Scalaand.

andPreventBugsinY o u r Code DeployingRailsApplications:AStep-by-Step Guide DesignAccessibleW e bSites:36Keysto CreatingContentforAllAudiencesand Platforms DesktopGIS:MappingthePlanetwithOpen SourceTools DevelopingFacebookPlatformApplicationswith Rails Domain-DrivenDesignUsingNakedObjects EnterpriseIntegrationwithRuby EnterpriseRecipeswithRubyandRails EverydayScriptingwithRuby:forTeams. Title AdvancedRailsRecipes:84NewW a y stoBuild StunningRailsApps AgileCoaching AgileRetrospectives:MakingGoodTeamsGreat AgileW e bDevelopmentwithRails.andY o u ExpressionEngine2:AQuick-StartGuide FXRuby:CreateLeanandMeanGUIswithRuby FromJavaToRuby:ThingsEveryManager ShouldKnow Year 2008 2009 2006 2009 2010 2005 2006 2010 2008 2009 2005 2009 2008 2007 ISBN 9780978739225 9781934356432 9780977616640 9781934356166 9781934356517 9780976694021 9780976694076 9781934356302 9781934356104 9781934356326 9780974514079 9781934356289 9780978739201 9781934356029 Pages 464 248 200 784 300 192 304 450 200 256 208 232 280 336 2008 2008 2009 2006 2008 2007 2010 2008 2006 9781934356067 9781934356128 9781934356449 9780976694069 9781934356234 9780977616619 9781934356524 9781934356074 9780976694090 368 200 375 360 416 320 250 240 160 Continuedonnextpage .Repair. Testers. The following are in print as of August 2010.com fornewertitles.Python. be sure to check our website at pragprog.ThirdEdition BeginningMacProgramming:Developwith Objective-CandCocoa BehindClosedDoors:SecretsofGreat Management BestofRubyQuiz CocoaProgramming:AQuick-StartGuidefor Developers CoreAnimationforMacOSXandtheiPhone: CreatingCompellingDynamicUserInterfaces CoreData:Apple’sAPIforPersistingDataon MacOSX DataCrunching:SolveEverydayProblems usingJava.ourtitlesareheretohelpyoustayontopof your game.ThePragmaticBookshelf AvailableinpaperbackandDRM-freeeBooks.andMore DebugIt!Find.

Deploy.Title GISforW e bDevelopers:AddingWheretoY o u r W e bApplications GoogleMapsAPI.andMonitorJavaApplications PragmaticThinkingandLearning:RefactorY o u r W e t w a r e PragmaticUnitTestinginC#withNUnit PragmaticUnitTestinginJavawithJUnit PragmaticV e r s o inControlUsingGit PragmaticV e r s o inControlusingCVS PragmaticV e r s o inControlusingSubversion ProgrammingClojure ProgrammingCocoawithRuby:Create CompellingMacAppsUsingRubyCocoa Year 2007 2006 2009 2008 2010 2006 2009 2009 ISBN 9780974514093 PDF-Only 9781934356463 9780978739294 9781934356562 9780976694052 9781934356265 9781934356456 Pages 275 83 200 264 320 240 280 350 2009 2007 2009 2008 2010 2009 2006 2007 2009 2009 2006 2004 2008 2007 2003 2008 2003 2006 2009 2009 9781934356364 9780978739249 9781934356296 9781934356111 9781934356470 9781934356401 9780977616664 9780978739287 9781934356500 9781934356272 9780974514086 9780974514031 9781934356050 9780977616671 9780974514017 9781934356159 9780974514000 9780977616657 9781934356333 9781934356197 240 360 200 568 240 260 240 320 144 350 208 176 288 176 160 200 176 248 304 300 Continuedonnextpage .Android:IntroducingGoogle’sMobile DevelopmentPlatform InterfaceOrientedDesign LandtheTechJobY o u Love LanguageImplementationPatterns:CreateY o u r OwnDomain-SpecificandGeneralProgramming Languages LearntoProgram.V2:AddingWheretoY o u r Applications Grails:AQuick-StartGuide GroovyRecipes:GreasingtheWheelsofJava Hello.2ndEdition ManageIt!Y o u r GuidetoModernPragmatic ProjectManagement ManageY o u r ProjectPortfolio:IncreaseY o u r CapacityandFinishMoreProjects MasteringDojo:JavaScriptandAjaxToolsfor GreatW e bExperiences MetaprogrammingRuby:ProgramLiketheRuby Pros ModularJava:CreatingFlexibleApplications withOSGiandSpring NoFluffJustStuff2006Anthology NoFluffJustStuff2007Anthology PomodoroTechniqueIllustrated:TheEasyW a y toDoMoreinLessTime PracticalProgramming:AnIntroductionto ComputerScienceUsingPython PracticesofanAgileDeveloper PragmaticProjectAutomation:HowtoBuild.

Title ProgrammingErlang:SoftwareforaConcurrent W o r d l ProgrammingGroovy:DynamicProductivityfor theJavaDeveloper ProgrammingRuby:ThePragmatic Programmers’Guide. Hints.NETMVC TextMate:PowerEditingfortheMac TheDefinitiveANTLRReference:Building Domain-SpecificLanguages ThePassionateProgrammer:Creatinga RemarkableCareerinSoftwareDevelopment ThoughtWorksAnthology UbuntuKungFu:Tips.9:ThePragmatic Programmers’Guide ProgrammingScala:TackleMulti-Core ComplexityontheJavaVirtualMachine Prototypeandscript.NETDevelopers RailsforJavaDevelopers RailsforPHPDevelopers RapidGUIDevelopmentwithQtRuby ReleaseIt!DesignandDeployProduction-Ready Software SQLAntipatterns:AvoidingthePitfallsof DatabaseProgramming ScriptedGUITestingwithRuby ShipIt!APracticalGuidetoSuccessfulSoftware Projects Stripes.andHacks W e bDesignforDevelopers:AProgrammer’s GuidetoDesignToolsandTechniques iPhoneSDKDevelopment NeverKnew Year 2007 2008 2004 2009 2009 2007 2006 2008 2007 2008 2005 2007 2010 2008 2005 2008 2010 2007 2007 2009 2008 2008 2009 2009 ISBN 9781934356005 9781934356098 9780974514055 9781934356081 9781934356319 9781934356012 9780977616602 9781934356203 9780977616695 9781934356043 PDF-Only 9780978739218 9781934356555 9781934356180 9780974514048 9781934356210 9781934356531 9780978739232 9780978739256 9781934356340 9781934356142 9781934356227 9781934356135 9781934356258 Pages 536 320 864 960 250 448 350 300 336 432 83 368 352 192 224 375 296 208 384 200 240 400 300 576 .SecondEdition ProgrammingRuby1..us:Y o u JavaScriptCouldDoThis! RailsRecipes Railsfor..andJavaW e bDevelopmentIsFun Again Test-DriveASP.aculo. Tricks.

Y o ucanuseittowrite traditional.95 http://pragprog.modern.multi-paradigm languagefortheJVM. Programming Scala: Tackle Multi-Core Complexity on the Java Virtual Machine V e n k a tSubramaniam (250pages) ISBN :9781934356319.highly concurrentapplicationsontheJavaPlatform.multicore systems. Programming Erlang: Software for a Concurrent World JoeArmstrong (536pages) ISBN :1-934356-00-X.$36.95 http://pragprog.But youcanalsoleverageitshigherlevelofabstraction totakefulladvantageofmodern.ErlangandScala ProgrammingErlang Learnhowtowritetrulyconcurrentprograms— programsthatrunondozensorevenhundredsof localandremoteprocessors.imperative.$34.com/titles/vsscala .com/titles/jaerlang ProgrammingScala Scalaisanexciting.Seehowtowrite high-reliabilityapplications—eveninthefaceof networkandhardwarefailure—usingtheErlang programminglanguage. ProgrammingScala willshowyouhowto usethispowerfulfunctionalprogramming languagetocreatehighlyscalable.object-orientedcode.

Presentedastwo-pagetasks.amodernLispdialect.theseJavaScripttips willgetyoustartedquicklyandsaveyoutime.$25. andtoolkits.$32.infrastructures.com/titles/pg_js ProgrammingClojure Clojureisageneral-purposelanguagewithdirect supportforJava.com/titles/shcloj . ProgrammingClojure showsyouhowtowriteapplicationsthathavethe beautyandeleganceofagoodscriptinglanguage.Nowyoucan writebeautifulcodethatrunsfastandscaleswell.dynamiclanguage witharichecosystemofprofessional-grade developmenttools.andamodern.00 http://pragprog.frameworks. concurrency-safefunctionalstyle. Programming Clojure StuartHalloway (304pages) ISBN :9781934356333.JavaScriptandClojure PragmaticGuidetoJavaScript JavaScriptisnowapowerful.Y o ucan’taffordtoignoreit–thisbook willgetyouuptospeedquicklyandpainlessly.and supportinboththelanguageanddatastructures forfunctionalprogramming. Pragmatic Guide to JavaScript ChristophePorteneuve (150pages) ISBN :978-1934356-67-8. thepowerandreachoftheJVM.95 http://pragprog.

eitherdirectly orthroughamappinglayer.$34.Thisbookshowsyou allthecommonmistakes.What’smore.givingyouthecore conceptsandprinciplesofdevelopmentincontext soyouwillbereadytobuildtheapplicationsyou’ve beenimagining.95 http://pragprog.MacandSQL BeginningMacProgramming Aimedatbeginningdeveloperswithoutprior programmingexperience.workingexamples.as wellastheiPhoneandiPod.com/titles/bksqla .andthenleadsyou throughthebestfixes.itshowsyou what’s behind thesefixes.ButmostoftheSQL thatgetsusedisinefficient.ItintroducesyoutoObjective-C andtheCocoaframeworkinclear.$34. thenchancesareyou’reusingSQL.Takesyouthrough concrete. SQL Antipatterns: Avoiding the Pitfalls of Database Programming BillKarwin (300pages) ISBN :978-19343565-5-5.95 http://pragprog. Beginning Mac Programming: Develop with Objective-C and Cocoa Tim Isted (300pages) ISBN :978-1934356-51-7.com/titles/tibmac SQLAntipatterns Ifyou’reprogrammingapplicationsthatstoredata.soyou’lllearnalotabout relationaldatabasesalongtheway.and sometimesjustplainwrong.hardtomaintain. easy-to-understandlessons.anddemonstrateshow youcanusethemtogethertowritefortheMac.

9(ThePickaxefor1.9) ThePickaxebook. •Up-to-dateandexpandedforRubyversion1.com/titles/ruby3 UsingJRuby Rubyhastheheart.andmethods •Complete descriptionsofallstandardlibraries •Learnmore aboutRuby’swebtools.Ola Bini. Using JRuby: Bringing Ruby to Java CharlesONutter.andJavahasthereach.$34.NickSieger.JRubyhas Ruby’sexpressivenessandwidearrayof open-sourcelibraries—it’sanevenbetterRuby.unittesting.theentireJRubycoreteam helpsexperiencedJavadevelopersandRubyists exploittheinteroperabilityoftheirrespective languages.$49.W t i hJRuby.modules.and programmingphilosophy Programming Ruby 1.namedforthetoolonthecover.you’llbesurprisedat what’snowpossible. isthedefinitivereferencetothishighly-regarded language.RubyandRubyontheJavaVM ProgrammingRuby1.95 http://pragprog.youcanbringthebestofRubyintothe worldofJava.W t i h JRuby.W r t ie nin100%Java.9 •Completedocumentationofallthebuilt-in classes.andIanDees (300pages) ISBN :978-1934356-65-4.9: The Pragmatic Programmers’ Guide DaveThomaswithChadFowlerandAndyHunt (992pages) ISBN :978-1-9343560-8-1.ThomasEnebo. W t i h UsingJRuby .com/titles/jruby .95 http://pragprog.

unittestingwithmock objects.95 http://pragprog.includingmeta programming.$34.you’llseehowtouseGrailsby iterativelybuildingaunique. Programming Groovy: Dynamic Productivity for the Java Developer V e n k a tSubramaniam (320pages) ISBN :978-1-9343560-9-8. Grails: A Quick-Start Guide DaveKlein (200pages) ISBN :9781934356463.workingapplication. Y o u l’seehowtouseGroovytodoadvanced programmingtechniques.functioningwebsite.In Quick-StartGuide .you’llhavebuiltand deployedareal.$32.processingXML.95 http://pragprog.com/titles/vslg Grails Grailsisafullstackwebdevelopmentframework thatenablesyoutobuildcompleteweb applicationsinafractionofthetimeandwithless Grails:A codethanotherframeworks.builders.GroovyandGrails ProgrammingGroovy ProgrammingGroovy willhelpyoulearnthe necessaryfundamentalsofprogramminginGroovy.workingwithdatabases andcreatingyourowndomain-specificlanguages (DSLs). Bythetimewe’redone.com/titles/dkgrails .

com proposals@pragprog. participate in our mailing list.com 1-800-699-PROG(+19198473884) .com/news Checkoutthelatestpragmaticdevelopments.com academic@pragprog.perhapsyou’dliketohaveapapercopyofthebook. the Pragmatic Programmers willbetherewithmoretitlesandproductstohelpyoustayontopofyourgame. join our online discussions.com/updates Benotifiedwhenupdatesandnewbooksbecomeavailable.too! Registero f rUpdates http://pragprog.com/titles/btlang.com/catalog support@pragprog.ThePragmaticBookshelf The Pragmatic Bookshelf features books written by developers for developers.andotherresources. interact withourwiki. ContactUs OnlineOrders: CustomerService: Non-EnglishV e r s o in s : PragmaticTeaching: AuthorProposals: Contactus: www.com translations@pragprog.com/community Read our weblogs.Comegiveusfeedback.newtitlesandotherofferings. BuytheBook IfyoulikedthiseBook.com/titles/btlang Sourcecodefromthisbook. JointheCommunity http://pragprog. The titles continuethewell-knownPragmaticProgrammerstyleandcontinuetogarnerawardsand rave reviews. NewandNoteworthy http://pragprog. Vs it UsOnline SevenLanguagesinSevenW e e k s http://pragprog.errata. As development gets more and more difficult.pragprog.It’savailable forpurchaseatourstore: pragprog.andbenefitfromtheexperienceofotherPragmaticProgrammers.

Sign up to vote on this title
UsefulNot useful