Pre-conj Prep: Paul deGrandis

Talk: Unlocking Data-Driven Systems

Paul deGrandis' talk at the conj is about the design tradeoffs when building your system in a Data-Driven way.

Background

The recommended priority for choosing an implementation strategy is Data > Function > Macro. Macros are made for humans, not machines, so they are the least composable. Functions are composable, but opaque. Their only meaning is their side-effects and their return value. Data, however, can be interpreted in different ways, depending on the context. If one can design it right, a data-driven system can be both easy for a person to read and write and reusable for many problems.

This talk is part of an ongoing discussion about data-driven systems in Clojure. Data-driven design has been around far longer than Clojure has. Paradigms of Artificial Intelligence Programming is the book on the subject, showing its use in Common Lisp. Christophe Grand gave a talk at the Clojure/conj in 2010 that explained in depth why macros should not be the first choice when building DSLs.

Many systems use data as their primary interface. Datalog queries in Datomic are just Clojure data. Prismatic Schemas are data. Leiningen project files are data (with a small macro for human convenience). Data-driven system is related to code-as-data, that all Lisps share. If code is data, why can't data be code? Clojure makes data-driven solutions easy with its variety of literal data structures.

Why it matters

The conversation about how best to design data-driven systems is not over. Active Clojure developers are still experimenting and testing the approach. This talk will show data-driven systems taken to an extreme, where an entire ClojureScript application is represented as data. Many people already agree with the approach and are eagerly awaiting the deeper analysis this talk promises.

About Paul deGrandis

Github - Twitter


The Clojure/conj is going to be awesome. I've never been, but I have watched all of the videos from the prior conferences. I'm going this year, and you should, too! Go buy your tickets. There's some cool stuff happening there, including Opportunity Grants. Check out the Clojure/conj site and buy your tickets while they last. Clojure/conj is organized by Cognitect, the company behind Clojure.

This post is one of a series called Pre-conj Prep, which originally was published by email. It's all about getting ready for the upcoming Clojure/conj, organized by Cognitect. 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, as well as the beautiful venue and city of Washington, DC.

Clojure/conj is a conference organized and hosted by Cognitect. This information 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

Pre-conj Prep: Steven Yi

Talk: Developing Music Systems on the JVM with Pink and Score

Steven Yi's talk at the conj is about music systems on the JVM, focusing on two systems he built, called Pink and Score.

Background

Pink is a library for signal generation and processing and event handling. It is designed as a low-level library to use to build your own audio system. It is written in Clojure.

Score is a library for composing musical scores. Those scores are generic, so that they can be played by a variety of backend systems. Score is written in Clojure.

Why it matters

Electronic music is an interesting field. It is one that Lisp has been applied to for many years. To paraphrase Sam Aaron, creator of Overtone, Clojure's high-level allows a programmer to leverage programming ability to create better music. Pink and Score join Overtone and Rich Hickey's Harmonikit as music systems developed in Clojure.

About Steven Yi

Github - Twitter - Blog

Steven Yi is the author of the Blue Integrated Music Environment. He is also a core developer of Csound.


The Clojure/conj is going to be awesome. I've never been, but I have watched all of the videos from the prior conferences. I'm going this year, and you should, too! Go buy your tickets. There's some cool stuff happening there, including Opportunity Grants. Check out the Clojure/conj site and buy your tickets while they last. Clojure/conj is organized by Cognitect, the company behind Clojure.

This post is one of a series called Pre-conj Prep, which originally was published by email. It's all about getting ready for the upcoming Clojure/conj, organized by Cognitect. 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, as well as the beautiful venue and city of Washington, DC.

Clojure/conj is a conference organized and hosted by Cognitect. This information 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

Willy Wonka and the core.async Guidelines

Summary: There are a few conventions in core.async that are not hard to use once you've learned them. But learning them without help can be tedious. This article presents three guidelines that will get you through the learning curve.

Willy Wonka, inventor of CSP.

Willy Wonka, inventor of CSP.

Introduction

The more you use core.async, the more you feel like Willy Wonka. He knew how to maximize the effectiveness of the Oomploompa. And while core.async comes with a lot of functions built in, he knew exactly which ones to use at which time.

In this extremely rare glimpse into the functioning of his mysterious factory, we take a look at the guidelines Wonka himself follows when orchestrating the work of the Oompaloompas.

When to use go versus thread?

Willy Wonka with his Thread Pool.

Willy Wonka with his Thread Pool.

Background

