The Proper Pronunciation of Clojure’s Assoc

Published on:
Tags: All, Clojure

Sometimes I pause before talking to someone about Clojure code. Not because I am unsure of the code, but because I am unsure of how to pronounce the code. The particular code in question is Clojure’s assoc. I have heard it pronounced two ways. One is “assosh”, the other is “assok”. So, to determine it, I decided to conduct a scientific poll of the Clojure community.

I posted the poll on twitter to the Cojure community who follow me. The control group poll was not viewed by those who do not follow me, and/or, are not on twitter.

The results were startling.

  • assosh – 10
  • assok – 8
  • assose – 2
  • Jeremy – 1
  • asoaksh – 1

The community is clearly deeply divided on this important question.

After sifting through the raw data, I remembered my statistical analysis and threw out the extremes.

The conclusion was still a stark reality.

We do not as a community know how to pronounce assoc.

Solution

I can only see one way forward. We must address this as a community. I propose that the community documentation of Clojure Docs and Grimoire modify their sites to include audio pronunciation like this.

Remember, I’m pulling for you. We are all in this together.

Clojure X-Men

Published on:
Tags: All, Clojure

Nobody knows how it happened. Some people think it was due to the rapid expansion and adoption of Clojure. Other people say that the language itself was caused by something deeper and more magical. No one knows for sure. All that we really know is that people starting being born with extraordinary powers. Powers that no human had had before. They were strange and unique to each person they touched. The only thing that they all had in common, was that each was an aspect of the Clojure programming language.

Luke (AKA Lazy Luke)

Luke was a teenager when his powers came to him. His mother always complained that he was lazy. It was true, he did prefer to sleep until noon. He also had a habit of putting everything off to the last minute, like saving all his papers for the night before they were due. One day, though, he noticed something very strange. He could start to see the future. Well not really “see” it. But he could see the infinite possibilities of the future. Not very far into the future, but enough. It was a few milliseconds at first. But now it was up to a full second. He checked the Clojure Docs as soon as he realized his gift. It was lazy evaluation and power to deal with infinite sequences.

Spress

Spress, whose real name is Emily, came into her power early. She was only 5 years old. Her mother had taken her to a farm to visit with the animals. Her mother had pointed at the cow and told her daughter that it said “Moo”. Then, at the horse, saying “Neigh”. Spress smiled and pointed at a bucket and said “cow”. Her mother shook her head at her, but Spress only smiled bigger. She said “cow” again. Then, suddenly, the bucked went “Moo”. She was immediately taken to the Clojure X-Men school, where they identified her power as protocols. She trained her power and now is so good at solving the “expression problem”, she is known as “Spress”.

Multi

Nobody knows Multi’s background. He came to notice in his early twenties with his powers. Ordinary humans process sensory input, (like sight, touch, and sound), in an asynchronous fashion. However, when it gets processed in the brain, it runs into a single pipeline bottleneck – consciousness. Multi’s power is that he can concurrently process his higher level consciousness and reasoning to all this sensory input. The result is that he can move, think, and perform super fast and in a super smart way. He got the power of Clojure’s concurrency.

Dot

Dot always had a way with animals. She had many pets growing up. Later, she would go into the forest and the animals would seek her out. She would be found resting by a tree surrounded by deer and birds. One time, on her walk, she fell down a ditch and had her leg trapped under a log. Her mother arrived, after searching for her, to see a Bear reach down and gently remove the log. She stood dumbfounded, as her daughter thanked the bear and it nodded in reply as it turned away. She could talk with animals effortlessly. She had the power of Clojure’s Interop.

Bob

Bob is the leader of the Clojure X-Men. He seeks out people with the power of Clojure and helps train and educate them. He also is the most powerful. He can come into any argument, problem, or challenge and immediately separate out what is most important to focus on. He always knows the right thing to do, without getting bogged down in unnecessary details . His power is Clojure’s simplicity.

There might be others out there, we don’t know. We can only hope, that they are found by Bob and the Clojure X-Men and use their powers for good.

Love Songs Through History and Why You Should Create

Published on:
Tags: All

The Earliest Known Love Song

The earliest known love song was found in an Egyptian tomb. The fragment found in the 4,300 year old tomb read:

I love and admire your beauty. I am under it.

Medieval Love Songs

Moving forward in history to Medieval times, there are many examples of love songs. One of them from a great composer in the 14th century, named Guillaume de Machaut:, went something like this:

