<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>http://www.laliluna.de/</id>
  <title>Laliluna Clojure, Java, Architecture articles</title>
  <updated>2017-12-17T00:00:00Z</updated>
  <link rel="alternate" href="http://www.laliluna.de/"/>
  <link rel="self" href="http://www.laliluna.de/articles/feed/blog.xml"/>
  <author>
    <name>Sebastian Hennebrueder</name>
    <uri>http://www.laliluna.de</uri>
  </author>
  <entry>
    <id>tag:www.laliluna.de,2017-12-17:/articles/2017/12/17/choosing-clojure-libraries-for-a-new-project.html</id>
    <title type="html">Setting up a Clojure Project in 2017</title>
    <published>2017-12-17T00:00:00Z</published>
    <updated>2017-12-17T00:00:00Z</updated>
    <link rel="alternate" href="/articles/2017/12/17/choosing-clojure-libraries-for-a-new-project.html"/>
    <content type="html">
&lt;h1 id="setting-up-a-clojure-project-in-2017"&gt;Setting up a Clojure project in 2017&lt;/h1&gt;

&lt;h2 id="the-challenge"&gt;The challenge&lt;/h2&gt;

&lt;p&gt;After at least two year of Clojure abstince, I explored libraries for an application exposing REST services. The system design is trival, a database and a couple of REST services exposing the data in
  various forms.&lt;/p&gt;

&lt;h2 id="the-surprise"&gt;The surprise&lt;/h2&gt;

&lt;p&gt;The Clojure world seems to undergo a phase of library consolidation. After years of heavily exploring new approaches, some libraries are successful while many projects are actually dead.&lt;/p&gt;

&lt;p&gt;This is not something bad. In my option it is a consequence of developers with background in other languages carried over concepts just to find out that it is actually not needed.&lt;/p&gt;

&lt;h2 id="sql"&gt;SQL&lt;/h2&gt;

&lt;p&gt;I explored libraries to interact with relation databases and I found that Korma, which I used in the past, is getting little community attention. So I explored available options&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://github.com/korma/Korma"&gt;https://github.com/korma/Korma&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://github.com/jkk/honeysql"&gt;https://github.com/jkk/honeysql&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://github.com/r0man/sqlingvo"&gt;https://github.com/r0man/sqlingvo&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://github.com/friemen/aggregate"&gt;https://github.com/friemen/aggregate&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://github.com/krisajenkins/yesql"&gt;https://github.com/krisajenkins/yesql&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://github.com/metabase/toucan"&gt;https://github.com/metabase/toucan&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://github.com/layerware/hugsql"&gt;https://github.com/layerware/hugsql&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of those felt like the perfect choice. After reading &lt;a href="http://clojure-doc.org/articles/ecosystem/java_jdbc/home.html"&gt;http://clojure-doc.org/articles/ecosystem/java_jdbc/home.html&lt;/a&gt; and &lt;a href="http://peterstratton.com/posts-output/2017-01-28-postgres-and-clojure-using-clojure-java-jdbc"&gt;http://peterstratton.com/posts-output/2017-01-28-postgres-and-clojure-using-clojure-java-jdbc&lt;/a&gt; the need for a library
  was actually questioned at all. Clojure JDBC has a light abstraction for inserts and updates. In addition it provides options to convert column names when reading and writing. It took 1 hour to
  write a small abstraction to convert our camelcase to nicer Clojure keywords. Consequently, there is a good chance that a library is not needed at all. We will see if we stay with core Clojure on the long term but currently it is a
  simple way to interact with a DB.&lt;/p&gt;

&lt;p&gt;To have slightly better support for dynamic queries, we are exploring Honeysql as an addition. Many of the named libraries are much more powerful than HoneySQL, but as long as there is no need for more advanced stuff, why add complexity&lt;/p&gt;

&lt;h2 id="rest"&gt;REST&lt;/h2&gt;

&lt;p&gt;Exploring REST libraries is trivial as there are many good options. I looked at&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Yada&lt;/li&gt;
  &lt;li&gt;Pedestal with Rook&lt;/li&gt;
  &lt;li&gt;Liberator&lt;/li&gt;
  &lt;li&gt;Compojure only&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compojure is still an option but I found that the REST libraries are mature and simple. For this time, I went with Liberator as it works nicely with Compojure which I have some experience with.&lt;/p&gt;

&lt;h2 id="module-system"&gt;Module system&lt;/h2&gt;

&lt;p&gt;A module system allows to define modules and dependencies between them. You can start your system and all modules are started depending on their relation and order.
 A module might read configuration files, another one connect to the DB, start scheduler for cron jobs etc. I liked &lt;em&gt;tolituis/mount&lt;/em&gt;. Integrant is a new candidate with nice concepts but it relies on a very fresh Clojure version.
 For know I postponed using a module system at all, because currently the complexity is not needed. If you are interested, here are some options&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="https://github.com/stuartsierra/component"&gt;https://github.com/stuartsierra/component&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://github.com/weavejester/integrant"&gt;https://github.com/weavejester/integrant&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://github.com/tolitius/mount"&gt;https://github.com/tolitius/mount&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id="testing"&gt;Testing&lt;/h2&gt;