Each Oompaloompa is a thread. Willy Wonka has a special group of Oompaloompas he calls a thread pool. Their assigment is simple: they manage a group of tasks that Wonka calls go blocks. Whenever Wonka has an appropriate task, he writes a go block and hands it to the Oompaloompas to work on.

As the Oompaloompas work, they take one task and do it until the task parks. When it parks, they put it down and pick up another task that isn't parked. Tasks become unparked when they get new input from the chocolate pipes. Then the Oompaloompas can continue working on them.

At one time, Wonka used to give the thread pool all sorts of tasks. He would give them very long calculation tasks, like weighing each chocolate bean in his chocolate bean mountain. He noticed that when they did this, lots of tasks were left undone, even though they were not parked, because all of the Ooompaloompas were busy doing something else.

So he came up with a guideline.

Avoid long calculations and blocking inside go blocks

Does your code do significant I/O, like downloading a file or writing to the network? Are you doing a very long calculation?

Then use a thread. If it will take a long time or block, you want a dedicated thread. It can work as long as it wants, and even block. That way it doesn't slow down the work of the thread pool.

Otherwise, you can use a go block.

When to use single- versus double-bang (!)

A couple of blocked Oompaloompas.

A couple of blocked Oompaloompas.

Background

Wonka also noticed that he needed to write different instructions for his two types of Oompaloompa. When he wrote a go block, he needed to say "park while you wait for input". But for the other Oompaloompas created with thread (or for his own work), he needed an instruction that said "block while you wait for input".

So he came up with a little notation convention. If you're just parking, so you're in a go block, use one bang. If you're outside of a go block, meaning you need to block, use two bangs.

These were his versions of his basic instructions:

>!, <!, and alts! versus >!!, <!!, and alts!!. The convention is easy.

Use single-bang versions in go blocks and double-bang versions outside.

The single-bang versions of these functions are meant to park a go block. Although they are defined as functions, they have special meaning to the go macro. In fact, if you actually run the functions (outside of a go block), they will throw an exception unconditionally, telling you they are meant to be inside a go block.

The double-bang versions are blocking. That means that the thread they are running on will block if the channel is not ready. They can be used outside of a go block (anywhere) or inside of a thread block. It's safe to block inside a thread block since it's a dedicated thread.

put!

Willy Wonka writing instructions for his mailman.

Willy Wonka writing instructions for his mailman.

Background

Like all factories, Willy Wonka's needs deliveries. When the UPS truck comes, there's plenty of boxes to unload. But Wonka is busy. So he leaves a note outside for the delivery guy.

The note tells the guy where to put everything so the Oompaloompas know where to find it. When he says where to put a box, he spells it put!. That is, it has a bang.

It's unfortunate because the other functions with a bang mean they park. But put! does not park. Wonka was just angry one day, and the convention stuck.

But the delivery guy knows that Wonka is eccentric, so he doesn't take it personally and does his job. He puts stuff in its places, without blocking.

Use put! to get stuff into your channels from outside.

put! is a way to get values from outside of core.async into core.async without blocking. For instance, if you're using a callback-style, which is very common in Javascript, you will want to make your callback call put! to get the value onto a channel.

Conclusion

That's it! Now to eat some chocolate!

core.async is really cool, but it has a learning curve. Once you learn these conventions, you will begin to feel the power they give you, whether you're making chocolate or building cars. If you'd like to learn core.async and feel like Willy Wonka, I recommend the LispCast Clojure core.async videos. They build up a deep understanding of the fundamental concepts in a fun and gradual way.

You might also like

Pre-conj Prep: Steve Miner

Talk: Generating Generators

Steve Miner's talk at the conj is about automatically creating test.check generators from a data-driven schema.

Background

Steve Miner is the author of the Herbert schema library. In Herbert, schemas are presented as plain EDN. They describe the structure and type of data. You can take a value and validate that it conforms to the schema. He is going to present a way to generate test.check generators from the schema. This way, you can do runtime checks and test-time checks. A good intro to Herbert is Steve Miner's lightning talk from Clojure/conj last year. Reid Draper gave a talk about test.check at Clojure/West.

Why it matters

test.check contains a set of combinators to create new generators from existing generators. But combinators are not very easy to read or write when the data they are generating is fairly complex. Being able to generate them automatically from a declarative, data-driven style is one way to make it easier.

Besides being easier, it also unifies the contracts (schema validation in function preconditions) with generative testing. The next domino would have to be building core.typed type signatures from the same data.

About Steve Miner

Github - Twitter