You are the true sapphire
that can heal and end all my sufferings,
the emerald which brings rejoicing,
the ruby to brighten and comfort the heart.

Love Songs from this Summer

Love songs abound on the radio and internet today. One was released by Coldplay recently, called “A Sky Full of Stars”. The lyrics go something like this:

Cause you're a sky
Cause you're a sky full of stars
I'm going to give you my heart
Cause you're a sky
Cause you're a sky full of stars
And cause you light up the path

Why Create?

I have nothing to say that has not been said

These are the whispering excuses that I hear in the back of my head when I sit down at a blank text editor:

  • Someone has already said this.
  • Someone has already built this algorithm.
  • Someone has already built this library.
  • I have nothing to say that has not been said before.

But it has not been said by you.

Love is a universal human emotion. We have evidence that people have been writing about it and singing about it for at least 4,000 years.

Hasn’t everything already been said about it?

No.

We still want to hear it again. We still want to hear it new, said by another. It means something slightly different, feels different when said again by someone else with different experiences, from a different life, from a different perspective..

The same goes for your writing, your code, your library, and your creation.

So open up your favorite editor and brush aside your fears. It is a blank canvas, ready for your thoughts and code.

Say it loud

Say it strong

Create

Don’t worry if it has been said before

It is new because it is said by you

A Taste of the Star Programming Language

Published on:
Tags: All, Star

A while ago, I was exploring creating a programming language with Instaparse. I ended up exploring some concepts of Speech Acts proposed by John McCarthy by creating my first toy language called Babar. Shortly after posting a blog about it, I got an email from someone saying that I might be interested in a full blown, real programming language that also incorporated Speech Acts. I happily started composing an reply to the email that started off with

That is so cool! ...

Then I realized that the author of the email and language was none other than Frank McCabe, one of the designers of the Go! programming language (not to be confused with Google Go). My brain froze while it was thinking

"OMG!!!! Frank McCabe, a real language designer, just emailed me!".

This unfortunately, made the rest of my email reply sound something like this

Frank,
That is so cool!  herp derp derp Speech Acts herp derp John
McCarthy derp...

His programming language is the Star Programming Language. It was originally developed for use at a company that he worked at called Starview. It has since been open sourced and moved to git. I finally had a bit a spare time and I had been itching to give Star a look. To my pleasant surprise, despite my initial fumbling email impression, Frank was open a friendly to get me started in it. I have only scratched the surface in exploring the language, but I wanted to share my initial impressions, as well as point you to some beginner katas that I put together, so that you could join in the fun.

Crash Overview

Star is a strongly typed, functional language. It is not a pure functional language because is allows assignment and stateful objects, but the language is designed in a way that immutable functional programming is encouraged. The feel of the language is concise but human readable.

Star is a coherent, general-purpose programming language that
combines elements from a wide variety of existing languages as
well as adding innovative elements of its own. Star inherits func-
tional programming in general, a Haskell-style type system, an F#-
style monad for parallel computations, and Concurrent ML for or-
chestrating concurrent and parallel applications.

Feel different on the Java platform: the star programming language dl.acm.org/…

Hello World

The best way to get a feel for it is to look at a few examples. Of course, let’s start off with Hello World.

1
2
3
main() do {
  logMsg(info, "Hello World");
}

Another way of doing our Hello World is in a worksheet. This feature is still in the works, but it will likely turn into a replacement for a REPL, being integrated into the editor. The import statement will also soon not be required. But a nice feature of using the worksheeet is that is a combined module and transcript of the session.

1
2
3
4
5
import worksheet

worksheet{
  show "hello world"
}

Here is what the output looks like:

Jun 11, 2014 11:21:09 AM  
INFO: "hello world" -> "hello world" at 4
info: execution took 0.053684428

Pattern Matching

Let’s take a look at another example. This time a naive fib function with pattern matching.

1
2
3
4
5
6
7
8
9
10
11
12
import worksheet

worksheet{
  fib(0) is 0
  fib(1) is 1
  fib(n) is fib(n-1) + fib(n-2)

  assert fib(0)=0;
  assert fib(1)=1;
  assert fib(3)=2;
  assert fib(10)=55;
}

Notice how the fib function is defined with pattern matching. Also how the keyword “is” is used instead of an “=” to make the code flow more readable (IMO).

The output of running the program is:

Jun 11, 2014 3:32:38 PM  
INFO: fib(0) = 0 ok at 9
Jun 11, 2014 3:32:38 PM  
INFO: fib(1) = 1 ok at 10
Jun 11, 2014 3:32:38 PM  
INFO: fib(3) = 2 ok at 11
Jun 11, 2014 3:32:38 PM  
INFO: fib(10) = 55 ok at 12
info: execution took 0.039725132

Pattern Matching with Guards

The declaration of pattern matching for functions can also include guards like in this fizzbuzz example

1
2
3
4
5
fizzbuzz has type (integer) => string
fizzbuzz(N) where N%3=0 and N%5=0 is "fizzbuzz"
fizzbuzz(N) where N%3=0 is "fizz"
fizzbuzz(N) where N%5=0 is "buzz"
fizzbuzz(N) default is "$N"

Also note the type declaration. The type declaration is optional. The complier is smart enough to figure it out. Sometimes it is more readable to include the type declaration. But, it can be left out for more concise code.

Cons Lists

One of the important collection types are cons lists. These are lists that you add to the front of and are destructed as the first element and then the rest of the list. To construct a cons list:

1
 testNumbers is cons of {1;2;3;4;5;6;7;8;9;10;11;12;13;14;15}

To use a cons list in a function with pattern matching:

1
2
3
listFizzBuzz has type (cons of integer) => cons of string
listFizzBuzz(nil) is nil
listFizzBuzz(cons(x, xs)) is cons(fizzbuzz(x), listFizzBuzz(xs))

The function listFizzBuzz takes in a list of integers and turns it into a list of strings using the fizzbuzz function. If we evaluate:

1
2
testNumbers is cons of {1;2;3;4;5;6;7;8;9;10;11;12;13;14;15}
result is listFizzBuzz(testNumbers)

The result will look like

1
cons of {"1";"2";"fizz";"4";"buzz";"fizz";"7";"8";"fizz";"buzz";"11";"fizz";"13";"14";"fizzbuzz"}

There are other collection types such as arrays and relations, (which are really cool – you can do queries on them like a database), but I haven’t explored them well enough to really talk about yet.

Actors and Speech Acts

Star has actors that use three Speech Acts: Notify, Request, and Query. The actors themselves can also be concurrent. I explored the Speech Act/ Actor model with an example from John McCarthy’s Elephant 2000 paper, which is a Airline Reservation system.

To use the notify speech act, you need to define what type the notifications are on the actors channel. In my case, the notifications are either going to be a book(string) method, or a cancel(string) method. To book a reservation for a person or cancel it.

1
type tx is book(string) or cancel(string);

The actor is defined using:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
flight((FlightName has type string), (MaxPeople has type integer)) is actor{
    var flightStatus := "open";

    setFlightStatus(s) do { flightStatus := s };

    on book(pname) on Tx do
        logMsg(info,"booking $pname on #FlightName's flight: max #MaxPeople current $(size(plist))");
    on book(pname) on Tx where size(plist) < MaxPeople do
      extend plist with pname;
    on book(pname) on Tx where size(plist) >= MaxPeople do
      logMsg(info, "sorry .. the flight is full");
    on book(pname) on Tx where flightStatus != "open" do
      logMsg(info, "sorry .. the flight is no longer open");

    on cancel(pname) on Tx do
      delete (X where X = pname) in plist;

    getPassengerList has type () => list of string;
    getPassengerList() is plist;
    }

There is some extra things in the code, but for right now, look at the book and cancel methods. These are the functions that will be called when the actor is notified like this:

1
2
3
F is flight("flight123", 5)
notify F with book("Carin") on Tx
notify F with book("Bob") on Tx

To query the actor we use :

1
 x is query F's getPassengerList with getPassengerList()

To use a request with the actor we use

1
 request F's setFlightStatus to setFlightStatus("closed")

Go Explore

I have only scratched the surface of the language, but I have had a great time. I invite you to come take a look.

Warning. Only the brave need apply. There is no StackOverflow. There is no user group or IRC channel yet. These are green fields to be discovered in the Open Source world. If it appeals to you as much as me, jump on in. Here are a few resources to get you going:

  • Star-Lang Katas: Clone the repo or fork the repos. It has a shell script to compile and run the star programs. It also has a emacs mode plugin and a reference pdf. The most important part is that it has a template of katas ready for your to solve. Your challenge: uncomment the assertion and make the code pass. My solutions are in the solutions branch when you are done. If you finish all of them and want more, consider creating some and submitting a pull request :)

  • I mentioned it earlier, but there is a great overview paper on the language itself here.

  • Finally, here is the repo of the Star Language itself https://github.com/fmccabe/star. Checkout out the tests. There are tons of sample star programs that cover the language’s features.