&lt;p&gt;I used &lt;em&gt;Midje&lt;/em&gt; in the past and had a look at alternatives.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Plain clojure test with &lt;em&gt;aviso pretty&lt;/em&gt; to nicely show test results.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Expectations&lt;/em&gt; with &lt;em&gt;lein-test-refresh&lt;/em&gt; to execute tests automatically&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Midje&lt;/em&gt; in combination with &lt;em&gt;lein midje&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, all solutions are good solutions. Test failures are very clear and precise. Java please have a look. ;-)&lt;/p&gt;

&lt;p&gt;I compared the test runners. Basically, they execute the tests if a test or code is modified. After saving your file, you can see the results in fractions of a second. If you are into TDD this is a productiviy turbo boost.&lt;/p&gt;

&lt;p&gt;Expectations&lt;/p&gt;

&lt;p&gt;Tests written in Java are verbose, tests written in Clojure are way more conside and small, but this library pushes it to an extreme that is very impressive. If too much code is an issue, have a look at it.
The latest versions integrate nicely with standard Clojure test runners as well. It is really worth looking at it.&lt;/p&gt;

&lt;p&gt;Aviso&lt;/p&gt;

&lt;p&gt;Use it to improve test output with standard clojure test significantly&lt;/p&gt;

&lt;p&gt;Midje&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Nice and powerful assertions&lt;/li&gt;
  &lt;li&gt;Good support for mocks and pre/post executed code&lt;/li&gt;
  &lt;li&gt;Asserts do not look like very “Clojure style”&lt;/li&gt;
  &lt;li&gt;Very efficient execution of only relevant tests on code change&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The impressive thing of the &lt;em&gt;lein midje :autotest&lt;/em&gt; is that it &lt;em&gt;only&lt;/em&gt; executes, depending on what you change, the modified test or all tests refering the modified code. This is amazing.&lt;/p&gt;

&lt;p&gt;In this case the test execution was the argument to prefer &lt;em&gt;Midje&lt;/em&gt; over the other options.&lt;/p&gt;

&lt;h2 id="other-stuff"&gt;Other stuff&lt;/h2&gt;

&lt;p&gt;I stumbled upon libraries while looking for security and scheduler. I did not explore them in detail, but the first impression was nice, so I decided to note them here.&lt;/p&gt;

&lt;p&gt;Security: &lt;a href="https://funcool.github.io/buddy-auth/latest"&gt;https://funcool.github.io/buddy-auth/latest&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scheduler (Later): &lt;a href="http://docs.caudate.me/hara/hara-io-scheduler.html"&gt;http://docs.caudate.me/hara/hara-io-scheduler.html&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;

&lt;p&gt;The first version of the software is ready by now and there is one thing I appreciate a lot using Clojure: &lt;em&gt;simplicity&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is what we achieved&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Read configuration file from Tomcat data directory or fall back to a configuration in the classpath based on an environment &lt;em&gt;test&lt;/em&gt; or &lt;em&gt;development&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Logger integration using an external configuration or as fall back a configuration in the classpath&lt;/li&gt;
  &lt;li&gt;Scheduler integration&lt;/li&gt;
  &lt;li&gt;Connection pools&lt;/li&gt;
  &lt;li&gt;No connection pool for import job&lt;/li&gt;
  &lt;li&gt;Tests for REST services, database and unit tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other projects, I use technologies like Java, JEE, Spring, Java Persistence/Hibernate. If you have experience setting up a customized Spring configuration, you probably have an idea what complexity is.
  It requires days of dedication to have a Spring application with mixed security for legacy and REST services nicely in place. But still at the point it works, you do not understand all pieces. Java libraries have a strong tendency to support
  old approaches they offered once. The downside is if you solve a problem, you find documentation using one approach, another or a mixture of many.&lt;/p&gt;

&lt;p&gt;Given my basic Clojure experience, I was impressed how quick everything was in place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When it comes to simplicity, Clojure rocks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Best Regards / Viele Grüße&lt;/p&gt;

&lt;p&gt;Sebastian Hennebrueder&lt;/p&gt;
</content>
    <summary type="html">In the process of replacing Java based REST services, I explored to use Clojure as an alternative</summary>
  </entry>
  <entry>
    <id>tag:www.laliluna.de,2014-12-12:/articles/2014/12/12/angular-restservice-seed.html</id>
    <title type="html">An Angular template for Java and Clojure REST services</title>
    <published>2014-12-12T00:00:00Z</published>
    <updated>2014-12-12T00:00:00Z</updated>
    <link rel="alternate" href="/articles/2014/12/12/angular-restservice-seed.html"/>
    <content type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;I created a clean and lean template for AngularJS development, which allows to easily plugin a Java or Clojure backend.&lt;/p&gt;
&lt;p&gt;It includes&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Module based structure for &lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;Test automation: &lt;span class="caps"&gt;GUI&lt;/span&gt; unit and end to end tests&lt;/li&gt;
	&lt;li&gt;Bootstrap and font awesome&lt;/li&gt;
	&lt;li&gt;Sass stylesheets&lt;/li&gt;
	&lt;li&gt;Live reload for &lt;span class="caps"&gt;GUI&lt;/span&gt; and Clojure backend&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is published under Apache License.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/laliluna/angular-rest-seed"&gt;https://github.com/laliluna/angular-rest-seed&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Best Regards / Viele Grüße&lt;/p&gt;