The Clojure/conj is going to be awesome. I've never been, but I have watched all of the videos from the prior conferences. I'm going this year, and you should, too! Go buy your tickets. There's some cool stuff happening there, including Opportunity Grants. Check out the Clojure/conj site and buy your tickets while they last. Clojure/conj is organized by Cognitect, the company behind Clojure.

This post is one of a series called Pre-conj Prep, which originally was published by email. It's all about getting ready for the upcoming Clojure/conj, organized by Cognitect. 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, as well as the beautiful venue and city of Washington, DC.

Clojure/conj is a conference organized and hosted by Cognitect. This information 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

Pre-conj Prep: Nathan Herzing and Chris Shea

Talk: Helping voters with Pedestal, Datomic, Om and core.async

Nathan Herzing and Chris Shea's talk at the conj is about using Pedestal, Om, Datomic, and core.async together. They promise to code systems live.

Background

Pedestal was the name for a frontend framework create by Cognitect. They deprecated that framework and used the name for a small piece of it that was libraries for backend web servers, which is now under development. So Pedestal now is a set of libraries for web development. Watch this Webcast for background.

Datomic is Cognitect's append-only database with Datalog queries. A nice introduction is this talk by Rich Hickey.

Om is a library in ClojureScript created by David Nolen. It is a wrapper around React, which is Facebook's library for manipulating the DOM in a functional way. Watch David Nolen's talk for a good introduction.

core.async is a library that brings Communicating Sequential Processes to Clojure and ClojureScript. A great talk on it is one by Rich Hickey.

Why it matters

I've said before that I like experience reports. This one will also combine it with live coding, which is exciting. Live coding is always a risk. This talk will combine four of the major components Clojure brings to the table, which are all very powerful in their own right. What will happen when their powers combine?

About Nathan Herzing

Github

About Chris Shea

Github


The Clojure/conj is going to be awesome. I've never been, but I have watched all of the videos from the prior conferences. I'm going this year, and you should, too! Go buy your tickets. There's some cool stuff happening there, including Opportunity Grants. Check out the Clojure/conj site and buy your tickets while they last. Clojure/conj is organized by Cognitect, the company behind Clojure.

This post is one of a series called Pre-conj Prep, which originally was published by email. It's all about getting ready for the upcoming Clojure/conj, organized by Cognitect. 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, as well as the beautiful venue and city of Washington, DC.

Clojure/conj is a conference organized and hosted by Cognitect. This information 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

The Content of Your Code

Summary: Code style is important, but way less important than content. Yet everyone talks about style because it's easier. Let's talk about content. I'll start with some bullet points.

In fiction writing, there is a fine, but visible, line between style and content. Style is your choice of words and grammar while you're telling a story. Content is the parts of the story itself. It's the characters, the plot devices, the motivations, etc.

Style is important. Classic works of literature usually have a good style. But content is more important. Good style can enhance a story. But a story can be retold many times, each with a different style, because a good character and story can stand on its own. No amount of style is going to save crappy storytelling with uninteresting characters. It didn't work for The Matrix 2 & 3, and man, did not help at all in the Star Wars prequels.

You can roughly divide programming decisions along a similar line. Coding style versus coding content. So much advice falls on the style side. It talks about variable naming, function length, what parts of a language not to use.

Where is all the stuff about code content? How do we choose an algorithm? How do we pick a data structure? Basically, how do we translate a real-world problem into a computational model? How do we determine if a program correctly models the problem? How do we judge if one model is better than another? The answer is so simplistic. A model fits a problem if the structure of the model matches the structure of the problem.

Structure, structure, structure.

Here are some bullet points:

1. Choose the right collection

Here's a good example that we should all be familiar with. How do you choose between an array and a map? Well, if your problem is to do things in order, an array is the better choice because it is naturally ordered. If your problem is "I have an x and I need a y", a map is probably better, because maps associate one value with another. The data structure's properties mirror the properties of the problem.

2. Factor your code

Refactoring is improving the style of your code without changing the content. But factoring is changing the structure of your code to reveal the underlying structure of the problem. This is the only reliable way to get a one-to-one mapping between code and reality.

3. Determine the essential structure of the problem

I have written before about finding the essential idea in a problem. Object Oriented Programming advice tends to recommend picking each of the objects in the real world and creating a class for each. So, if you're modeling students and courses, regardless of the problem you're solving, you should have a student class and a course class.

This practice comes from the early days of OOP, when it was still used a lot in simulations. I can see the benefit of representing each thing in your simulation as an object. But we're not building a simulation. A university registration system is not a university simulator. We are not simulating students. We are not simulating courses. We need to be looking at the problem we're trying to solve.

How is it already done?