World Domination With Hexapods and Clojure

Published on:

Once you have your hexapod assembled and running using the hand held controller, of course, your thoughts naturally turn to world domination.

The most powerful tool in the world is the Clojure REPL

World domination requires the most powerful tools available. That of course calls for Clojure and the Clojure REPL. I recommend Emacs as the editor of choice of such an endeavor. However, it if you are content with city, state, or single country domination, other editors that support Clojure are also fine.

Connect the XBee to your computer

First, we need to get the computer to talk to the hexapod wirelessly. We can do this with a USB to Serial adapter that uses the paired XBee from the handheld commander.

Take the XBee from the handheld commander

and move it to the USB to serial adapter

Now plug the usb into your computer.

Get your Clojure ready

In your clojure project, the only magic you need is the Serial Port library. Import the library and list your serial ports. Then open the one that shows up for you.

1
2
3
4
5
6
7
8
9
(ns clj-hexapod.core
  (require [serial-port :as serial]))

;; Use this command to see what port your serial port
;; is assinged to
(serial/list-ports)

;; replace the USB0 with whater it shows
(def port (serial/open "/dev/ttyUSB0" 38400))

Since we are going to be talking to the hexapod. We need to send the commands in the same format that it is expecting. Basically, a packet of where the postions of the joystick are, as well as what buttons are pushed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(defn checksum [v]
  (mod (- 255 (reduce + v)) 256))