&lt;p&gt;Sebastian Hennebrueder&lt;/p&gt;</content>
    <summary type="html">A lean Angular template for Java and Clojure development. Includes GUI unit and end to end tests, Bootstrap, Sass stylesheets, live reloading.</summary>
  </entry>
  <entry>
    <id>tag:www.laliluna.de,2014-09-05:/articles/2014/09/05/building-angular-clojure.html</id>
    <title type="html">Understanding JavaScript GUI builds for Java and Clojure developer</title>
    <published>2014-09-05T00:00:00Z</published>
    <updated>2014-09-05T00:00:00Z</updated>
    <link rel="alternate" href="/articles/2014/09/05/building-angular-clojure.html"/>
    <content type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Imagine you want to build an application with a Java or Clojure backend, exposing services via &lt;span class="caps"&gt;REST&lt;/span&gt;. The services are consumed by a JavaScript application using AngularJS.&lt;/p&gt;
&lt;p&gt;In article, I summarize the experience I made to develop, test, build and release applications with mixed technologies. I will give you an introduction into JavaScript tooling and share my experience how to integrate the &lt;span class="caps"&gt;GUI&lt;/span&gt; with a Java or Clojure backend.&lt;/p&gt;
&lt;h2&gt;JavaScript build tool ecosystem&lt;/h2&gt;
&lt;p&gt;The JavaScript ecosystem is amazing. You will find well designed tools, each one with a defined but limited responsibility, which allows to combine them into powerful tool chains. It is enlightening coming from a Java Maven background. The Java world has a tendency to create things like &amp;#8216;the coffee making, water distributing, ice machine, soap bubble making bicycle&amp;#8217;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Task runner&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A task runner can execute tasks, define dependencies between them, run them in parallel or sequential but very important they don&amp;#8217;t know much about the tasks themselves. &lt;a href="http://gulpjs.com"&gt;Gulp&lt;/a&gt; &lt;a href="http://gruntjs.com"&gt;Grunt&lt;/a&gt; and &lt;a href="http://brunch.io"&gt;Brunch&lt;/a&gt; fall into this category.&lt;/p&gt;
&lt;p&gt;Combined with plugins the task runner can do anything you need to do with a JavaScript web application.&lt;/p&gt;
&lt;p&gt;Here is an extract of a task definition using Gulp. It compiles Sass style sheets into normal &lt;span class="caps"&gt;CSS&lt;/span&gt; and send a desktop notification, if it succeeds or fails.&lt;/p&gt;
&lt;pre class="prettyprint lang-javascript"&gt;
	// load plugins
	var gulp = require('gulp'),
    	minifycss = require('gulp-minify-css'),
    	notify = require('gulp-notify'),
    	source = require('vinyl-source-stream'),
    	streamify = require('gulp-streamify'),
    	uglify = require('gulp-uglify'),
    	sass = require('gulp-ruby-sass');

	// define a task	
	gulp.task('styles-sass', function () {
	    return gulp.src(paths.styles_sass)
	            .pipe(sass({ style: 'expanded' }))
	            .on("error", notify.onError(function (error) {
	                return "CSS problem: " + error.message;
	            }))
	            .pipe(gulp.dest('dist/dev/styles'))
	            .pipe(notify({ message: 'Saas styles task complete' }));
	});	
&lt;/pre&gt;
&lt;p&gt;A typical JavaScript build file consists of small tasks. Whenever you need to achieve something, just search for a plugin using something like &amp;#8220;Grunt minify &lt;span class="caps"&gt;CSS&lt;/span&gt;&amp;#8221; or &amp;#8220;Gulp compress JavaScript&amp;#8221;.&lt;/p&gt;
&lt;p&gt;To describe the three task executors shortly: Grunt has the largest plugin collection, Gulp is more efficient has it uses pipes to pass the output from one step into the next, Brunch is the youngest and makes heavy use of conventions over configurations, which makes it very easy to setup but on the other hand sometimes harder to understand and to adapt. After trying out each of them, I choose Gulp. But this is a matter of personal preferences. Each tool has its shiny sites.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dependency management&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Maven or Clojars equivalent in the JavaScript world are &lt;a href="https://www.npmjs.org/doc/"&gt;&lt;span class="caps"&gt;NPM&lt;/span&gt;&lt;/a&gt; and &lt;a href="http://bower.io"&gt;Bower&lt;/a&gt;. Both help dealing with fetching dependencies. &lt;span class="caps"&gt;NPM&lt;/span&gt; provides dependencies in a format suitable for JavaScript backend application. Combined with a tool like Browserify which packs the dependency into a single file, it can be used for JavaScript in the browser as well. Bower is already intended to be used with Browser applications. Both are viable solutions.&lt;/p&gt;
&lt;p&gt;You will probably always use &lt;span class="caps"&gt;NPM&lt;/span&gt; to install all other tools needed for development.&lt;/p&gt;
&lt;p&gt;Writing JavaScript modules is not trivial, as you need to target both &lt;span class="caps"&gt;NPM&lt;/span&gt; and Bower. It is worth to invest some time understanding how they work. Especially in larger &lt;span class="caps"&gt;GUI&lt;/span&gt; applications you need a form of modularization to avoid naming conflicts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scaffolding&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There is a good chance that you run into &lt;a href="http://yeoman.io"&gt;Yeoman&lt;/a&gt; as well. It helps to quickly start building a JavaScript application. If you want to have an AngularJS application including build script, test runner and an application template, just type:&lt;/p&gt;
&lt;p&gt;yeoman init angular&lt;/p&gt;
&lt;p&gt;Alternatively, there is large choice of &lt;em&gt;boilerplate tempates&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Development&lt;/h2&gt;
&lt;p&gt;For development there is a list of typical tasks for a JavaScript application.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Quality check the JavaScript code using JSHint or JSLint&lt;/li&gt;
	&lt;li&gt;Package all required libraries&lt;/li&gt;
	&lt;li&gt;Concatenate all your JavaScript code&lt;/li&gt;
	&lt;li&gt;Transform your Saas or &lt;span class="caps"&gt;LESS&lt;/span&gt; style sheets into normal &lt;span class="caps"&gt;CSS&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;Copy fonts, &lt;span class="caps"&gt;HTML&lt;/span&gt; files and images&lt;/li&gt;
	&lt;li&gt;Execute unit and end to end tests&lt;/li&gt;
	&lt;li&gt;Automatically reload the browser if anything has changed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All this can be achieved with plugins for Gulp, Grunt or Brunch. The automated test execution, reloading and quality check are very useful. Every time you save a file, you get a feedback fractions of a second later.&lt;/p&gt;