I really think the best way is to look at the process that is already being used. If you're hired to replace a manual, pen-and-paper system, you have a head start over a new system. Computerizing an existing process is easier because the problem is already well-understood. Go ask the registrar's office how they are doing it.

Let's say that each department keeps a large list of all the courses they give each semester. For each semester, they start a new notebook and make a page for each course. As students register, they write down their name. If they unregister, they cross them out. They leave room for enough students between each course, sometimes skipping a page. They put post-it notes sticking out the top so they can quickly turn to the page for a course when a student comes in the office.

Wow! Your job is now way easier. You just have to replicate that notebook in code. That is so much easier than modeling students and courses. And once it's done, you have a place for improvements that are only possible in a computer.

Finding the essence

But let's say it's a new university, trying to get a head start on old universities by organizing everything on a computer. So there's no existing process. You've got to make it up.

What do you do if the structure is not obvious? How do you determine the structure of a poem? Reading. Re-reading. Underlining. Arrows. Notes. Clarifying definitions. Basically, look for structure. Dig it all up. Then use your judgment about what is important. There often is not one single kind of structure, but a constellation of structure.

4. Factor out incidence from essence

The incidental structure just happens because of the choice of solution instead of the structure of the problem. The structure inherent in the problem is essential structure.

In the notebook used for registering students, there are some incidental implementation details that you don't want to replicate. In the notebook, they left some blank space for more students after each page so that they wouldn't run out of room. But running out of room is not an issue in a computer (no university is that big). So you can leave that part out.

But less obviously, the fact that there is a separate page for each course is also incidental. It's not important that the students in one class all be stored in a single place. What's important is that at any time, a student can register for the course (random access!) and that at any time, a teacher can list all students in a particular course (random access!). We need a way to project a list of students quickly enough in a course from however it is stored.

But it turns out that, if you factor correctly and find the essence, your solution should be generic. Why? Because structure is generic. It is pure content. The correct solution to this problem is to make a system to manage many-to-many relationships. Relational databases can do this easily with one table. You could make a ManyToMany<A, B> class. Those are implementation details that are incidental. What's essential is the many-to-many part.

Conclusion

We need more discussion about the content of programs. Style is important, but we need people to create acronyms and rules of thumb for choosing program constructs. The Design Patterns book (and movement) were important in this respect. It documented patterns of common structure. But it failed to do a good job teaching the how, and added an air of mystery.

Although this process is language-agnostic, Clojure is great for finding essential structure. One thing I like about Clojure is that the data structures are described in terms of their usage structure. And Rich Hickey has expressed many times that to understand a problem, to design a solution, we must pull things apart into its essential parts.

If you'd like to learn Clojure and see how it might help you think in terms of structure, I can recommend my LispCast Introduction to Clojure video course. It builds up skills from complete beginner to decomposing a problem into a generic solution.

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

You might also like

Pre-conj Prep: Michał Marczyk

Talk: Persistent Data Structures for Special Occasions

Michał Marczyk's talk at the conj is about Persistent Data Structures that are available as libraries to Clojure. Given Michał Marczyk's contributions, this should be a great talk.

Background

Clojure comes with several Persistent Data Structures built-in. There is no need to copy them to share them, since they are immutable. And they are efficient at making modified copies as well, since they share structure. A great introduction to Clojure's Persistent Data Structures is this talk by Rich Hickey. For a deeper dive into how they work, check out Daniel Spiewak's talk.

Why it matters

Although the built-in data structures are great, there's no reason not to have more! Other data structures might be more appropriate at different times, given that they have different performance characteristics. It's great that there is development in these areas.

About Michał Marczyk

Github

Michał Marczyk has written several persistent data structures in use by lots of us every day. He wrote the map and set types for ClojureScript, along with transients.


The Clojure/conj is going to be awesome. I've never been, but I have watched all of the videos from the prior conferences. I'm going this year, and you should, too! Go buy your tickets. There's some cool stuff happening there, including Opportunity Grants. Check out the Clojure/conj site and buy your tickets while they last. Clojure/conj is organized by Cognitect, the company behind Clojure.

This post is one of a series called Pre-conj Prep, which originally was published by email. It's all about getting ready for the upcoming Clojure/conj, organized by Cognitect. 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, as well as the beautiful venue and city of Washington, DC.

Clojure/conj is a conference organized and hosted by Cognitect. This information 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

Pre-conj Prep: Julian Gamble

Talk: Applying the paradigms of core.async in ClojureScript

