Fun With Clojure(script) - Baconbot 2.0

Posted on Fri 20 November 2015 in Tutorial • Tagged with programming, clojure, clojurescript, reaget, react.js, figwheel, humor, baconbot-seriesLeave a comment

This is the second post in a series of articles about writing my first real application using Clojure. For more information about why I'm doing this or how, please see my first article.

A Slight Change In Direction

I'm really happy with what I've created already. I have the guts of a system that can evaluate a question and then execute a customized response. The system is easy to read and maintain, and it even looks like halfway idiomatic Clojure.

My next steps (according to my earlier post) were to create a decent command-line user interface and integrate TTS. I really wanted to start with TTS, but quickly learned that all of the open source TTS libraries that are written in Java are fairly difficult to install and configure. Hmmm....

Then I had the following conversation with my daughter:

Hey honey! I made a lot of progress on the baconbot app today. Pretty soon you'll have a custom REPL that you can use to enter questions!
A whah? What's mean I can't talk to it?
Ha ha ha! Oh honey, what you're asking for is as crazy as a jetpack! Heck, I can't even make it talk yet.
Oh, uhhhh, that still sounds cool I guess. So what do I push on my iPod to see it?

Obviously I had misunderstood the scope of this project. I was trying to create an app that I could share with one of my buddies in 2007, but what my kids wanted was something, you know, GOOD and EASY to play with. Also, I wanted my 5 year-old son to be able to play around with this app a little bit, so I really needed to make everything much easier.

Then I found the following:

It turns out that TTS and speech recognition are actually built into Chrome already thanks to the Web Speech API [1]. I don't have to install any libraries or configure anything. I can just start making my web browser talk to me today using the a couple lines of Javascript.

Which is super cool but doesn't work at all with plain-old-JVM-powered-Clojure. If I wanted all of this speech-powered awesomeness and the ability to make my app available to everyone in the world by pushing a button then I needed to move all of my code over to a browser.