&lt;p&gt;To get an impression, how to configure such a build file, I found it helpful to develop it step by step from scratch and then compare it to existing solutions.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="https://github.com/ngbp/ngbp"&gt;AngularJS template&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Templates created by yeoman&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next thing is how to integrate the JavaScript &lt;span class="caps"&gt;GUI&lt;/span&gt; with a deployed Java or Clojure backend.&lt;/p&gt;
&lt;p&gt;A very good way to achieve this is using a JavaScript web server with integrated proxy. It is a normal web server serving requests from a defined directory. In addition a &lt;span class="caps"&gt;URL&lt;/span&gt; like &lt;em&gt;/api&lt;/em&gt; can be defined to be forwarded to a backend running under its own port.&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/articles/any/proxy.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why not using backend tools to build the JavaScript application?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Gradle and even Maven has extensions to build JavaScript applications. The answer is simple. If you go swimming what do you pick: flippers or a bucket of heavy stones.&lt;/p&gt;
&lt;p&gt;The JavaScript build tools are much more advanced, used by many more people and are very easy to adapt to your own needs.&lt;/p&gt;
&lt;h2&gt;Packaging for Production&lt;/h2&gt;
&lt;p&gt;For production &lt;span class="caps"&gt;CSS&lt;/span&gt;, JavaScript and libraries needs to be minimized. If the backend and the &lt;span class="caps"&gt;GUI&lt;/span&gt; is packaged as single application, the JavaScript application is copied into the web directories of the backend project.&lt;/p&gt;
&lt;p&gt;In the past, I achieved this by adding a task to the Gulp or Grunt build. The reason, I am controlling this from the JavaScript and not the backend build script, is that the JavaScript task runners are way easier to adapt. Neither of tools like Maven or Gradle (Java world) or leiningen (Clojure world) is as flexible.&lt;/p&gt;
&lt;h2&gt;Releasing&lt;/h2&gt;
&lt;p&gt;Typical tasks to release a project are&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;run production build for backend and &lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;run tests&lt;/li&gt;
	&lt;li&gt;remove snapshot suffix for production release in backend and &lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;commit and tag version&lt;/li&gt;
	&lt;li&gt;upload application to a repository (Nexus etc)&lt;/li&gt;
	&lt;li&gt;bump up version in backend and &lt;span class="caps"&gt;GUI&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;commit with new version&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I found this part a bit tricky. Releasing can be both controlled from the task runner and the backend build script or even a third script controlling both. I used the backend build script in the past to do the actual release, but triggered the JavaScript task runner before doing this from an outside script.&lt;/p&gt;
&lt;p&gt;Other solution, I encountered:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Rake (The smart Ruby buildtool) to control both JavaScript and backend build&lt;/li&gt;
	&lt;li&gt;Control everything from the JavaScript task runner&lt;/li&gt;
	&lt;li&gt;Control everything from the Java or Clojure build tool. I did this once with Gradle in a Java project.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;This overview should get you started easier in building mixed builds. Feel free to sent me comments with your own experiences.&lt;/p&gt;</content>
    <summary type="html">A guide for Java and Clojure developer to learn how to build and release mixed applications using a JavaScript GUI and CLojure or Java backends.</summary>
  </entry>
  <entry>
    <id>tag:www.laliluna.de,2014-04-28:/articles/2014/04/28/clojure-async-kindergarden-party.html</id>
    <title type="html">Clojure Async - Kindergarden Party</title>
    <published>2014-04-28T00:00:00Z</published>
    <updated>2014-04-28T00:00:00Z</updated>
    <link rel="alternate" href="/articles/2014/04/28/clojure-async-kindergarden-party.html"/>
    <content type="html">&lt;h1&gt;Clojure Async Channels: Kindergarden Party&lt;/h1&gt;
