Pre-conj Prep 2014

Prepare for the conj

People have been asking me how they can get ready for all of the great talks lined up for Clojure/conj. There are many topics, and people are feeling overwhelmed. They might know about some of the ideas, but not all of them.

Wouldn't it be nice to do just a little homework before the conj so that you would be sure to maximize your understanding and be able to participate in the conversations afterward?

Unfortunately, googling any topic reveals lots of material, and it's not always the best. It would take hours to sift through the background material for just one topic.

That's why I am publishing the Pre-conj Prep. Each day, I will send you one or two things to read or watch (whichever is better) to get up to speed on the topics of the talks (which are listed on the Clojure/conj speakers page). I'm used to finding great content for the Clojure Gazette, so you can be sure it will be helpful.

Conferences are ongoing conversations and explorations. Speakers discuss trends, best practices, and the future by drawing on the rich context built up in past conferences and other media. That rich context is what Pre-conj Prep is about. I want to enhance everyone's experience at the conj by surfacing that context. With just a little homework, we can be better prepared to understand and enjoy the talks and the hallway conversations.

There are 18 talks listed. After I go through all of them (that will take 18 days), I will go further than the published topics into other helpful stuff to get ready for a great conj. I am trying to get interviews with the speakers, restaurant/event/city guides, and more, to make the conference a special one.

Sign up below

It's ok if you missed some of the emails. They're all archived. Sign up now and it will link you to all of the past emails.

The conj is a single-track conference, which means all talks happen in series in a single auditorium. The advantage of that is that everyone has a very similar experience. We all see the same talks (unless you skip one). The disadvantage is that you can't choose a different talk if you don't know about a topic. Preparation is key to having a great experience.

As you probably know, conferences are social events. The talks are mostly an excuse to get together, meet each other, and talk about Clojure. The conversations that happen after a talk can be very rewarding. But if you don't understand why the topic is important, you may feel left out. Don't let that happen! You're travelling far and paying (or expensing) lots for the ticket, hotel, and travel. Make the most of it!

Clojure/conj is a conference organized and hosted by Cognitect. This email list is in no way official. It is not sponsored by nor affiliated with Clojure/conj or Cognitect. It is simply me curating and organizing public information about the conference.

You might also like

4 Features Javascript can steal from Clojure(Script)

Summary: ClojureScript adds a lot of value on top of the Javascript platform. But some of that value can be had directly in Javascript without using a new language.

ClojureScript is a dialect of Clojure that compiles to Javascript. It lets you run Clojure in a browser or on Node. Just like Clojure, it has immutable data structures, literals for those data structures, macros, and core.async support.

These features are very powerful and they give ClojureScript a lot of power above Javascript. But a lot of that power can be had in Javascript through libraries, tools, and now some ES6 features. If you can't make the switch to ClojureScript, these tools might help you out. If you've heard of all the cool stuff that ClojureScript can do, well, this might be a good way to dip your toes in before you jump in.

1. Use ClojureScript's awesome data structures in Javascript

David Nolen, the maintainer of ClojureScript, has wrapped up the ClojureScript immutable data structures to be used as a Javascript library which he calls mori. He's put in a lot of work to make it convenient to use from Javascript. It's not just the datastructures. It also has all of the functional goodness that makes them powerful to use.

2. Write CSP like core.async without core.async

CSP stands for Communicating Sequential Processes. It's a model of concurrency that is used in Go and in Clojure core.async. It's a powerful tool, especially in Javascript, where you don't have threads. Once you use it, you'll never go back.

Well, thanks to Generators in EcmaScript 6, you can write CSP code in Javascript. There's a library called js-csp that does just that.

3. Better data formats than JSON

JSON is a great format for data exchange, but it has limitations. One of the biggest limitations is that it is not extensible. You cannot define new types. Wouldn't it be nice to have values that get parsed as Javascript Date objects? Another limitation is that map keys can only be strings.

The edn format is Clojure's literal syntax made into a data format. It includes many data structures, including symbols, keywords, sets, maps, lists, and vectors. It is also extensible with tagged literals, meaning a small tag can be placed in front of a value to indicate the semantic meaning of that value. There are a couple of built-in tags, such as #instant for Dates and #uuid for, yes, UUIDs. But the important thing is you can define your own and define how they get parsed.