(defn vec->bytes [v]
  (byte-array (map #(-> % (Integer.) (.byteValue) (byte)) v)))

(defn build-packet [r-vert r-horz l-vert l-horz buttons]
  [255 ;header
   r-vert
   r-horz
   l-vert
   l-horz
   buttons
   0
   (checksum [r-vert r-horz l-vert l-horz buttons])])

(defn send [packet]
  (serial/write port (vec->bytes packet)))

From here, we can simply make functions for the joystick controls to go up and down

1
2
3
4
5
6
7
8
9
10
11
12
13
;;values between 129-254
(defn up [speed]
  "joystick up for speed between 1-100"
  (if (good-range? speed)
    (int (+ 129 (* 125 (/ speed 100.0))))
    CENTER))

;;values between 0 and 125
(defn down [speed]
  "joystick down speed between 1-100"
  (if (good-range? speed)
    (int (- 125 (* 125 (/ speed 100.0))))
    CENTER))

Then we can do things like walk, turn, and change the gait

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
(defn walk-forward [speed]
  "walk forward speed between 1-100"
  (send (build-packet CENTER CENTER (up speed) CENTER 0)))

(defn walk-backwards [speed]
  "walk backwards speed between 1-100"
  (send (build-packet CENTER CENTER (down speed) CENTER 0)))

(defn walk-right [speed]
  "walk right speed between 1-100"
  (send (build-packet CENTER CENTER CENTER (up speed) 0)))

(defn walk-left [speed]
  "walk right speed between 1-100"
  (send (build-packet CENTER CENTER CENTER (down speed) 0)))

(defn turn-right [speed]
  "turn right speed between 1-100"
  (send (build-packet CENTER (up speed) CENTER CENTER 0)))

(defn turn-left [speed]
  "turn left speed between 1-100"
  (send (build-packet CENTER (down speed) CENTER CENTER 0)))

(defn change-gait [gait-key]
  (let [gait-num (gait-key gaits)]
    (send (build-packet CENTER CENTER CENTER CENTER gait-num))))

(defn stop []
  "stop hexapod"
  (send (build-packet CENTER CENTER CENTER CENTER 0)))

You can control it from the REPL with some simple commands

1
2
3
4
5
6
7
8
9
10
11
(walk-forward 20)
(walk-backwards 10)
(walk-right 10)
(walk-left 10)
(turn-right 10)
(turn-left 10)
(change-gait :ripple-smooth)
(change-gait :tripod-normal)
(change-gait :ripple)
(change-gait :amble)
(stop)

If you want to see the code, it is out on github as clj-hexapod. Please keep in mind that it is early days still, and I am still just exploring.

Phoneix Code Firmware

It is worth noting the the above code was meant to run with the default hexapod firmware. That is the “Nuke” firmware. There is another firmware, the Phoenix code, that gives the hexapod more lifelike moves and allows it to twist and shift is rather creepy ways.

I just loaded it on the hexapod yesterday. The commander software changed too, so I will of course need to revisit the code, to add in the new moves. But here is a sneak preview of what it can do:

That is my daughter singing in the background

That’s all for now

I hope I have given you pointers for getting started on your own world domination with Clojure and Hexapods. Remember to practice your laugh …. Muhahaha :)

Walking With Hexapods

Published on:
Tags: All, Robots

Here we see the PhantomX Hexapod thriving in the natural habitat of a cozy, climate controlled, modern house. But there was a time before the hexapod. In particular, there was a time of many hexapod parts and a high level software developer that somehow, despite her natural lack of mechanical skills, managed to bring it to life. This blog post endeavors to chronicle the high and low points of this journey. And perhaps, will make it easier for any other brave souls that would like to bring the Age of Hexapods into their homes.

Oh My! So Many Parts

I wasn’t really mentally prepared for the vast amounts of parts in the kit. Here is a sampling:

  • 18 AX-12A Servos
  • Top/ Bottom Body Plate
  • 20 Brackets
  • Arbotix Board
  • 2 Xbees
  • Lipo Battery & Charger
  • Arbotix programmer
  • 19 Cables
  • 50,000 nuts and screws (Really only about 850 – but you get my point)

First Things First

The very first thing to do is to make sure that you have all the parts. Once I went through the checklist and double counted all my screws, I was relieved to go onto the next task of programming the Arbotix and assign ids to servos and center them. These steps consisted of:

  • Getting the Arduino IDE going
  • Loading the Drivers and Libraries
  • Loading the ROS (Robot Operating System) on the Arbotix Board, so that it could be used to program the servos.

Each of the servos have to be assigned a number. This will let the program know which part of the leg is which, so that it will eventually – hopefully, be able to walk. Once the id is given, a sticker is labeled on the servo for future use. Centering the servos is a VERY important step not to overlook. If you do not center the servos, you will get into the unfortunate circumstance of having to dissemble the robot, cry, recenter the servos, and then reassemble the robot. Please avoid.

Putting It Together

The assembly starts with the feet and legs first. I was so pleased when I got the feet assembled, that I considered knitting little baby hexapod booties.

Next a servo and the tibia is added

Another servo and the tibia and femur is assembled

Finally, another servo and the whole leg is assembled

Newbie Advice

I would like to pause for a minute to share some advice from my trial and errors in assembly thus far:

  • Don’t overtighten screws – More is not better. It makes things like plexiglass frames crack and break.
  • Seating nuts in servos is hard – This isn’t really advice. Just moral support in your struggle. There are 18 servos and up to 20 nuts to seat in each servo.

Assembling the body

The body is where the board, battery and and cables go.

At long last, the legs can be attached to the body – with 120 screws of course.

Round two of Newbie Advice

  • For those who have never stripped wires and attached them to power supplies, like me, please mind that the wires are twisted so that the edges don’t fray out and short out everything requiring you to re-assign all the servos that lost their ids and much unscrewing, crying, and reassembling.
  • When programming the Arbotix board. You must remove the Xbee, or it will not work.
  • Also, did I mention not over-tightening screws? Also, the order in which you tighten the screws is important too. Try to tighten them all loosely in order, so you don’t stress the fiberglass parts and have something like this happen.

It is Alive!

Finally, the moment of truth. The hexapod is assembled and it is time to upload a test check on the board to make sure that everything is working alright.

It lives - the first test check of the PhantomX Hexapod

Walking with Hexapods

The kit comes with a commander that you assemble of course. You can use it to control the hexapod with hand-held joysticks.

The moment of truth, when it finally took its very first steps, and the Age of Hexapods began.

First cautious steps of running the PhantomX Hexapod with wireless controller

Stay tuned for the next post of how to control the hexapod with your Clojure code and loading the Phoenix firmware that gives it a life-like moves

Remembering Jim

Published on:
Tags:

You don’t really understand how important someone is in your life until they are suddenly gone. I have had the honor and privilege of working, playing, and laughing alongside Jim Weirich for the last few years. He was an amazing man. I miss him dearly.

Think

Jim taught us how to think about computer programming. I once had a Physics professor tell me not to worry so much about the formulas and math. The most important thing was how to think. Everything thing after that would naturally fall into place. Jim embodied that philosophy for programming. The languages and algorithms poured almost effortlessly from his masterful fingers. He knew how to think about the problem, observe from a multitude of angles. Finally, bringing his experience, creativity, and humility to bear on it, he would shape it into a beautiful piece of code.

Make

Jim showed us how to make. He was a master craftsman and a maker. The care and joy that infused his work was inspiring. He loved the process of Test Driven Development. Green tests were always a celebration. The surprise of beautiful code emerging from a refactoring was treated as a gift. He is best known for his Rake build tool, but his testing library rspec-given is one that reminds me most of him and the way that he loved to craft code.

Care

Jim showed us how to care. Jim cared deeply about each and every person. While flying his drone in the office hallway, he would wave down a passing building maintenance worker and ask if they wanted to fly it. Over the course of the next few minutes, Jim would put them completely at ease and chat happily with them. He was like that to everyone. In the few days after his passing, many building workers, and people from other offices, that I only ever nodded at in passing, stopped by to give their sincere condolences his loss. He is without a doubt, the kindest person I have ever known. He took great joy in his faith and in his family. He would talk about his family all the time and how much they enjoyed each others company. He is without a doubt, one of the personally richest men I have ever known.

Share

Jim taught us how to share. Jim wanted to share his knowledge. He was a great teacher and presenter. He gave engaging presentations that took people on a journey with him, not only imparting knowledge, but becoming friends with him in the process. He was a pillar in the local Cincinnati technical community. He is the reason why myself and countless others were drawn to Ruby and the Ruby community.

Dream

Jim dreamed with us. He was a creative. He was also a singer, song writer, musician, and artist. He brought that creative spirit, curiosity, and love of learning to the technical world. I will cherish our lunches spent together flying our AR Drones, sometimes crashing them into walls and each other, while trying to find creative ways of controlling them with code. He was just lately exploring with the micro-quadcopters like the Proto-X. We had plans to make all our Spheros, Roombas, big drones, and little drones dance to live coded music. We were both auditing on Autonomous Mobile Robots to see what we could learn to help us with our robot dreams.

I miss him dearly. I will cherish my memories of him and I am so grateful for all the ways he has enriched my life. I will remember that when I dream in code, he is still there with me.

Until that day when we will fly our friendly robots together again.

Hitchhiker’s Guide to Clojure - Part 3

Published on:

Amy and Frank fled down the stairs from her office and met an unexpected obstacle to their exit, a locked door. As they peered out the window, they saw yesterday’s Amy pull up in the parking space, get out, retrieve her laptop, and start to head in the front door.

“Oh good, we can take your car”, said Frank.

Amy took a second to recover from the shock of seeing what her hair really looked like from behind and then asked, “But, how can we get to it? The door is locked, and we can’t go back up to the office… I would meet myself.”

Frank smiled, pulled out the Hitchhiker’s Guide to Clojure and pulled up a page with the heading Locked Doors and Other Small Bothers.

One of the reasons for the surprising success of The Hitchhiker’s Guide to Clojure is helpful advice of on an assortment of practical matters.

Locked doors are a common nuisance in modern times. Fortunately, Clojure provides a very handy function for such occasions, fnil. This commonly overlooked function, takes an existing function and returns a new function that allows you to specify a default for a nil parameter. For example, take this locked door:

1
2
3
4
5
(defn locked-door [key]
        (if key "open" "nope - staying shut"))

(locked-door :key) ;=> "open"
(locked-door nil) ;=> "nope - staying shut"

In this case, the simple application of fnil will help remove this pesky obstacle.

1
2
3
4
(def this-door (fnil locked-door :another-key-that-works))

(this-door :key) ;=> "open"
(this-door nil) ;=> open

Please be advised, that some doors are locked for a good reason. It is left to the user’s discretion. But it is highly recommended in Norway’s moose regions, to think twice.

They unlocked the door and headed for Amy’s car. She couldn’t decide whether she was surprised or not to find her keys in her pocket, so she gave up and just got in instead. After a short drive, they arrived at the zoo and navigated their way through various school groups and arrive at the Aquarium.

Amy at this point, having prided herself on her adaptable nature, was still having trouble processing the latest events. She had discovered that Frank was a Datomic time traveller, the world was made of Clojure, and it was also about to be destroyed in a short future that she just came from. Her rational brain, (which was currently working way too hard), was quite relieved to be distracted by the sight of two really adorable otters. They were floating contentedly around the pool, occasionally stopping to crack an Abalone shell on their fuzzy tummies.

Her rational brain, after having a nice breather, finally re-asserted itself and made Amy ask Frank:

“Why are we here?”

“Otters are the front-line Chrono-guards, of course.”

He went on to explain that otters are tasked with the important job of keeping a close watch on human civilization and making critical, minor adjustments to keep things on an even track. All those nature videos of otters cracking shells with rocks? They are really evaluating Clojure expressions crucial to our way of life. Most of the time, they prefer to do their work remote. They find floating on their backs in the peaceful waters the most productive work environment. However, sometimes they will construct zoos or aquariums, when their work requires them to keep a closer watch on some areas. In times of great need, they might even take a human form for a short while. Recently, one of their agents was inadvertently exposed and required a few extra Abalone shells to straighten out.

Frank opened his pack and handed his evaluator to Amy to hold while fished out four mini-marshmallows. He gave two to Amy and then proceeded to put one in his ear and the other in his mouth. More remarkably still, he appeared to be speaking with the otters.

Mini-marshmallows are the best way to create portable Clojure core.async channels that won’t melt in your hands.

To construct a channel simply use chan

1
(def talk-to-otters-chan (chan))

Channels by default are unbuffered, which keeps them at the mini-marshmallow size. It requires a rendezvous of a channel producer and consumer to communicate. In the case of otters, someone to talk to the otters and the otters, themselves, to listen. Be advised that with a regular blocking put >!!, the main thread will be blocked. That is, if you try to speak to the otter, you will be stuck there until it gets around to listening. This isn’t the best case for the talker if the otter was busy, so one approach would be to use a future to talk to the otter with a blocking put >!!.

1
2
(future (>!! talk-to-otters-chan "Hello otters.")) ;=>#<Future@3c371c41: :pending>
(<!! talk-to-otters-chan) ;=> "Hello otters."

One could also use a buffered channel, but that increases the size of the marshmallow.

1
2
3
4
5
6
(def talk-to-otters-chan (chan 10)) ;;create channel with buffer size 10
(>!! talk-to-otters-chan "Hello otters.") ;=> nil
(>!! talk-to-otters-chan "Do you know anything about the world ending?") ;=> nil

(<!! talk-to-otters-chan) ;=> "Hello otters."
(<!! talk-to-otters-chan) ;=> "Do you know anything about the world ending?"

The best way to conserve space and time is to use asynchronous communication with go blocks that wont’ block the threads. Inside these go blocks one can use regular non-blocking puts >! and gets <!.

1
2
3
4
5
6
7
8
9
10
11
(def talk-to-otters-chan (chan))
(go (while true
      (println (<! talk-to-otters-chan))))
(>!! talk-to-otters-chan "Hello otters")
(>!! talk-to-otters-chan "Do you know anything about the world ending?")
(>!! talk-to-otters-chan "Also, you are really fuzzy and cute.")

;; (This prints out in the REPL as you talk to the otters)
Hello otters
Do you know anything about the world ending?
Also, you are really fuzzy and cute.

This compact, lightweight, and asynchronous method of communication is well suited to conversations and messaging of all sorts, including conversing with human, animals, and other Clojure-based life forms.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(def talk-chan (chan))
(def listen-chan (chan))
(go (while true
      (println (<! listen-chan))))
(go (while true
      (>! listen-chan
          (str "You said: "(<! talk-chan)
                " " "Do you have any Abalone?" ))))
(>!! talk-chan "Hello otters")
(>!! talk-chan "Do you know anything about the world ending?")
(>!! talk-chan "Also, you are really fuzzy and cute.")

;; (This prints out in the REPL as you talk to the otters)
You said: Hello otters Do you have any Abalone?
You said: Do you know anything about the world ending? Do you have any Abalone?
You said: Also, you are really fuzzy and cute. Do you have any Abalone?

Amy put one of the mini-marshmallows in her ear. She immediately began to hear the conversation that Frank was having with the otters.

“But who would want to destroy the entire world? That is really kinda over-board.”

“I don’t really know, but there was someone on Galactic Hacker News the other day that was quite tiffed over the idea that Clojure was considered a Lisp.”

Amy reached to put the other marshmallow in her mouth to ask a very important question. But unfortunately, as she moved her hand, she accidentally pushed the big red Source button on the evaluator. Suddenly, she and Frank were swept up in a vortex that spun them around and sucked them down into the ground.

Hitchhiker’s Guide to Clojure - Part 2

Published on:

Amy and Frank were hurtled quite rapidly through time and space after attaching themselves to a transaction headed through the Datomic Transactor. From there things slowed down a bit, then took a sharp left and ricocheted off again with incredible speed until they landed in another Datomic Peer, and finally appeared in the same room. Amy was quite startled by the anti-climatic nature of the whole dematerializing and rematerializing in the same exact spot, and didn’t really know what to do next. She surveyed her office and found it exactly the same, except for two distinct details. For one, the pistachio shells had disappeared, and for another, the date on the computer showed yesterday at 8:00 am. She tried to connect these facts rationally with the pistachios in her pocket and finally said,

“I am about to come into work.”

Frank, who was busily hunting through his blue zippered pack around his waist, looked up briefly.

“Well, we better get out of here then, I only have a blue fanny pack.”

The Hitchhiker’s Guide to Clojure explains that the “fanny pack”, or “bum bag”, is the symbol of a licensed Chrono-agent. The rank of the Chrono-agent can be clearly determined by its color on the ROYGBIV scale.

The origins of this licensing method can be traced to an embarrassing incident in human history known as “The Great Flood”. A junior Chrono-agent was trying to increase the yield of a tomato crop during a dry spell and was trying to do the following recursive function in his evaluator:

1
2
3
4
5
6
7
8
9
10
11
12
(defn rain [days]
  (when (pos? days)
    (println (str "Rain: " days))
    (rain (dec days))))

(rain 5)
;;Output
;;  Rain: 5
;;  Rain: 4
;;  Rain: 3
;;  Rain: 2
;;  Rain: 1

Unfortunately, he made the rookie mistake of forgetting to decrement the days before passing it to the recursive function.

1
(dec 5) ;=> 4

The result of which was severely overwatered tomatoes.

1
2
3
4
5
6
7
8
9
10
11
12
(defn rain [days]
  (when (pos? days)
    (println (str "Rain: " days))
    (rain days)))

(rain 5)
;;  Rain: 5
;;  Rain: 5
;;  Rain: 5
;;  Rain: 5
;;  Rain: 5
;;  ...(you get the idea)

It is interesting to note that he could he written the same function with a recur instead.

1
2
3
4
5
6
7
8
9
10
11
12
(defn rain [days]
  (when (pos? days)
    (println (str "Rain: " days))
    (recur days)))

(rain 5)
;;Output
;;  Rain: 5
;;  Rain: 5
;;  Rain: 5
;;  Rain: 5
;;  Rain: 5

That would have had the nice effect of not consuming the stack, (which is fabulous for constructing those lovely fibonacci sea shells for beach vacations), but without decrementing the parameter in the recursive call, it wouldn’t have really helped.

A senior Chrono-agent was dispatched to sort out the mess. By the time he got there and stopped the rain, there was not much left to work with. Thankfully, he was quite versed in lazy and infinite aspects of Clojure. For instance, take this vector of 2 chickens:

1
[:hen :rooster]

It can be transformed into an infinite lazy list of chickens by using cycle.

1
(cycle [:hen :rooster])

What really set the senior Chrono-agent apart from his junior colleague, was that he did not put the infinite sequence in the evaluator. If he had, there would have been another embarrassing incident in human history, this time involving an over-abundance of poultry. Instead, he used take to get the first n infinite chickens.

1
2
3
4
5
(take 5 (cycle [:hen :rooster]))
;;=> (:hen :rooster :hen :rooster :hen)
(take 10 (cycle [:hen :rooster]))
;;=> (:hen :rooster :hen :rooster :hen :rooster :hen :rooster :hen
:rooster)

After that, the council of Chrono-agents, decided to license evaluator use. Low-level recursion requires the 2nd highest indigo level rank. The highest violet rank, of course, belonging only to the Macro Masters. All lower levels are required to stick to the safer, higher level abstractions like for, map, or reduce.

Amy was still watching Frank busily rumaging through his pack in the office . Finally he found what he was looking for, his hand emerging triumphantly with a fistful of mini-marshmallows.

“Got it. Come on, let’s go! Someone is trying to destroy the world and we need to see the otters.”