&lt;p&gt;Let&amp;#8217;s learn about Clojure async channels by organizing a kindergarden party.&lt;/p&gt;
&lt;p&gt;The parents bake cake and bring them to the event. Cake has to be cut in pieces, put on tables etc. Everybody is doing something to make it a nice event.&lt;/p&gt;
&lt;h2&gt;Preparation&lt;/h2&gt;
&lt;p&gt;Create a new leiningen project and update the project.clj to&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(defproject sample "0.1.0-SNAPSHOT"
  :dependencies [[org.clojure/clojure "1.5.1"]
                 [org.clojure/core.async "REPLACE_THIS_WITH_THE_LATEST_VERSION_ON_http://clojure.github.io/core.async/"]
                 [org.jgroups/jgroups "3.4.4.Final"]])
&lt;/pre&gt;
&lt;h2&gt;Handing over a cake&lt;/h2&gt;
&lt;p&gt;Anne is preparing the table with the cakes. She takes a cake and puts it on a table.&lt;/p&gt;
&lt;p&gt;Open a &lt;span class="caps"&gt;REPL&lt;/span&gt; session to execute the code.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(require '[clojure.core.async :refer :all])
&lt;/pre&gt;
&lt;p&gt;Create a channel:&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(def anne (chan))
&lt;/pre&gt;
&lt;p&gt;Let Anne wait in the background:&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(thread (println "Put" (&amp;lt;!! anne) "on the table"))
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&amp;lt;!!&lt;/strong&gt; reads from a channel and waits until something is put onto the channel.&lt;/p&gt;
&lt;p&gt;A crib for me: The channel is !! and you send something to it &amp;gt;!! or read from it &amp;lt;!!&lt;/p&gt;
&lt;p&gt;Pass the cake to the channel.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(&amp;gt;!! anne "Apple cake")
&lt;/pre&gt;
&lt;p&gt;And we see:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Put Apple cake on the table&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A channel is blocking. If you write to a channel, you will wait until a read from this channel happens.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Tuning our code a bit&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Our code is not very efficient.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(thread (println "Put" (&amp;lt;!! anne) "on the table"))
&lt;/pre&gt;
&lt;p&gt;This code created a thread waiting in the background. This blocks a &lt;span class="caps"&gt;JVM&lt;/span&gt; thread even if Anne is doing nothing. You can verify it by starting a &lt;strong&gt;jconsole&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;To improve, we can use a &lt;em&gt;go block&lt;/em&gt;. It runs in the background but releases the background thread when Anne is doing nothing. In a &lt;em&gt;go block&lt;/em&gt; &lt;em&gt;&amp;lt;!&lt;/em&gt; is used instead of &lt;strong&gt;&amp;lt;!!&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(go (println "Put" (&amp;lt;! anne) "on the table"))
&lt;/pre&gt;
&lt;p&gt;Next, let Anne take over the job for a while and simulate parents bringing a couple of cakes over time.&lt;/p&gt;
&lt;p&gt;Anne:&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(go (loop [cake (&amp;lt;! anne)]
       (if cake
          (do (println (str "Anne puts " cake " cake on the table"))
              (Thread/sleep 1000)
              (recur (&amp;lt;! anne)))
          (println (str "I, Anne go home")))))
&lt;/pre&gt;
&lt;p&gt;Or a bit shorter:&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(go-loop [cake (&amp;lt;! anne)]
	     (if cake
	         (do (println (str "Anne puts " cake " cake on the table"))
	             (Thread/sleep 1000)
	             (recur (&amp;lt;! anne)))
	         (println (str "I, Anne go home"))))
&lt;/pre&gt;
&lt;p&gt;The parents:&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(go (doseq [cake ["Apple" "Pineapple" "Chocolade" "Creme"]]
	    (println "About to deliver cake " cake)
	    (&amp;gt;! anne cake)
	    (Thread/sleep (rand-int 1000))))
&lt;/pre&gt;
&lt;p&gt;A closed channel returns nil. If you close the channel, Anne is going home. :&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(close! anne)
&lt;/pre&gt;
&lt;p&gt;The problem we are facing is that parents are queuing up, as there are too many cakes. So we setup a small table where the parents can at least put 2 cakes, which are then taken by Anne. Basically, we create a buffered channel.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(def anne (chan 2))
&lt;/pre&gt;
&lt;p&gt;Holger starts helping Anne now. So we introduce the small table as channel and both Anne and Holger fetch cake from it to place it on the tables.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(defn put-cake-on-the-table [name in-table]
	(go-loop [cake (&amp;lt;! in-table)]
	       (if cake
	         (do (println (str name " puts " cake " cake on the table"))
	             (Thread/sleep 1000)
	             (recur (&amp;lt;! in-table)))
	         (println (str "I," name " go home")))))
	
(def small-table (chan 2))
(put-cake-on-the-table "Anne" small-table)
(put-cake-on-the-table "Holger" small-table)
&lt;/pre&gt;
&lt;p&gt;Let&amp;#8217;s introduce a method for delivering cakes.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(defn deliver-some-cakes [table]
	(go (doseq [cake ["Apple" "Pineapple" "Chocolade" "Creme"]]
	    (println (str "About to deliver cake " cake))
	    (&amp;gt;! table cake)
	    (Thread/sleep (rand-int 1000)))))
	