Julian Gamble's talk at the conj is about core.async in ClojureScript. core.async is an implementation of CSP for Clojure and ClojureScript. It allows for concurrency, and communication using an abstraction called channels. It is similar to built-in facilities in the Go programming language.

Background

core.async provides two main abstractions: go blocks and channels. Go blocks are lightweight processes that give the basic type of independent concurrency. To coordinate and communicate between the go blocks, the go blocks take values from and put values to channels.

Why it matters

core.async is important because it is a very powerful way to structure your code. Further, core.async is a library, not a core feature of the language, even though in many languages it is a fundamental part of the language. Finally, core.async gives Javascript (through ClojureScript) a much needed asynchrony model that is more expressive than callbacks.

About Julian Gamble

Twitter - Github - Blog


The Clojure/conj is going to be awesome. I've never been, but I have watched all of the videos from the prior conferences. I'm going this year, and you should, too! Go buy your tickets. There's some cool stuff happening there, including Opportunity Grants. Check out the Clojure/conj site and buy your tickets while they last. Clojure/conj is organized by Cognitect, the company behind Clojure.

This post is one of a series called Pre-conj Prep, which originally was published by email. It's all about getting ready for the upcoming Clojure/conj, organized by Cognitect. 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, as well as the beautiful venue and city of Washington, DC.

Clojure/conj is a conference organized and hosted by Cognitect. This information 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

Pre-conj Prep: Rich Hickey

Talk: Transducers

Rich Hickey's talk at the conj is about Transducers, a new abstraction in the core language (coming in Clojure 1.7).

Background

Transducers are a way to define the standard map, filter, and mapcat functions that does not bake in the idea of creating a list as output. Instead, it takes that as a parameter. It's hard to explain, but Rich Hickey does a great job making it clear.

The talk has no abstract at the time of this writing, so I can't say what he will add to the Strange Loop talk he gave. But I would guess that it will be more deeply aimed at Clojure programmers.

Why it matters

Transducers are very new. They haven't even been released yet. However, they've already made a splash, with static typists trying to come up with their type signature, and implementations in other libraries.

About Rich Hickey

Github - Twitter - Blog


The Clojure/conj is going to be awesome. I've never been, but I have watched all of the videos from the prior conferences. I'm going this year, and you should, too! Go buy your tickets. There's some cool stuff happening there, including Opportunity Grants. Check out the Clojure/conj site and buy your tickets while they last. Clojure/conj is organized by Cognitect, the company behind Clojure.

This post is one of a series called Pre-conj Prep, which originally was published by email. It's all about getting ready for the upcoming Clojure/conj, organized by Cognitect. 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, as well as the beautiful venue and city of Washington, DC.

Clojure/conj is a conference organized and hosted by Cognitect. This information 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

Pre-conj Prep: Jeanine Adkisson

Talk: Variants are Not Unions

Jeanine Adkisson's talk at the conj is about using Variants in Clojure. Variants are a way to represent different cases of value that belong to the same type. For instance, a linked list type might be represented as two cases: an empty list and a tuple of an element and a list. A tag distinguishes between the two cases.

Background

In a dynamically typed language, we often play fast and loose with type. For instance, we might write a function with a giant cond statement in the body that does little more than switch on type. But how do we know we've checked all the types we need to? Variants solve this problem.

Variants are a key feature of Haskell and ML. Adkisson mentions that there is no standard way of representing them in Clojure, which is true, though several commonplace conventions exist for getting some of the uses of Variants. However, there is not a common convention for noting all of the possible tags and ensuring that all cases are covered in a conditional. The talk description also mentions core.typed (a type system for Clojure, which does not have Variants) and Datomic (a database written by the creators of Clojure).

Why it matters

Adding Variants to Clojure is a good example of the Clojure community's excitement about borrowing good ideas from a variety of languages. And the fact that a new kind of type can be introduced that works in the dynamic language, a type system, and a database is promising for the future of idea borrowing in Clojure.

About Jeanine Adkisson

Twitter - Github - Blog


The Clojure/conj is going to be awesome. I've never been, but I have watched all of the videos from the prior conferences. I'm going this year, and you should, too! Go buy your tickets. There's some cool stuff happening there, including Opportunity Grants. Check out the Clojure/conj site and buy your tickets while they last. Clojure/conj is organized by Cognitect, the company behind Clojure.

This post is one of a series called Pre-conj Prep, which originally was published by email. It's all about getting ready for the upcoming Clojure/conj, organized by Cognitect. 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, as well as the beautiful venue and city of Washington, DC.

Clojure/conj is a conference organized and hosted by Cognitect. This information 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