There's a Javascript library for parsing and generating edn.

edn is a great format, but parsing it in Javascript is never going to be as fast as parsing JSON. The JSON parser is written in C and highly optimized. Because of that limitation, the folks who build Clojure wrote Transit, which is a data format that serializes to JSON. It's semantically equivalent to edn, so it's extensible, but it's also JSON, so it's fast to parse. There's a Javascript implementation.

4. Write your own syntax with macros

Macros are one of those legendary things Lisps are known for. They let you write code that writes code. Well, that's kind of a meaningless statement. Think of it more like extensible syntax. You can write a new type of syntax which will be translated to plain Javascript.

There's a macro system for Javascript called Sweet.js. The macro system is similar to the one found in Scheme systems. This isn't directly from Clojure, but you get the same power. Macros are a great way to extend a language. You no longer have to wait for a new language feature to be implemented. You can do it yourself.

Conclusion

The Javascript community is active and growing. There are plenty of smart people making cool libraries that can revolutionize your programs. One of Clojure's philosophies is to have a small core language and extend, to the extent possible, using libraries1. So, those libraries can often be leveraged outside of Clojure, which is true in the case of mori. Or they are simply standardized to work cross-platform, like edn and Transit. CSP and macros are simply powerful tools that can be added to many languages.

Go give these tools a try. If you like them, you might like Clojure/ClojureScript. They will be here when you're ready. And when you are ready, I must recommend LispCast Introduction to Clojure. It's a video course designed and produced to take you from zero to Clojure.

Learn Functional Programming using Clojure with screencasts, visual aids, and interactive exercises
Learn more

You might also like


  1. Those libraries often contain macros which extend the base language.

Convince your boss to use Clojure

Summary: Clojure has been successfully adopted by many companies. There are many resources available by people who did the hard work of introducing Clojure to their team.

Do you want to get paid to write Clojure? Let's face it. Clojure is fun, productive, and more concise than many languages. And probably more concise than the one you're using at work, especially if you are working in a large company. You might code on Clojure at home. Or maybe you want to get started in Clojure but don't have time if it's not for work.

One way to get paid for doing Clojure is to introduce Clojure into your current job. I've compiled a bunch of resources for getting Clojure into your company.

Take these resources and do your homework. Bringing a new language into an existing company is not easy. I've summarized some of the points that stood out to me, but the resources are excellent so please have a look yourself.

The Strategy

Before you begin your quest to introduce Clojure, you're going to need a good strategy. By far the best presentation of a strategy is by Neal Ford. Neal Ford is a Director at ThoughtWorks and has a great strategy for introducing Clojure into an existing company. Watch this video.

  1. Spread Clojure outside of the company.
  2. Get a groundswell of people inside the company.
  3. Use Clojure for things it's great at.
  4. Get the Clojure jar file included.

If your company happens to be using Ruby, Joshua Ballanco has some great tips for How to Sneak Clojure Into Your Rails Shop.

Sean Corfield helped move a sizeable legacy application to Clojure. He's got some good, sobering advice.

  1. Be ready to explain the lack of a framework.
  2. OOP habits are ingrained.
  3. Don't underestimate the difficulty.

A lot of great advice from someone who's actually done it.

  1. Find allies.
  2. Answer the questions.
  3. Take responsibility.
  4. Get help.
  5. Be an advocate.

Some great advice from Logan Campbell, someone who convinced his coworkers to use Clojure at a Post Office.

  1. Be positive: if they say "We need static typing", say "Great! Clojure has that!" (which it does with Typed Clojure).
  2. Show them working code.
  3. Be ready for performance questions.

Material for other developers

Prismatic has been using Clojure to great success. They've written about how Clojure is used throughout their stack. This is a great introduction to answer the question "Why Clojure?". Spread this post whenever anyone asks why?.

Leo Polovets polled Clojurists at Factual and summarized their answers to Why Clojure?.

A while ago, this great post was trending on Hacker News. It explains Why Clojure?.

Material for the project manager