(deliver-some-cakes small-table)	
&lt;/pre&gt;
&lt;h2&gt;Splitting work&lt;/h2&gt;
&lt;p&gt;Anne and Holger are going to specialize. Anne takes only fruit cakes whereas Holger takes all other cakes.&lt;/p&gt;
&lt;p&gt;We can achieve this using a splitter.&lt;/p&gt;
&lt;p&gt;A cake is now a map: &lt;em&gt;{:name &amp;#8220;Apple&amp;#8221; :type &amp;quot;fruit&amp;quot;}&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;First we enhance the &lt;em&gt;put-cake-on-the-table&lt;/em&gt; and &lt;em&gt;deliver-some-cake&lt;/em&gt; methods to work with a map.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(defn put-cake-on-the-table [name in-table]
	(go-loop [{cake :name} (&amp;lt;! in-table)]
	       (if cake
	         (do (println (str name " puts " cake " cake on the table"))
	             (Thread/sleep 2000)
	             (recur (&amp;lt;! in-table)))
	         (println (str "I," name " go home")))))
	
(defn deliver-some-cakes [in-table]
	(go (doseq [{:keys [name] :as cake} [{:name "Apple" :type "fruit"}
	                          {:name "Pineapple" :type "fruit"}
	                          {:name "Chocolade" :type "other"}
	                          {:name "Creme" :type "other"}]]
	    (println (str "About to deliver cake " name))
	    (&amp;gt;! in-table cake)
	    (println (str "Delivered cake " name))
	    (Thread/sleep (rand-int 1000)))))