There are, of course, a couple of caveats as I write this. Not only is this API only supported in Chrome (at the time that I'm writing this), but it doesn't seem to work in every version of Chrome on every platform. For example, a friend of mine had trouble getting it to work on his Surface.

Also, the default voice can really be a crapshoot. On my Debian laptop, the default voice sounds pretty decent. On my Android phone it sounds OK but not great. And on my wife's Macbook, it sounds like a female German villian from a Mel Brooks movie.

Yet Another Tangent On How Great Clojure Is

At this point, if I was developing with pretty much any other language I would be screwed. You just can't jump from one platform (e.g. web client, server, JVM, .Net) to another. If I had written iteration 1 of my app in Python, for example, then I would need to rewrite everything in Javascript or some language built on top of Javascript like Coffeescript [2].

Also, what if you really didn't want to write in plain-old-Javascript? There's a lot of great languages built on top of it that fix some of its warts, but probably none that allow me to "port" most of my Python (or Ruby, or Java, or whatever) code line-for-line.

The good news is that you actually can port a lot of your plain-old-Clojure code to a web browser using Clojurescript. Of course you can't port everything, like any code that relies on a third-party Java library. But you can port code that doesn't rely on a feature that's specific to the JVM.

For example, I'm glad that I didn't spend a bunch of time trying to make something like FreeTTS work with this app, because none of that would have been callable from Clojurescript. But the good news is that I can use Javascript interop with Clojurescript to implement those types of features, just like I would use Java interop from plain-old-Clojure.

But enough origin story - let's actually get started with a simple Clojurescript app.

Choosing My Clojurescript Tools

Living With Fear

No matter how much I do it, I'm always a little gunshy about writing code that runs in a web browser because it used to be [3] really difficult to do. My first exposure to Javascript was when I helped develop a fairly complex web application about 14 years ago and it was just torture compared to using my nifty VB 6 IDE back in cowboy times.

I naturally then assumed that all of the awesomeness that I had grown accustomed to when developing with Clojure (using tools like Leiningen, nREPL and Cider) would disappear as soon as I started developing for the cold, bleak web browser. Heck, does Leiningen even work with Clojurescript? Also, how hard would it be for me to see my code changes in the browser?

My fear is that I would basically spend all of my time doing the following:

  1. Write Clojurescript
  2. Compile (somehow?)
  3. Reload browser
  4. Read crazy Javascript error
  5. Somehow link the Javascript error message to my Clojurescript code
  6. Wonder how I could just write functional Javascript code and skip all of this
  7. Goto 1.

The good news is that not only are the Clojurescript development tools very good, they're some of the best I've ever used for any language.

Embracing Awesomeness

There's actually lots of different ways to start a Clojurescript project and lots of frameworks that can help. I spent a little time trying to find the best of breed tools when I came across the following tutorial:

That looked pretty perfect, so I just decided to copy him. I highly recommend that you also watch his video because he covers a lot of stuff that I don't for people who know a bit more about UX design and React.js.

Actually Coding Something

Ok, I'm pretty sure that I said I would start coding something a few pages ago so let's just get started. I'm assuming that you already have read my first article and installed Leiningen, so let's create our Clojurescript project:

$ lein new figwheel baconbot-dot-js -- --reagent
Retrieving figwheel/lein-template/0.5.0-2/lein-template-0.5.0-2.pom from clojars
Retrieving figwheel/lein-template/0.5.0-2/lein-template-0.5.0-2.jar from clojars
Generating fresh 'lein new' figwheel project.

You should now see something that looks like this:

$ cd baconbot-dot-js && find .

We just create a project using the figwheel profile with the reagent flag. So what does that mean?

First, reagent is the wrapper for React.js so I no longer have an excuse to build lame user interfaces.

Figwheel, on the other hand, isn't a web app framework. It's a tool that auto-compiles your Clojurescript every time you save your cljs file. This might not sound that impressive but you'll soon see how cool it really is.

Speaking of which, let's start our figwheel server:

tom@pam:~/Dev/Clojurescript/baconbot-dot-js$ lein figwheel
Figwheel: Starting server at http://localhost:3449
Figwheel: Watching build - dev
Compiling "resources/public/js/compiled/baconbot_dot_js.js" from ["src"]...
Successfully compiled "resources/public/js/compiled/baconbot_dot_js.js" in 9.794 seconds.
Figwheel: Starting CSS Watcher for paths  ["resources/public/css"]
Launching ClojureScript REPL for build: dev
Figwheel Controls:
          (stop-autobuild)                ;; stops Figwheel autobuilder
          (start-autobuild [id ...])      ;; starts autobuilder focused on optional ids
          (switch-to-build id ...)        ;; switches autobuilder to different build
          (reset-autobuild)               ;; stops, cleans, and starts autobuilder
          (reload-config)                 ;; reloads build config and resets autobuild
          (build-once [id ...])           ;; builds source one time
          (clean-builds [id ..])          ;; deletes compiled cljs target files
          (print-config [id ...])         ;; prints out build configurations
          (fig-status)                    ;; displays current state of system
  Switch REPL build focus:
          :cljs/quit                      ;; allows you to switch REPL to another build
    Docs: (doc function-name-here)
    Exit: Control+C or :cljs/quit
 Results: Stored in vars *1, *2, *3, *e holds last exception object
Prompt will show when Figwheel connects to your application

After opening http://localhost:3449 in my browser my command prompt will be update with the following:

To quit, type: :cljs/quit

Ok, so far, so confusing but still good I think. When I look at my browser, I see "Hello world!". When I look at my src/baconbot_dot_js/core.cljs file I see this:

(ns baconbot-dot-js.core
  (:require [reagent.core :as reagent :refer [atom]]))


(println "Edits to this text should show up in your developer console.")

;; define your app data so that it doesn't get over-written on reload

(defonce app-state (atom {:text "Hello world!"}))

(defn hello-world []
  [:h1 (:text @app-state)])

(reagent/render-component [hello-world]
                          (. js/document (getElementById "app")))

(defn on-js-reload []
  ;; optionally touch your app-state to force rerendering depending on
  ;; your application
  ;; (swap! app-state update-in [:__figwheel_counter] inc)

At this point I would love to tell you that you're going to understand everything about this code by the time I'm done with this article, but I just can't. I'm still learning too, and besides the goal is to build something that I can build on, not a complete app.

There's one more thing we need to do to fully set up our development environment. We're going to be writing a lot of debug messages using the println command, but the output isn't written to your web page - it's written to the Javascript console. To get to this in either Chrome or Firefox, simply type Ctrl-Shift-i to open the developer tools, anad then click on the Console tab.

On the Console tab you should see output like this:

Edits to this text should show up in your developer console.
Figwheel: trying to open cljs reload socket
Figwheel: socket connection established

Ok, still kindof confusing but this is how it's supposed to look. Now let's make a change!

Kicking The Tires (Or Why We're Using Figwheel)


Before we move on I highly recommend that you tile your text editor and web browser so that you can see them both at the same time. Changes in your text editor are going to be pushed to your web page automatically on every save, and that's pretty cool to see.

The really cool thing about figwheel is that it automatically compiles and loads your code when you save your core.cljs file. A cool way to test this is by changing the println statement from this:

(println "Edits to this text should show up in your developer console.")

... to this:

(println "Foobar de rhubarb")

Now, while looking at your web page and your text editor at the same time, save your core.cljs file. If you wait a couple of seconds, you should see a flashing "CLJS" icon in your browser. That's showing you that your code changes are being compiled and loaded on-the-fly.

Next, take a look at your Developer Tools console tab again. You should now see something that looks like this:

Figwheel: notified of file changes
Foobar de rhubarb.
Figwheel: loaded these files

Please note that you did not have to reload the web page to see the "Foobar de rhubarb" statement in your console. If you did reload the page, try making another change to the println statement and then saving your file again. Seriously, it's like magic :-)

This is the main debugging interface that we're going to use for developing this iteration of the baconbot application. Play around with it and make sure that you are comfortable.

Porting The Old Code

Next I'm going to port my old code from the plain-old-Clojure version of this app. Here's what I'm adding:

(defn matches?
  "See if a pattern matches a string"
  [pattern string]
  (boolean (re-find pattern string)))

(def video-url
  "The URL of the \"Rub Some Bacon On It\" video"

(def rules
  "My rule set for baconbot's question"
   {:pattern #"[H|h]ello" :response #(println "Hello!")}
   {:pattern #"[H|h]i" :response #(println "Hello!")}
   {:pattern #"^/video$" :response #(println video-url)}
   {:pattern #"^/sharted$" :response #(println "I think I may have sharted too!")}
   {:pattern #".*" :response #(println "Rub som bacon on it!")}

(defn ask
  "Now with filter!"
  ((:response (first (filter #(matches? (:pattern %) question) rules)))))

This is nearly identical to what I was running in the plain-old-Clojure version of my app. The only difference is that I don't yet know how to play a video in this application without encountering a popup blocker, so I'm just printing the video-url value.

You should have been able to save your code and see it compile successfully in the browser (if you could see both at the same time). Now let's test it with some println statements:

;;; Testing
(ask "My friend went steampunk")
(ask "Hi baconbot!")

In your console, you should see something like this:

Rub som bacon on it!

Hooray, my ask function and all of its supporting functions work!. My "core logic" (for lack of a better word) is intact, even though I ported it to this new platform. Now I just need to worry about the platform-specific stuff.

Adding A User Interface

First, let's change the component we're rendering. Here's what we currently have:

(defn hello-world []
  [:h1 (:text @app-state)])

(reagent/render-component [hello-world]
                          (. js/document (getElementById "app")))

We should change the name of rendered component from hello-world to baconbot to be app-specific. Use this instead:

(defn baconbot []
  [:h1 (:text @app-state)])

(reagent/render-component [baconbot]
                          (. js/document (getElementById "app")))

Next, you may have noticed the weird-looking :h1 property in the baconbot function. This is actually a representation of HTML in Clojure using the hiccup library. It's a little weird at first, but since our needs are pretty simple we don't have to change it much.

Let's add a subtitle to our page like this:

(defn baconbot []
   [:h1 (:text @app-state)]
   [:h2 "Does this work?"]

Please note that I put both headings into a div. I read about some people having issues if they didn't do this.

Next I would like to add a text box and a button. I didn't want to add more clutter to my baconbot function, so I created the following:

(defn question-form
   [:input {:type "text" :id "question" :class "form-control"}]
   [:button {:type "submit"
             :class "btn btn-default"
             :on-click #(ask (.-value (.getElementById js/document "question")))}

(defn baconbot []
   [:h1 (:text @app-state)]
   [:h2 "Does this work"]

Here's what I'm doing. First, I'm creating an input field and a button using hiccup. If you've ever created something like this with HTML before then this should be pretty intuitive.

The anonymous function that we're assigning to the button's on-click event is reading the value property of the document.getElementById method. In this instance, it's getting the value of our input box, which is your question.

Now if everything is working correctly, we should be able to test our ask function without writing println statements in our core.cljs file. Try entering a question into the text field and then pressing the "Ask" button. You should see the response in your Developer Tools console window.

Now that we have the bare minimum that we need to interact with our system, let's make it talk to us.

Making My Web App Talk

Next, I added the following function:

(defn say
  "Talk to me."
  (let [message (js/SpeechSynthesisUtterance. phrase)]
    (.speechSynthesis.speak js/window message)))

First, I'm creating a SpeechSynthesisUtterance object by passing my phrase string to it and the assigning that to messaage. After that I simply pass that message object to the window.speechSynthesis.speak Javascript method.

You can test this super quickly by simply adding something like this to your core.cljs file and saving it:

(say "Up jumped the boogey to the boogey to be")

Now save your file and within a handful of seconds you should automatically hear your browser talking to you!

Now we finally have everything we need to enter a quesion into the browser window and hear a response. All you have to do is make a few simple changes to your rules vector:

(def rules
 "My rule set for baconbot's question"
  {:pattern #"[H|h]ello" :response #(say "Hello!")}
  {:pattern #"^[H|h]i" :response #(say "Hello!")}
  {:pattern #"^/video$" :response #(println video-url)}
  {:pattern #"sharted" :response #(say "I think I may have sharted too!")}
  {:pattern #".*" :response #(say "Rub som bacon on it!")}

Save your file and voila! You can finally start prodding and poking your say function without editing your core.cljs file.

Compilation And Distribution

At this point you may be thinking about sharing your demo with some friends. However, we need a way to turn our code into something that can run as a static site in a web browser. There's a couple of ways to do this with Leiningen, only one of which works for me.

First, let's try it the working way. Navigate to the root of your project and execute this command:

$ lein clean
$ lein cljsbuild once
Compiling ClojureScript...
Compiling "resources/public/js/compiled/baconbot_dot_js.js" from ["src"]...
Successfully compiled "resources/public/js/compiled/baconbot_dot_js.js" in 7.291 seconds.

The results of this compilation are stored in the resources/public directory. On my system, this compiles everything down to 164 files which take up 6.8 MB of total space. Yikes. However, it works like a charm and it's what I'm hosting now on version 2 of my baconbot site

Of course this is not an ideal situation if you're expecting lots of people to have a good experience using your site. The good news is that Leiningen gives you the ability to create a single, small minified Javascript file with all of your code in it. It's super cool because it deletes "dead code" and does lots of other handy things to create a relatively tiny file.

The bad news is that it doesn't work for me for this particular project. But if it did, I would execute the following command to build my site:

$ lein clean
$ lein cljsbuild once min
Compiling ClojureScript...
Compiling "resources/public/js/compiled/baconbot_dot_js.js" from ["src"]...
Successfully compiled "resources/public/js/compiled/baconbot_dot_js.js" in 17.291 seconds.

Now when I look at my resources/public directory, here's what I see:

$ tree
├── css
│   └── style.csspp
├── index.html
└── js
    └── compiled
        └── baconbot_dot_js.js

3 directories, 3 files

Wow, this is significantly better, but it doesn't work in the browser. I'll leave the task of loading this code in a browser and finding the errors as an exercise for the reader.

I definitely want to fix this before I consider this project "done", but for now I'm happy that option 1 works.

The Finished Project

If you want to see what I have at this point, then take a look at this (remember, as of today this only works in Chrome):

Once again, hooray for the bare minimum. Speaking of which, keep the following in mind when running this app:

  • You still need to click on the Ask! button, not just hit return. I'll fix this soon, natch.
  • Your computer needs to interpret the string that we're passing to the ask function and convert that into a music file that it can play. This can take anywhere from a few moments to dozens of seconds, depending on how fast and busy your computer is.
  • This is not intended to win any awards, it's just another step towards awesomeness :-)

What We've Accomplished And What's Next

Whew! This is a long blog post, even by my standards. If you've made it this far, then this is what we've done:

  1. Bootstrapped a sophisticated Clojurescript development environment using figwheel and Leiningen.
  2. Built a simple, web-based UI using the reagent library.
  3. Ported (i.e. copied) the vast majority of our "old", plain-old-Clojure code over to Clojurescript.
  4. Made our web browser actually freakin' talk to us using the Web Speech API and Clojurescript's Javascript interop features.

I'm really happy with how much progress I've made with the second iteration of this project in such a short amount of time, and it really says a lot about how sophisticated the Clojure ecosystem is.

Here's what I would like to work on next:

  • Input - Not only do I want to make the "form" look a lot nicer, but I would also like to make it easier for kids who can't read or type very well to be able to ask questions. Some day I'll hopefully be able to do this with voice recognition, but in the mean time maybe I'll add some buttons that will populate the question box.
  • Launching URL's - I would like to be able to do this again.
  • BDD - I really find that once I implement BDD in a project I wonder how I ever lived without it. Is this even possible with Clojurescript? If not, what are the TDD options?
  • Programming Baconbot With Questions - I would love to be able to add new rules to baconbot from the question interface. I think kids would have fun making baconbot say arbitrary phrases.

Thanks for reading!


[1]In Firefox, speech synthesis will be supported in version 44 and speech recognition will be added in the near future.
[2]I unwittingly just made a really good argument for just writing everything in Javascript since it can run on the client or server (or practically any other platform you can think of). However, I'm not a huge fan of plain-old-Javascript so I'm going to pretend that I didn't.
[3]I start a lot of sentences this way so feel free to imagine me sitting in a rocking chair while winding a watch.

Fun With Clojure - Baconbot 1.0

Posted on Wed 18 November 2015 in Tutorial • Tagged with programming, clojure, java, humor, baconbot-seriesLeave a comment

I'm currently learning Clojure and for my first project I thought it would fun to create my own Baconbot. What's a Baconbot you say?

My kids love this video, so I thought it would be fun to write a program that can "talk" to them like Baconbot. Since I'm new to Clojure, I figured that I would start with something simple that runs in the REPL. My plan is to cover each major iteration with a blog post until I've created something that my kids will actually think is cool. Wish me luck.


Did I mention that this is really similar to my posts on creating a cowsay server and client? If you want to learn the basics of the Unix socket API, then I recommend checking it out.

Iteration 1


First, I need to point out that I'm not creating highly-polished software that can run on any platform at this point. I'm just creating a simple app with which you can interact in a Clojure REPL.

So what does that mean? Well, at this point I'm going to be focusing on the functions that process the data, not the user interface. What I need is some sort of naive "scaffold" that works well enough to provide feedback while I turn it into a "real" program.

I therefore think that I'll consider this iteration "done" when I can ask Baconbot multiple, text based questions and receive multiple, text-based answers (no TTS yet but I really want to add it later).

I'll try my best to make everything as idiomatic and functional as possible because I want to take all of the advantages of this awesome language. However, I'm also content with putting my ego on the bench for a little while and just writing working code that I know has plenty of flaws and anti-patterns. I'm not writing the next Emacs here - I'm having fun and learning something new. Besides, I'm sure that I'll come back later and refactor tons of stuff once I learn more about functional programming. That's kinda the point :-)


For this application I'm going to be using any old text editor and leiningen to keep things somewhat cross-platform and simple. Once you have leiningen installed, create you project like so:

tom@pam:~/Dev/Clojure$ lein new app baconbot2000
Generating a project called baconbot2000 based on the 'app' template.


It's not necessary, but I highly recommend Emacs + Cider. It's an amazing development environment for Clojure. Also check out Chapter 2 of Clojure For The Brave And True for a great quick-start guide.


Next open the baconbot2000/src/baconbot2000/core.clj file in your favorite text editor and add the following:

(ns baconbot2000.core

(defn matches?
  "See if a pattern matches a string"
  [pattern string]
  (boolean (re-find pattern string)))

(defn ask
  "Ask the baconbot whatever you please!"
  (cond (matches? #"[H|h]ello" question) "Hello"
        (matches? #"/sharted"  question) "I think I may have sharted"
        (matches? #"/video"    question) "Go watch the video on Youtube!"
        :else "Rub some bacon on it!")

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (println "Hello, World!"))

For now, we can ignore the auto-generated -main method. What we'll be calling from the REPL is the ask method.

As you can see, the ask method takes just one parameter, question. It then compares that questtion string to a regular expression using the matches? function. The matches? function simply checks a string for a pattern and the returns whether it found one. The cond function is a lot like a case statement in other languages. It runs each test until one of them evaluates to true, and then it returns the associated "result" as a string.


Now we can test our code. Navigate to the root of your baconbot2000 directory and enter the following commands:

tom@pam:~/Dev/Clojure/baconbot2000$ lein repl
nREPL server started on port 55359 on host - nrepl://
baconbot2000.core=> (ask "hi Baconbot")
"Rub some bacon on it!"
baconbot2000.core=> (ask "Oh, uh hello Baconbot")
baconbot2000.core=> (ask "My friend went steampunk!")
"Rub some bacon on it!"
baconbot2000.core=> (ask "/sharted")
"I think I may have sharted"

Hooray! The absolute minimum!


If your code changes and you don't feel like restarting the lein REPL, execute this command in your active REPL session:

baconbot2000.core=> (use 'baconbot2000.core :reload)

Iteration 1.1


There's a few things that I don't like about my silly program so far:

Rule Definition

My pattern/response pairs (which I call "rules") don't feel right for a lot of reasons. First, it doesn't seem like I should have to change the ask method every time I want to add a new rule. I should be able to read them from a config file, or even better I should be able to change them at runtime.

Next, every time I'm working over any set of data in Clojure and that data isn't in a list of some type I feel like I'm doing something wrong. Ideally, I just feel that my rules should be in some sort of list and that list should be processed by a more elegant function.

Response Types

What if I don't want my response to be a string? For example, it would be nice if I could open a browser to the "Rub Some Bacon On It" video instead of printing a string. Or maybe both, who knows? Why assume that I'm going to be returning a string from this function?


Making ask More Functional

Add the following to your core.clj file right above the ask function:

(def rules
  "My rule set for baconbot's question"
   {:pattern #"[H|h]ello" :response "Hello!"}
   {:pattern #"[H|h]i" :response "Hello!"}
   {:pattern #"^/video$" :response "Go watch the video on Youtube!"}
   {:pattern #"^/sharted$" :response "I think I may have sharted too!"}
   {:pattern #".*" :response "Rub som bacon on it!"}

All of my rules are in a list now, which means that I can start to use some of Clojure's really powerful idioms. The only thing missing is a function that will actually process this rule set, so here goes:

(defn ask
  "Now with filter!"
  (println (:response (first (filter #(matches? (:pattern %) question) rules)))))

To understand this function, you first have to look at the filter expression. What we're doing is iterating over every rule in our rules vector. filter then applies the anonymous function that is within the #() form to each rule. This expression simply tests whether the pattern in the rule matches the question.

When filter is done, it returns a list of rule maps that have patterns that matched the question. We then take the first result and then extract the :response section from that. Finally, we print that response to standard out.

That's a mouthful, so let's break it down and see what's happening. First, let's examine the filter expression:

baconbot2000.core=> (filter #(matches? (:pattern %) "my test") rules)
({:pattern #".*", :response "Rub som bacon on it!"})

In this case, the "my test" question only matched the catch-all pattern, #".*". Let's see what happens if my question matches more than one pattern:

baconbot2000.core=> (filter #(matches? (:pattern %) "hello") rules)
({:pattern #"[H|h]ello", :response "Hello!"} {:pattern #".*", :response "Rub som bacon on it!"})

Of course, since we only care about the first match we then pass those results to the first function and then print the response from there.

More Than Just Printing

So now that our rules are stored in a vector, it's also easy to give each rule a custom action. First, change your rules def to look like this:

(def rules
  "My rule set for baconbot's question"
   {:pattern #"[H|h]ello" :response #(println "Hello!")}
   {:pattern #"[H|h]i" :response #(println "Hello!")}
   {:pattern #"^/video$" :response #(browse-url-in-background video-url)}
   {:pattern #"^/sharted$" :response #(println "I think I may have sharted too!")}
   {:pattern #".*" :response #(println "Rub som bacon on it!")}

The add the following between matches? and rules:

(def video-url
  "The URL of the \"Rub Some Bacon On It\" video"

(defn browse-url-in-background
  "Open a URL in a browser without blocking"
  (.start (Thread. #( url))))

... and finally, remove the println function from the ask function:

(defn ask
  "Now with filter!"
  ((:response (first (filter #(matches? (:pattern %) question) rules)))))

My first change was to replace String :response values with anonymous functions in my rules form. So I guess it's not really a "response" any more. Maybe I'll change this later. This makes it easy to define a custom behavior (ooh, that's a much better property name) for each rule.

Next I add a video-url form to keep my code a little cleaner. Since this is probably what I would call a "global constant" in another language I added it here.

Next, I added a function that would open a URL in a browser. The function already does an excellent job of this, but there's one snag - it makes your script block until you close the browser tab. To work around this, I simply wrap that function in an anonymous function and then pass that to a new thread. I know I just made it sound like I know what I'm talking about but I assure you this sort of thinking is all still very new to me :-)

The final change in the ask function is a little tricky. All I did was remove the println function name, so now our :response function is wrapped in another set of parentheses. So I basically changed this:

(println (:response ({:pattern #"[H|h]i", :response #object[baconbot2000.core$fn__8043 0x784bae8d "baconbot2000.core$fn__8043@784bae8d"]})))

... to this:

((:response ({:pattern #"[H|h]i", :response #object[baconbot2000.core$fn__8043 0x784bae8d "baconbot2000.core$fn__8043@784bae8d"]})))

So what does that do? Well, calling a map property like :response like it's a function will return that's map property's value. Since we changed the value of :response to an anonymous function instead of a string, we need a way to execute these functions. Wrapping them in parentheses will do that.

Here's the final version of the script for testing:

(ns baconbot2000.core

(defn matches?
  "See if a pattern matches a string"
  [pattern string]
  (boolean (re-find pattern string)))

(def video-url
  "The URL of the \"Rub Some Bacon On It\" video"

(defn browse-url-in-background
  "Open a URL in a browser without blocking"
  (.start (Thread. #( url))))

(def rules
  "My rule set for baconbot's question"
   {:pattern #"[H|h]ello" :response #(println "Hello!")}
   {:pattern #"[H|h]i" :response #(println "Hello!")}
   {:pattern #"^/video$" :response #(browse-url-in-background video-url)}
   {:pattern #"^/sharted$" :response #(println "I think I may have sharted too!")}
   {:pattern #".*" :response #(println "Rub som bacon on it!")}

(defn ask
  "Now with filter!"
  ((:response (first (filter #(matches? (:pattern %) question) rules)))))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (println "Hello, World!"))


All right, let's try this out again. Make sure that you the (use 'baconbot2000.core :reload) command from above to refresh your code in the lein REPL.

baconbot2000.core=> (ask "Hi baconbot!")
baconbot2000.core=> (ask "I'm an adult with braces")
Rub som bacon on it!
baconbot2000.core=> (ask "/video")

The last "/video" command launches the video in my default browser.

What's Next?

I feel like this is a decent start on the guts of my app, but of course there's a lot more that I want to do eventually:

  • Add my own REPL interface that can be invoked from the command line.
  • Speech synthesis/TTS
  • A Javascript version using Clojurescript

I hope I was able to help a few other people get started with Clojure. Thanks for reading!

Connecting To An SSH Tor Hidden Service

Posted on Tue 06 October 2015 in Tutorial • Tagged with technology, tor, sshLeave a comment


This is a cleaner version of my tor related notes from this page, which also shows you how to set up SSH as a hidden service on a Debian server. Also, I'm happy to plug my torssh puppet module which also will help you set up a hidden service.


This tutorial shows you how to connect to an SSH service exopsed as a hidden service using Tor using an SSH client. It is Debian-specific, but the instructions should mostly work on all Unix-like systems (including OS X).


In addition to an SSH package (like openssh) you also need to install the connect-proxy package. This package is required to proxy your request through the Tor network.

If you're using Debian then it's just this easy:

$ sudo apt-get install connect-proxy

Similar packages should exist for other Linux distributions. A friend of mine also said that it was very easy to compile and install on his OS X system.


Next, add the following to your ~/.ssh/config file:

Host *.onion
    ProxyCommand connect -S localhost:9050 %h %p

This tells SSH to use that proxy every time you try to connect to a .onion address.


Believe it or not that's all you should have to do to connect to an SSH server through the Tor network. You can test it like this:

$ ssh me@somelongaddress.onion

Extra Credit

SSH Aliases

I don't know about you but I can never remember .onion addresses. To keep track I therefore add aliases to my ~/.ssh/config file like this:

host bart.onion
    HostName somelongaddress.onion
    User me

Now I just have to remember that this is the Tor version of the hostname for the bart server. To log in I just execute the following command:

$ ssh bart.onion

Easy peasy.


One thing that's a little annoying about connect-proxy is that it prompts you for a SOCKS5 password automatically. I don't even have a SOCKS5 password when using Tor so I can bypass the prompt by just typing return. However, this is a little annoying and is incompatible with some tools that are built on top of the ssh client (like Emac's tramp mode).

To get rid of this prompt simply add the following to any file that is sourced by your shell when you login (such as .bashrc):


Now that password prompt will be removed.

Stupid Emacs Tricks - Editing Remote Files Using Sudo (And Even Tor)

Posted on Tue 06 October 2015 in Tutorial • Tagged with technology, tor, emacs, sshLeave a comment

I've recently learned how to edit files on a remote server using tramp and emacs and I really love how easy and powerful it is. Here are some of the tricks that I've learned that I'm now using every day.

Simple Remote File Editing

For example, let's say that you wanted to edit a remote file on server bart that has a path of /home/tom/foo. Here's how you would do that in emacs:

C-x C-f /ssh:tom@bart:/home/tom/foo

And viola - you can now edit the remote file locally using a tool that is built into Emacs. No more worrying about having all of your .emacs goodies on each server that you use - now just install it all in one place and be more awesome with Emacs!

Editing Remote Files That Require Sudo Access

Of course, this isn't all that amazing because lots of other text editors include this type of functionality by default (including my old standby Vim). What's cool about tramp mode (and unique as far as I know) is that you can actually open a file using the sudo command in a local emacs editor using a feature of tramp called proxies.

So for example, let's assume that you want to open a file that can only be edited by the root user on bart called /root/secret. Here's how you would open it in emacs:

C-x C-f /ssh:tom@bart|sudo:bart:/root/secret

Assuming that you can edit that file using your sudo access on the bart server you can now edit it on your local computer. Not only can you do that, but you can also now navigate directories as root using dired.

Chaining All Of This Together Using Tor

Finally, let's assume that you want to edit a file on a remote server that exposes the ssh server as a tor hidden service. Heck, maybe you even used this puppet module to set it up. Tramp doesn't care - it will just treat your .onion address as yet another ssh URL and it works really well. Opening and saving files is a bit slow, but everything else is very snappy.

There are however a few more things that you will need to do to make this work. Please see my tutorial on logging into an ssh hidden service for more information. Once you've made that work, just replace the host name with your tor host alias like this:

C-x C-f /ssh:tom@bart.onion:/home/tom/foo

Make sure that you also set the following environment variable in the shell that opens emacs:


For whatever reason tramp seems to choke on the SOCKS5 password prompt and for me it's always blank anyways. Of course if you are using a SOCKS password then change it as needed.

Finally, the sudo trick above also works with .onion URL's.


Tramp has really improved my workflow considerably when editing files with emacs. If you find yourself logging into lots of servers every day then I highly recommend checking it out

Configuring Jenkins To Run As A Different User Using Puppet

Posted on Thu 01 October 2015 in Tutorial • Tagged with technology, jenkins, puppetLeave a comment

I was recently rebuilding my laptop using Puppet and needed install Jenkins to run scheduled jobs. Thankfully, the excellent rtyler/jenkins module exists, but I needed to make a few changes to make it work for me.

A couple of the scheduled jobs that I need to run make encrypted backups using GnuPG and duply. The problem is that by default the jenkins service runs under the jenkins user, which cannot access either my duply or gnupg profiles. The simplest solution for this is to simply run jenkins under my local account (which is this case it tom).

There's already a really good tutorial on doing this manually, but since doing the same thing with Puppet is a little tricky, I thought it might be helpful to share my experience.

First, of course, you need to add the rtyler/jenkins module. After that you need to add the following to your manifest:

 1 $mainuser = "tom"
 3 Exec {
 4     path => [ "/bin/", "/sbin/" , "/usr/bin/", "/usr/sbin/" ],
 5 }
 7 include jenkins
 9 file_line { 'Replace runas user':
10     path    => '/etc/default/jenkins',
11     line    => "JENKINS_USER=${mainuser}",
12     match   => '^JENKINS_USER=\$NAME$',
13     notify  => Service["jenkins"],
14 }
16 file_line { 'Replace runas group':
17     path    => '/etc/default/jenkins',
18     line    => "JENKINS_GROUP=${mainuser}",
19     match   => '^JENKINS_GROUP=\$NAME$',
20     notify  => Service["jenkins"],
21 }
23 exec { "chown-var-lib-jenkins":
24     command => "/bin/chown -R ${mainuser}:${mainuser} /var/lib/jenkins",
25     unless  => "[ \"${mainuser} ${mainuser}\" = \"$(/usr/bin/stat -c \"%U %G\" /var/lib/jenkins)\" ]",
26     notify  => Service["jenkins"],
27 }
29 exec { "chown-var-cache-jenkins":
30     command => "/bin/chown -R ${mainuser}:${mainuser} /var/cache/jenkins",
31     unless  => "[ \"${mainuser} ${mainuser}\" = \"$(/usr/bin/stat -c \"%U %G\" /var/cache/jenkins)\" ]",
32     notify  => Service["jenkins"],
33 }
35 exec { "chown-var-log-jenkins":
36     command => "/bin/chown -R ${mainuser}:${mainuser} /var/log/jenkins",
37     unless  => "[ \"${mainuser} ${mainuser}\" = \"$(/usr/bin/stat -c \"%U %G\" /var/log/jenkins)\" ]",
38     notify  => Service["jenkins"],
39 }

Most of this should be pretty obvious to most Puppet users, but there's a few tricky things. For starters it may seem to be overkill to specify my path in the Exec statement at the top, but the command in your unless parameters won't work without it, even if you use explicit paths.

In the file_line statements I'm simply performing a find and replace using regexes.

The 3 exec statements are probably the weirdest things that I'm doing in this snippet. There's not a built-in way to perform a chmod -R command using puppet, so this is closest thing I could find. Basically, I'm first checking if the parent directory is owned by the "tom" user and group. If not, I run the chown command and then notify the jenkins service so that it can be restarted.

The unless parameter is a bit difficult to read with all of the escaping and such, so here's what it looks like on the command line without all of that:

$ [ "tom tom" = "$(/usr/bin/stat -c "%U %G" /var/log/jenkins)" ]

This command is comparing the output of the stat command with the string "tom tom". The [ ] operands are a way of testing conditions in Bash. If the output of the stat command matches "tom tom" then this command returns 0. Otherwise it returns 1 which tells Puppet to run the chown command.

So there you go - super simple setup of a Jenkins instance that can run as a non-standard user. Please note that if you should not configure Jenkins this way if the web interface is accessible using the public internet. This creates a fairly large security hole in your server because a vulnerability in Jenkins could allow an attacker to hijack your personal account. Please, please please don't configure your Jenkins server this way unless it's running behind a firewall or on your laptop or something like that.