If you'd like a high-level overview of the business advantages to using Clojure, you can do a lot worse than asking Cognitect, the company that develops Clojure itself. They've published a case study, meant for non-tech folks, to understand the implications. It's focused mainly on Datomic, but it touches on Clojure.

Though a little hyperbolic, this post is a good one for the skeptical manager, the one who wonders whether their team can really learn a new technology quickly enough to justify the cost.

For those who like to follow industry trends and what others are recommending, look no further than the ThoughtWorks Technology Radar. It's a compendium of recommendations, published regularly, that takes a realistic view of a constantly changing landscape. Clojure has been rated at Adopt since October 2012. A lot of secondary Clojure technologies are also on the radar, including core.async, om, Datomic, and ClojureScript.

Documentation, Training, Support

I mainly want to show that there's plenty out there and plenty of new stuff coming out, not recommend anything specific.

Books

There's plenty going on with documentation. There are many books available on Amazon. These are all of the same quality as any enterprise Java book.

Videos

Videos are an up-and-coming type of training, but there's plenty out there.

Training

Besides these courses, there are often Clojure courses before or after the Clojure conferences.

Support

Besides the normal IRC (#clojure on freenode), Google Group, and Jira, Cognitect offers support.

Conclusion

Clojure is gaining traction. It's fun, it's productive. But it's still a little fringe in larger companies. Though it will still take a lot of work, these resources should help you make a case for Clojure. It's my mission to help people thrive with Clojure. If you'd like to keep up to date on what's happening in the Clojure world, you may be interested in getting the Clojure Gazette for free. Sign up here.

For more inspiration, history, interviews, and trends of interest to Clojure programmers, get the free Clojure Gazette.

Learn More

Clojure pulls in ideas from many different languages and paradigms, and also from the broader world, including music and philosophy. The Clojure Gazette shares that vision and weaves a rich tapestry of ideas from the daily flow of library releases to the deep historical roots of computer science.

You might also like

Just Hack Something Together

Summary: Lisp is viewed as difficult and academic but it is a great language for hacking a solution together.

I used to be in a carpool with other developers. We would drive an hour to work each way. And sometimes we'd talk about programming languages. Once I was talking about why Common Lisp wasn't more popular. Someone answered "people just want to hack something together".

That took a while to unpack and it felt like many conversations I had with that group. Without exploding all of the context, I'll just say that he meant that Common Lisp was less amenable to quickly building a solution than Java1. That notion caused my head to spin and I didn't know how to respond.

So I'll respond here, now (5 or 6 years later!). Lisp was made to explore solutions quickly. Lisp is often seen as a difficult, academic language. But Lisp has several things that make it a beautiful language for hacking a solution together.

1. The REPL

You can type code in and it will run. Right there. The entire language is available without having to open a text file. You can experiment on a solution, testing as you go. This is much faster than having to write a main method.

2. Incremental compilation

You can redefine a function. Any code that calls that function will now use the new definition. You no longer have the edit-compile-run cycle. You can make changes and fixes much faster.

3. Data structures

Even the humble Lisp list is better than most of what Java gives you. Lists can represent linear data, trees, or associative data. But more importantly, the interface is powerful. There are many operations built to use lists, so you're compounding effectiveness on top of everything built in. And if you bring in Clojure's data structures, there's no comparison.

In Java, you can use Lists and Maps. But most of the time, people will create a new class to represent their data. And making a new class means you have to write all of the methods. And that is definitely slower than using an existing data structure with existing methods.

4. Less code

Lisp is less verbose than Java. If you're trying to go quickly, one limiting factor is how fast you can type the code in.

I purposefully left out a lot of the features of Lisp that make it great because some of them are considered "advanced". I want to keep the list down to those basic things that you're going to have to use in order to use the language. The "advanced" features require expertise in order to be more efficient at them. You can be more effective in Lisp with a small cheatsheet of syntax and functions.

I think it's pretty clear that Lisp is superior to Java for "hacking". It was developed to experiment with programs interactively. And it serves that purpose very well. If you think you'd like to learn a modern Lisp, I suggest learning from LispCast Introduction to Clojure. It's a great video series that takes you from zero knowledge to a deep understanding of functional programming.

Learn Functional Programming using Clojure with screencasts, visual aids, and interactive exercises
Learn more

You might also like


  1. I don't mean to pick on Java, it was his language of choice. Having a comparison language merely helps the imagination

Atom code explanation

Summary: I go over a real-world example of how atoms and immutable values allow you to compose constructs in ways that are easy to reason about and less prone to error.

The other day I was in IRC #clojure and someone asked a good question. They had code like the following, and they couldn't understand why they couldn't modify a map.

(def state (atom {}))

(doseq [x [1 2 3]]
  (assoc @state :x x))

(println @state)

What does this print? Well, the asker wanted it to print {:x 3}. But it printed {}. To understand what's happening, let's go step by step.

{} creates an empty map. It's literal syntax for a constructor for a map. This one happens to be empty.

(atom {}) takes the empty map that was just created and passes it to the function atom, which constructs a new clojure.lang.Atom. Atoms are objects, and its current state is the empty map we just passed in.

(def state (atom {})) defines a new var called state in the current namespace.

At this point, we've got a variable called state whose value is an atom that holds an empty map.

(doseq [x [1 2 3]] loops over the numbers 1, 2, and 3. x will be bound to each of those numbers, in turn.

@state gets transformed into (deref state), which returns the current value of state. :x is a literal keyword, and x is a reference to the x bound inside the loop.

(assoc @state :x x) creates a new map by taking the current value of state (which happens to be {}) and associating :x with x (which will be 1, 2, and 3 as the loop happens). The value is returned by assoc, and then thrown away, since it isn't bound to anything.

Then (println @state) will print the current value of state, which still is {}.

This code shows a common problem that beginners face in Clojure: how do immutable data structures (like maps) and the concurrency primitives (like atom) work together to manage state?

The answer is quite simple (in the Rich Hickeyan sense) and elegant. By separating the ideas of value and state, Clojure has made it easy to express precisely the behavior you want in concurrent systems.

The value is the map. It is immutable. It cannot change. It is a single value, and it will always be the same. That means threads can share the value with no worries that one of them will change it.

The state is the atom. It's a mutable object. And being an object, it has methods that define its interface. In the code above, we saw that you can call deref on an atom to get its current value. deref is basically a getter.

The main way to change the value of an atom is using swap!. swap! takes an atom and a function (plus optional arguments) and calls the function on the current value of the atom. It then sets the value of the atom to the return value of the function. So let's use that to fix the code.


(def state (atom {}))

(doseq [x [1 2 3]]
  (swap! state assoc :x x))

(println @state)

swap! takes the atom (state) and a function (assoc) and some arguments (:x x). It calls assoc on the current value of state with those extra arguments and sets the value of the atom to the return value of the function.

The swap! expression is almost (but not) the same as this code:


(reset! state (assoc @state :x x)) ;; never do this

reset! changes the state of the atom but without regard to the current value. This new code is bad because it's not thread-safe. Use swap! if you need to use the current value to determine the new value.

So what does an atom do? What does it represent?

Atoms guarantee one very important thing: that each state is calculated from the last state. The swap! operation is atomic. No matter how many threads are trying to change the value, each change is calculated from the previous value and no previous values are lost. That's its contract as an object and it's one of the important ways that Clojure helps with concurrency.

How can a value be lost?

If we have two threads, each trying to change state in the same incorrect way (using reset!), the order of evaluation will have several steps:

  1. (deref state) ;; call this value *1
  2. (assoc *1 :x x) ;; call this value *2
  3. (reset! state *2)

Because the threads are running concurrently, the operations have a chance of interleaving their steps in unwanted ways. For instance, threads A and B might interleave like this:

  1. A: (deref state) ;; call this value *1A
  2. A: (assoc *1A :x x) ;; call this value *2A
  3. B: (deref state) ;; call this value *1B
  4. B: (assoc *1B :x x) ;; call this value *2B
  5. B: (reset! state *2B)
  6. A: (reset! state *1A)

What happened? On line 6, A set the value of state to the value it calculated on line 2. So B's work is completely discarded. That's probably not what was intended. What's worse is that that is one of many possible interleavings, some of which work and some don't. Welcome to concurrency!

What you probably wanted was to make sure that no work is discarded. You want the operation to be atomic. That's why it's called an atom. swap! is atomic. A swap! to an atom occurs "all at once", instead of on three lines like the reset! example. If two threads are doing swap!, there are two possible interleavings.

  1. A: (swap! state assoc :x x)
  2. B: (swap! state assoc :x x)

And

  1. B: (swap! state assoc :x x)
  2. A: (swap! state assoc :x x)

These are usually what you want. If only one or neither one works, atom is not the right construct for you.

So there you go. Atomic mutable state with immutable values gives you a nice, composable concurrency semantics. You could do it with locks but it's harder to ensure you're doing it correctly. It's slightly higher-level than locks yet it provides tremendous value. Atoms are easier to reason about and less prone to errors.

If you'd like to learn the basics of Clojure, I recommend my video course called LispCast Introduction to Clojure. I don't go over concurrency, but you will learn lots of functional programming. Go check out the description to see if it's right for you.

Learn Functional Programming using Clojure with screencasts, visual aids, and interactive exercises
Learn more

You might also like

Two Kinds of Bootstrapping

Summary: I like languages with a small core that is extensible. The languages tend to be weird and require less code to bootstrap.

I know of two ways to bootstrap a language.

The first way is probably more traditional. I'll call the first way Type 1. In Type 1, you write a bare-minimum compiler for your language in a host language. So maybe you write a Lua compiler in C. Then you write a Lua compiler in Lua. Then you compile your compiler. Now you have a compiler, written in Lua. You can add to it and modify it without ever having to touch the C code again. You have the advantage of writing the features of your language (Lua) in a higher-level language (Lua). And finally, as you add features to your compiler, you can use those to add more features. There's some leverage.

I like the second way better. I'll call it Type 2. In Type 2, you write a small, powerful set of abstractions in the host language. For instance, you write an object system in C, a stack and dictionary in assembler, or lexical closures in Java. Then you write a compiler that targets those abstractions. If the abstractions are chosen correctly, your compiler is done. You can begin building abstraction on top of abstraction without touching the compiler.

There are a few things to note:

  1. Type 2 languages (Lisp, Smalltalk, FORTH) tend to be weird because they were birthed in a different way. The abstractions, though powerful, are often raw.

  2. Type 2 languages can be bootstrapped faster. The core is often much smaller than a full-featured compiler.

  3. Type 2 languages tend to require less code in general. I guess it's because you're writing most of it in a language that is compounding leverage.

  4. Type 2 languages are more easily ported, since all you have to do is rewrite the core. Type 1 languages, depending on how they are built, can require you to re-bootstrap or write a cross-compiler.

In the end, I believe that both Type 1 and Type 2 are viable options for language-building. I prefer Type 2. If Type 2 intrigues you, you should learn Lisp (or FORTH or Smalltalk). I recommend the LispCast Introduction to Clojure videos course.

Learn Functional Programming using Clojure with screencasts, visual aids, and interactive exercises
Learn more

You might also like

Clojure is Imperative

Summary: Clojure is an imperative language. Its operations are defined in terms of concrete actions. But those actions are often the same actions available to the programmer at runtime. This makes it easy to bootstrap.

Update: أخلاق الخيميائي pointed out that I was wrong about the size of GHC. Luckily it was not salient to my point so I just removed that part of the article.

Update: After talking with several people, I've decided that my writing was really unclear. I've done some major editing to make it as clear as I can. Thanks to everyone who commented and helped me clarify my thinking and writing.

I was recently on the Cognicast and I mentioned something really important to me, but I did not go that deep into it.

Clojure, and Lisps in general, are imperative languages. Yes, they are good for doing functional programming, but their main paradigm is executing lists of commands in order.

On the podcast I mentioned the first imperative example that came to mind, which was the do form, which executes each expression in the body and returns the value of the last expression. You would only want to execute an expression and throw away its value for its side effects.

But why is that important to me? It got me thinking about a deeper but related idea.

Clojure is a relatively transparent layer above the JVM. I say "relatively" because languages do get quite a bit more opaque1. But it manages to be powerful through well-chosen abstractions.

I should be a little more specific about what I mean by "transparent" and "opaque". This should be the most controversial part of this post, so I want to get this right. These are not formal definitions. Transparency/opaqueness measures abstractions. Opaque abstractions show less of the underlying machinery. Transparent abstractions show their machinery. This is a spectrum.2

Clojure's functions are rather opaque. Defining a function (with fn) in Clojure creates a class and instantiates it with the values from its lexical environment. This happens without having to think about classes. You're not thinking about the machinery. The machinery leaks out sometimes, like when you're looking at stack traces. But in general, an illusion is maintained.

But Clojure's def form is pretty transparent. You do have to think about what it's doing, about the current namespace, the order of the defs in a namespace, etc. There is not much of an illusion to maintain.

Haskell has a well-defined execution semantics. It's formally defined and you can step through the execution of a Haskell program by hand if you want. In that sense, it's imperative. But the execution order is obscured by the somewhat opaque abstraction of lazy evaluation. Clojure's execution order is more or less directly the execution order of the JVM it runs on--hence more transparent.

The reason this is important is that Clojure's strategy is to be transparent unless there is significant gain. This is part of what is meant by "embracing the host". Haskell's strategy is orthogonal to the transparency/opaqueness axis. Haskell aims to be formally well-defined. Formal semantics allows deep static analysis and program transformation.

Besides the strategy of being transparent, what I like even more about Clojure is that the many abstractions are defined in the same abstractions that you have available as a programmer.

This is from the docstring of def:

Creates and interns a global var with the name of symbol in the current namespace (*ns*) or locates such a var if it already exists. If init is supplied, it is evaluated, and the root binding of the var is set to the resulting value. If init is not supplied, the root binding of the var is unaffected.

Creating a var? I can do that. Interning it? I can do that, too. Setting the root binding? Easy! The core can be kept minimal because abstractions can build on each other. If you get the abstractions right, the amount of code you have to write in your implementation language is small.

And this gets to the heart of it: you can write a Lisp yourself. Many people have. You can write an easy Lisp compiler in a weekend and build features on top of it, almost never having to change the original compiler.

This is the magic of bootstrapped languages like Lisps. They have a small core that you need to get right, then everything else can be written in that core. It's the ultimate minimal virtual machine.

What's the relationship between bootstrapping and transparency? The more opaque the abstractions, the more the language must do to maintain the illusion. Lisps are easy to bootstrap because the abstractions chosen are either transparent and trivial to implement (like def or if) or opaque and powerful (like fn).

I like Lisps (and Clojure) because I feel that I can understand them and build them myself. I don't actually understand everything, but I could if I tried. Somewhere along the way I developed a deep interest in bootstrapping. Bootstrapping is compounded leverage. You build small abstractions on top of the previous ones, and use those to build yet grander ones.

If you like this attitude toward programming languages, you should learn a Lisp. I suggest Clojure, and I recommend the LispCast Introduction to Clojure video series. You'll learn about building up powerful abstractions, one layer at a time, in a small amount of code.

Learn Functional Programming using Clojure with screencasts, visual aids, and interactive exercises
Learn more

You might also like


  1. There are more transparent languages as well, but they tend to be obscure.

  2. As an aside to those who read previous versions of this post, what I meant by imperative/declarative was transparent/opaque. I botched it and I'm trying to get this idea right.

Complex Syntax

Summary: Lisps are revered for their simple syntax, but parens are complex. They complect function calls and macro calls, which have drastically different semantics.

One of the problems that people have with Lisps is that they hate the parentheses. Clojure does a pretty good job of minimizing unnecessary parens and giving them a much clearer meaning. But there's a deeper problem that people express all the time when they're first learning. It's frustrating to watch people struggle with it, because it's not their fault. It's a problem with Lisps in general.

Parens in all Lisps I've seen, including Clojure, are complex. I'm not using the word lightly. Parens complect two similar but distinct ideas: macro application and function application.

Macros and functions are obviously different. Macros are expanded at a time just before compilation called "macro-expansion time". They typically cannot be accessed at runtime. Functions, on the other hand, are applied at runtime. And they are first-class, meaning they are runtime values. In addition, the calling semantics are different. Macros are call-by-name. The code of each gets passed unevaluated. Functions are call-by-value. Functions and macros are two distinct species.

However, despite being distinct semantics, the syntax for calling the two is identical. Parens complect applying macros with applying functions. Beginners trip up on this all the time. Their head is already spinning from the notion that some of the things they are learning are macros, called at compile time. Now add on top that the syntax of the language does not help one bit in distinguishing macro calls from function calls. You just have to memorize what's a macro and what's a function.

We learned in The Next 700 Programming Languages that our syntax should serve to elucidate the semantics. Lisp just fails at this pretty hard. The only consolation is that you actually can remember, with time and experience, what's a macro and what's a function. Every Lisp programmer is proof of that.

A simple solution would be to have a weird syntax for calling macros. You know, instead of parens, you use something else. Something that distinguishes the two to decomplect them. This would have broad and deep implications for the language that I cannot begin to fathom.

The takeaway for the beginner is that, sorry, Clojure won't help you much with this, but it's very important to know what's a macro and what's a function. You just have to keep track in your head. If you're not sure, you can call clojure.repl/doc1 on any symbol. If it names a macro, it will tell you.

So, there you have it. Lisps complect function calls and macro calls, which have drastically different semantics, using the same notation. Common Lisp and Scheme use parens for much more than that, making the syntax complex and context-dependent2. Clojure removes a lot of those parens, replacing them with square braces or removing them altogether. However, the complexity of macro and function calls remains.

Despite this, Clojure is still a great language! If you'd like to learn Clojure, I have to recommend the LispCast Introduction to Clojure video series.

Learn Functional Programming using Clojure with screencasts, visual aids, and interactive exercises
Learn more

You might also like


  1. That's a macro.

  2. For instance, inside of a let, parens take on the meaning of grouping the bindings and also grouping the variable with its value.

Is core.async Against the Clojure Philosophy?

Summary: Clojure core.async is a way to manage mutable state. Isn't that against functional programming?

When core.async was first announced, there was a lot of fanfare. But among the celebration, there was some consternation about core.async. Isn't core.async against the functional principles of Clojure? Aren't channels just mutable state? Aren't the <! and >! operations mutation?

Well, it's true. core.async is about mutation. It's procedural code. Go blocks run their bodies one step at a time. It's imperative.

But that's what Clojure is all about. It makes functional programming easy (with fns, immutable data structures, and higher order functions). It also makes mutable state easy to reason about. It does not eliminate it. It simply gives you better abstractions. That's what Atoms, Refs, Vars, and Agents are: useful abstractions for dealing with state.

core.async is just another abstraction for dealing with state. But, following the Clojure philosophy, it was chosen to be easy to reason about. The hardest part about coordinating and communicating with independent threads normally is that neither of them know what the other is doing. You can make little signals using shared memory. But those signals get complicated fast once you scale past two threads.

And that's what a channel is: it's just a shared coordination point. But it has some cool properties that make it super easy to reason about:

  1. Carry semantics: the channel carries its own coordination semantics (buffering, unbuffered, etc).
  2. Simple interface: channels have put, take, and close. That's it.
  3. Very scalable: any number of processes can use a single channel with no additional cost.
  4. Decoupling: consumers don't need to know producers and vice versa.

Channels are awesome, but they're not the whole story. The other part of core.async is the go block. Go blocks are another abstraction. They allow you to write code in an imperative style that blocks on channels. You get to use loops and conditionals, as well as local let variables, global variables, and function calls -- everything you're already using, but augmented with the coordination power of channels.

All of these features add up to something you can reason about locally. That's the key: the code you're looking at now can be understood without looking at other code.

But there's a downside: you now have more choices. In theory, they're easier choices. But that requires you to understand the choices. You need to understand the abstractions, the idioms, and the tradeoffs. That's the goal of the LispCast Clojure core.async video course. If you'd like to use core.async but you don't know where to start, this is a good place.

You might also like

Reification

Summary: Reification means making an abstraction into a concrete value that can be manipulated at runtime. Reification is the core of what makes a language dynamic. Three types of reification in Clojure are discussed.

What made Object Oriented programming (in the Smalltalk sense) so powerful? So powerful, in fact, that the GUI, WYSIWYG editing, overlapping windows, MVC, and more, were invented using it, not to mention an entire programming paradigm.

What made Lisp so powerful? So powerful that we still see new Lisps popping up and its legend looms over every serious programmer's mind.

Now, I don't want to boil it down to one thing. But one thing that was important, that you see in both of these languages, was the idea of reification. In fact, reification is possibly the essence of what makes a language "dynamic".

Reification, as I define it here in this article, means to make an abstraction available at runtime. Many languages have a text-based syntax that is read in by a compiler and compiled to machine code. But Smalltalk made each line of code into an object that you could manipulate, either with the input devices or with other code. And it let programmers bootstrap an IDE that was unparalleled at the time.

But Smalltalk's coup de grace reification was the class, which is an object which represents the behavior of another object. Instead of some static switch statement that dispatched the methods, the methods were stored in a data structure that could be inspected and added to at runtime. Dynamic dispatch! You see this in multimethods in Clojure.

Clojure's namespaces are reified. Some languages have a linking step in the compiler where modules are brought together to form a binary. But in Clojure, the namespace is accessible at runtime. Does your code want to know what Vars are defined? Easy. How about add a new Var. Done. These serve to support interactive programming--a hallmark of dynamic languages.

Lisps have always, from the very beginning, supported homoiconicity, which is a silly way of saying that programs are reified into the language as data. This means you can write functions that write code--also known as macros. Macros serve a very useful bootstrapping function because you can gradually add to the language instead of having to design it up front. And sometimes you get a huge win, like core.async, which adds a totally new semantic.

The next level of reification in Lisps is the higher-order function. Functions are not just things to call, but things to pass as arguments, save in collections, etc. They are real values, just like numbers and strings. There was a time in the history of programming when you could not refer to a function except to call it. Now, we take it for granted. Being able to reify an abstraction into a thing to pass around is amazing, and we should all just take a moment to ponder just how awesome it is.

Lisps have traditionally gone to the next level, which is to reify a problem into a data-driven solution. Nowadays, people call this type of programming "DSL". But it's just a type of reification. Instead of writing code to solve the problem, let's encode the solution as data. The problem domain is encoded in the interpreter for that data. Now it's accessible at runtime in a way simple code never could be.

Prismatic's Schema is a great example of this. You define a validator for a piece of data using existing data types: maps, vectors, strings, classes, regexes, etc. Then the library can interpret that data structure and tell you if a piece of data is described by that validator. If schemas were merely a static construct, this would not be possible. You would have to wait for the language to "support" it, which is a terrible form of tyranny.

Here's the secret to compounding the power: that data structure can be interpreted in many ways. Take Prismatic's Schema again. You can generate schemas at runtime. You can print them out. You can use them to build test.check generators. When things are reified and use the same interface as everything else, you can see synergy between libraries. You use one reification to enhance another.

Data-driven solutions are superior to macro-driven ones or even higher-order function solutions. Data can be stored. It can go over the wire. It can be meaningful in different contexts. A macro is useful at compile time, which happens once. Functions are black boxes and can really only do one thing (apply to arguments). But data is just data, ready to be interpreted.

Many Clojure libraries are considered "language features" in other languages. You don't have to mess with the internals of the language. Dynamic languages can do this, but Clojure (and most Lisps) has it at enough levels that interesting things happen.

Here's another reification: Haskell reifies side effects into values that can be composed. That's cool.

If you're into this whole reification thing, where language features that require major releases in other languages are just libraries; if you think you should learn functional programming; if you are curious about what everyone is talking about, check out the LispCast Introduction to Clojure video series.

The series is 1.5 hours taking you from zero Clojure knowledge through data-driven programming, one of the coolest types of reification. You'll help a robot who always wanted to be a baker learn to make bread :) Help him learn the recipes and convert them from static code to dynamic data.

Learn Functional Programming using Clojure with screencasts, visual aids, and interactive exercises
Learn more