&lt;/pre&gt;
&lt;p&gt;Then we can split the work.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(def small-table (chan 2))
(let [[cake-for-anne cake-for-holger] (split #(= (:type %) "fruit") small-table)]
	(put-cake-on-the-table "Anne" cake-for-anne)
	(put-cake-on-the-table "Holger" cake-for-holger))
(deliver-some-cakes small-table)
&lt;/pre&gt;
&lt;p&gt;Next Karl is going to help out. He is making small labels for every cake, before Anne and Holger put them on the tables.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(defn make-label [my-name in-table me]
	(go-loop [{name :name :as cake} (&amp;lt;! in-table)]
	       (if cake
	         (do (println (str my-name " makes label for " name))
	             (&amp;gt;! me cake)
	             (recur (&amp;lt;! in-table))))))

(def karl (chan))
(def small-table (chan 2))
(let [[cake-for-anne cake-for-holger] (split #(= (:type %) "fruit") karl)]
	(put-cake-on-the-table "Anne" cake-for-anne)
	(put-cake-on-the-table "Holger" cake-for-holger))
(make-label "Karl" small-table karl)
(deliver-some-cakes small-table)
&lt;/pre&gt;
&lt;h2&gt;Merging work&lt;/h2&gt;
&lt;p&gt;Judie has a nice hand writing and starts writing labels as well. Anne and Holger can now take cakes from both of them.&lt;/p&gt;
&lt;p&gt;We can merge messages from two channels into one using &lt;em&gt;merge&lt;/em&gt;.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(def karl (chan))
(def judie (chan))
(def small-table (chan 2))
(let [[cake-for-anne cake-for-holger] (split #(= (:type %) "fruit") 
(merge [karl judie]))]
	(put-cake-on-the-table "Anne" cake-for-anne)
	(put-cake-on-the-table "Holger" cake-for-holger))
(make-label "Karl" small-table karl)
(make-label "Judie" small-table judie)
(deliver-some-cakes small-table)
&lt;/pre&gt;
&lt;h2&gt;Alternating&lt;/h2&gt;
&lt;p&gt;As more and more cakes are delivered, the small entry table has not enough capacity. We set up a second table and ask Karl and Judie to take cakes from both tables.&lt;/p&gt;
&lt;p&gt;If no cake is their, they just do nothing for a moment.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(defn make-label [my-name in-tables me]
	(go-loop [[{name :name :as cake} _] (alts! in-tables :default "nothing")]
	       (if cake
	         (do
	           (if (= cake "nothing")
	             (do (println "Do nothing for a moment")
	                 (Thread/sleep 500))
	             (do (println (str my-name " makes label for " name))
	                 (&amp;gt;! me cake)))
	           (recur (alts! in-tables :default "nothing")))
	         (println (str my-name " goes home")))))

(def karl (chan))
(def judie (chan))
(def small-table-1 (chan 2))
(def small-table-2 (chan 2))
(let [[cake-for-anne cake-for-holger] (split #(= (:type %) "fruit")
	                                         (merge [karl judie]))]
	(put-cake-on-the-table "Anne" cake-for-anne)
	(put-cake-on-the-table "Holger" cake-for-holger))
(make-label "Karl"  [small-table-1 small-table-2] karl)
(make-label "Judie" [small-table-1 small-table-2] judie)
(deliver-some-cakes small-table-1)
&lt;/pre&gt;
&lt;p&gt;The function &lt;strong&gt;alts!&lt;/strong&gt; alternates between a vector of channel. It none of the channel contains messages, it can block or fall back to a default value.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(alts! in-tables :default "nothing")
&lt;/pre&gt;
&lt;p&gt;You can use alts! to write to different channels as well.&lt;/p&gt;
&lt;h2&gt;Timeout&lt;/h2&gt;
&lt;p&gt;Karl and Judie decide not wait for ever for cakes. If no cake is delivered for a long time, they go home.&lt;/p&gt;
&lt;p&gt;This can be achieved by adding a timeout channel to the &lt;em&gt;alts!&lt;/em&gt; function. It creates a channel which closes after the defined milliseconds. A closed channel returns nil.&lt;/p&gt;
&lt;p&gt;The modified method looks like&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(defn make-label [my-name in-tables me]
	(go-loop [[{name :name :as cake} _] (alts! (cons (timeout 5000) in-tables))]
		(if cake
	       (do (println (str my-name " makes label for " name))
	           (&amp;gt;! me cake)
	           (recur (alts! (cons (timeout 500) in-tables))))
	       (println (do (println (str my-name " does nothing for a moment"))
	                    (Thread/sleep 500))))))
							

(def karl (chan))
(def judie (chan))
(def small-table-1 (chan 2))
(def small-table-2 (chan 2))
(let [[cake-for-anne cake-for-holger] 
	(split #(= (:type %) "fruit") (merge [karl judie]))]
	(put-cake-on-the-table "Anne" cake-for-anne)
	(put-cake-on-the-table "Holger" cake-for-holger))
(make-label "Karl"  [small-table-1 small-table-2] karl)
(make-label "Judie" [small-table-1 small-table-2] judie)
(deliver-some-cakes small-table-1)
&lt;/pre&gt;
&lt;h2&gt;Network&lt;/h2&gt;
&lt;p&gt;If we need more computing power, we can start distributing the application across multiple computers. So we need a channel, which actually writes to a remote channel.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s write a simple solution using reliable messaging via JGroups.&lt;/p&gt;
&lt;p&gt;The basic usage pattern is to create a channel, connect to a cluster name, set a receiver to react on incoming messages and to use the channel to send messages.&lt;/p&gt;
&lt;p&gt;Use the following to use the JGroups default configuration. It uses &lt;span class="caps"&gt;UDP&lt;/span&gt; multicast for node detection.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(def c (org.jgroups.JChannel.))
&lt;/pre&gt;
&lt;p&gt;Or specify a customized configuration if you like.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(def c (org.jgroups.JChannel. (clojure.java.io/resource "jgroups.xml")))

(def r (reify org.jgroups.Receiver
         (receive [this msg]
           (println (.getObject msg) (.getSrc msg)))
         (viewAccepted [this view]
           (println view))))
(.setReceiver c r)
(.connect c "foo")
(.send c nil "hello")
&lt;/pre&gt;
&lt;p&gt;If you struggle sending messages, have a look in the JGroups documentation. It has a trouble shooting section.&lt;/p&gt;
&lt;p&gt;It is easier, to use JGroups messaging, if we provide a couple of utility classes. Let&amp;#8217;s built a channel which sends messages to remote addresses and a receiver which passes&lt;br /&gt;
the message to a local channel.&lt;/p&gt;
&lt;p&gt;Here is the source code.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(ns sample.jgroups-async
	(:import (org.jgroups Channel Address Receiver))
	(:require [clojure.core.async.impl.protocols :as protocols]
	      [clojure.core.async.impl.channels :as channels]
	      [clojure.core.async :refer [close! &amp;gt;!!]]))
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;clojure.core.async&lt;/strong&gt; defines protocols. If you implement &lt;em&gt;WritePort&lt;/em&gt;, then you can use your channel with the async &lt;span class="caps"&gt;API&lt;/span&gt; &lt;em&gt;&amp;gt;!!&lt;/em&gt; to send messages.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(deftype JgroupsWriteChannel [^Channel jgroups-channel ^Address target-address]
	protocols/WritePort
	(protocols/put! [port val fn0-handler]
		(when (nil? val)
			(throw (IllegalArgumentException. "Can't put nil on Jgroups channel")))
			(.send jgroups-channel (org.jgroups.Message. target-address nil val))
			(channels/box nil))
	protocols/Channel
	(protocols/close! [chan]
		(.close jgroups-channel)))
&lt;/pre&gt;
&lt;p&gt;A factory method bootstraps JGroups and creates instances of the &lt;em&gt;JGroupsWriteChannel&lt;/em&gt;.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(defn create-write-channel [cluster-name target-address]
	(let [jc (org.jgroups.JChannel.)]
	(.setReceiver jc (reify Receiver
	                   (viewAccepted [this view]
	                     (println view))))
	(.connect jc cluster-name)
	(JgroupsWriteChannel. jc target-address)))
&lt;/pre&gt;
&lt;p&gt;The receiver is composed of a JGroups channel and a async channel.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(deftype JgroupsReceiver [jgroups-channel local-channel]
	protocols/Channel
	(protocols/close! [chan]
	(.close jgroups-channel)
	(close! local-channel)))
&lt;/pre&gt;
&lt;p&gt;A factory method bootstraps JGroups and creates instances of &lt;em&gt;JgroupsReceiver&lt;/em&gt;.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(defn create-remote-receiver
	[cluster-name port]
	(let [jc (org.jgroups.JChannel.)]
		(.setReceiver jc (reify Receiver
	    	(receive [this msg] (&amp;gt;!! port (.getObject msg)))
        	(viewAccepted [this view] (println view))))
	(.connect jc cluster-name)
	(JgroupsReceiver. jc port)))
&lt;/pre&gt;
&lt;p&gt;Let&amp;#8217;s play with it.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(require '[clojure.core.async :refer :all])
(def anne (create-remote-receiver "foo" (chan)))
(def joe (create-write-channel "foo" (.getAddress(.jgroups_channel anne))))
(go-loop [m (&amp;lt;! (:local-channel anne))] 
	(if m (do (println "Anne " m)
		(recur (&amp;lt;! (:local-channel anne))))))
&lt;/pre&gt;
&lt;p&gt;Now, we can send messages around&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(&amp;gt;!! joe "Hello Anne")
&lt;/pre&gt;
&lt;p&gt;Once you are done, close the JGroups cluster and the channels.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;	
(doseq [c [anne joe]] (close! c))
&lt;/pre&gt;
&lt;p&gt;As an exercise, try to split the cake preparation steps across two nodes.&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;p&gt;If you ever wanted to parallelize processing in an application, Clojure async is a great tool set to achieve this. I hope you enjoyed the article.&lt;/p&gt;
&lt;p&gt;Sebastian Hennebrueder&lt;/p&gt;</content>
    <summary type="html">A hands-on workshop to build asynchronous applications with Clojure</summary>
  </entry>
  <entry>
    <id>tag:www.laliluna.de,2013-10-29:/articles/2013/10/29/clojure-destructuring.html</id>
    <title type="html">Beautiful Clojure - destructuring data</title>
    <published>2013-10-29T00:00:00Z</published>
    <updated>2013-10-29T00:00:00Z</updated>
    <link rel="alternate" href="/articles/2013/10/29/clojure-destructuring.html"/>
    <content type="html">&lt;h1&gt;Beautiful Clojure &amp;#8211; Destructuring data&lt;/h1&gt;
&lt;h2&gt;What is destructuring?&lt;/h2&gt;
&lt;p&gt;Destructuring is one of the beautiful features which impressed me, when learning Clojure. It helps you to assign individual elements of a vector/list or map to variables. You can destructure function parameters as well as return values.&lt;/p&gt;
&lt;h2&gt;A first example&lt;/h2&gt;
&lt;p&gt;Imagine a function which returns the age of the youngest and the oldest person in a sport club.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(defn find-min-max-age [club]
  (let [min-age (calculate-min-age club)
        max-age (calculate-max-age club)]
    [min-age max-age]))
&lt;/pre&gt;
&lt;p&gt;The vector which is returned can be assigned directly to two variables: min and max.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(let [[min max] (find-min-max-age "Swim Club")]
  (println "Youngest member is " min)
  (println "Oldest member is " max))
&lt;/pre&gt;
&lt;p&gt;I like this elegant approach a lot. It is much more compact as a comparable Java version, which requires additional code to deal with null values.&lt;/p&gt;
&lt;pre class="prettyprint lang-java"&gt;
    Integer[] minMax = findMinMax("Swim Club");
    Integer min = minMax.length &amp;gt; 0 ? minMax[0] : null;
    Integer max = minMax.length &amp;gt; 1 ? minMax[1] : null;
    System.out.println("Youngest member is " + min);
    System.out.println("Oldest member is " + max);
&lt;/pre&gt;
&lt;h2&gt;More vector examples&lt;/h2&gt;
&lt;p&gt;You can destructure function parameters as well. It just works every where.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(defn find-team-member [[min max]] 
	(println min max))
	
; Calling the function
(find-team-member [5 20])
&lt;/pre&gt;
&lt;p&gt;As well, you can ignore values. To ignore values at the end of the vector, just leave off the variables.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(let [[min] (find-min-max-age "Rugby Club")]
  (println "Youngest member is" min))
&lt;/pre&gt;
&lt;p&gt;To ignore values at a specific place, just use _ as the variable name. It is a common convention.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(let [[_ max] (find-min-max-age "Kite Surfing Club")]
  (println "Oldest member is" max))
&lt;/pre&gt;
&lt;h2&gt;Destructuring maps&lt;/h2&gt;
&lt;p&gt;Clojure separates functions and data. Maps are frequently used to store data and they can be destructured as well.&lt;/p&gt;
&lt;p&gt;The following function expects a map as parameter. It extracts the values for the keys &lt;em&gt;min&lt;/em&gt; and &lt;em&gt;max&lt;/em&gt; and assigns them to variable named &lt;em&gt;min, max&lt;/em&gt; respectively.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(defn find-team-member[ {:keys [min max]} ] 
	(println min max))

; Let us use our function
(find-team-member {:min 5 :max 10})
&lt;/pre&gt;
&lt;p&gt;The destructuring of a map is expressed as a map. What could be more concise?&lt;/p&gt;
&lt;p&gt;If you need to get hold of the whole map, you can add a special key &lt;em&gt;:as&lt;/em&gt; to the map.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(defn find-team-member[ {:keys [min max] :as all-data} ] 
	(println min max all-data))

; Let us use our function
(find-team-member {:min 5 :max 10 :foo "some value"})
&lt;/pre&gt;
&lt;h3&gt;Default values for maps&lt;/h3&gt;
&lt;p&gt;To specify default values for maps, just add a key &lt;em&gt;:or&lt;/em&gt; and a map describing those values.&lt;/p&gt;
&lt;pre class="prettyprint lang-clojure"&gt;
(defn find-team-member[ {:keys [min max] :or {min 3 max 20}}] 
	(println min max))
&lt;/pre&gt;
&lt;p&gt;I hope you enjoyed the article.&lt;/p&gt;</content>
    <summary type="html">Introduction into beautiful features in Clojure</summary>
  </entry>
</feed>
 