The REPL turns one! 🎂

The REPL turns one! 🎂

Efficient matrices, and lisp editing
View this email in your browser

The REPL

Notes.

  • The REPL turns one this week. Thanks to everyone who has read it, shared it with friends and colleagues, and sent me links.

-main

Libraries & Books.

  • Larch is an Elm like ClojureScript SPA framework
  • Ring-SSE from Bobby Calderwood
  • Haslett is a websocket library for ClojureScript

People are worried about Types. ?

Tools.

Recent Developments.

Learning.

  • Guide to Reagent from PurelyFunctional.tv
  • I'm not sure if there's an online link for this, but I got an email recently saying that Clojure/conj and Clojure/west are merging next year for one larger conference.
Copyright © 2017 Daniel Compton, All rights reserved.


Want to change how you receive these emails?
You can update your preferences or unsubscribe from this list

Email Marketing Powered by MailChimp

Permalink

Guide to Reagent

Guide to Reagent

Reagent is a ClojureScript wrapper around React. It gives you a way to easily create React components. Reagent has three main features that make it easy to use: using functions to create React components, using Hiccup to generate HTML, and storing state in Reagent Atoms. Reagent lets you write React code that is concise and readable.

React components are functions

Form-1 component

When we're using React from ClojureScript, we are typically using React in a functional programming way. That is, we want to define a function from inputs to DOM tree. Reagent makes this as easy as possible. Just define a function that returns Hiccup. This is called a Form-1 component. The function corresponds to the React render() method.

(defn green-button 
  [:button.green text])

Form-2 component

The next case is slightly more complicated. If you need to initialize something when the component is created, you use a Form-2 component. Form-2 components are functions that return their render function. The outer function will be called once to get the render function. Then the render function will be called each time the component needs to render. If you wrap that inner render function in a let, you can initialize some state in there.

(defn counting-button 
  (let [state (reagent/atom 0)]
    (fn 
      [:button.green
        {:on-click #(swap! state inc)}
        (str text " " @state)])))

Form-3 component

React has a full lifecycle for its components, which includes methods to initialize the component and to perform effects when the component is mounted. There are lots of methods for everything that happens to a component from creation through removal from the DOM. You rarely need access to those, but when you do, Reagent gives you Form-3 components. Form-3 components are functions that return a value created by reagent/create-class.

(defn complex-component [a b c]
  (let [state (reagent/atom {})] ;; you can include state
    (reagent/create-class
      {:component-did-mount
       (fn [] (println "I mounted"))

       ;; ... other methods go here
       ;; see https://facebook.github.io/react/docs/react-component.html#the-component-lifecycle
       ;; for a complete list

       ;; name your component for inclusion in error messages
       :display-name "complex-component"

       ;; note the keyword for this method
       :render-reagent
       (fn [a b c]
         [:div {:class c}
           [:i a] " " b])})))

See Creating Reagent Components for more explanation of the three forms.

Hiccup generates HTML

In normal React, you have two options for generating HTML in your render methods. The first and most common is to use JSX. JSX is a preprocessor to JavaScript that reads in HTML embedded in your JavaScript and turns it into normal React DOM method calls. The second method is to call those methods yourself directly, which is very verbose.

Luckily, Reagent provides a third (and possibly better) approach. Your render function can return Hiccup. Hiccup is a very common way to express HTML inside of Clojure applications. It may already be familiar to you.

Hiccup represents HTML elements as Clojure vectors. You specify the element type with a keyword. The HTML attributes go in a map. And the contents follow inside of the vector. The elements nest well. All-in-all, it is a very elegant way to embed HTML inside of Clojure.

Hiccup is more concise than using the React DOM method calls. But it is also more concise than embedded HTML since you omit the ending tag. It also has shortcuts for id and class attributes.

Reagent adds an extra feature, which is to allow you to embed Reagent components directly into the Hiccup with no extra ceremony. Simply put the component's name in the place of the element name keyword and follow it by its arguments.

;; hiccup to render deeply nested div
[:div#login-form
  [:form {:method :post :action "/login"}
    [username-field] ;; embed Reagent component (defined elsewhere)
    [password-field a b c] ;; note the arguments
    [:button {:type :submit} "Log in"]]]

Notice how easy it is to close those things. No more trouble matching tags.

Reagent Atoms

Applications need state. Part of the magic of good libraries is how that state is managed. Reagent gives us a single, flexible tool for handling state, and it's one you're probably familiar with if you've programmed in Clojure before: Atoms.

Reagent has its own Atoms. They're just like regular Clojure Atoms in every way except they do one extra thing: they keep track of Reagent components who have derefed them. Every time those Atoms change values, the component will be re-rendered.

What that means is that you have very "reactive" way to use state. You can create as many Reagent Atoms as you want. You can write any code you want to modify the states of the Atoms. And your Reagent components will re-render in response. Atoms provide one level of indirection between your app's behavior and how it is rendered.

You create a Reagent Atom by calling reagent/atom.

When will components be re-rendered?

It is very easy to understand when Reagent components will be re-rendered. In fact, there are only two circumstances under which a component will be re-rendered.

The first way is to change the arguments to the component as it is embedded in Hiccup. Here's an example. Let's say you had this Hiccup inside of a component.

[:div
  [my-component a]]

my-component is a component and a is a local variable bound to 1. Let's say that the component that returns this hiccup gets re-rendered, but this time, a is bound to 2. my-component will be re-rendered, since its arguments have changed.

But what made the outer component re-render? Let's zoom out and look at that component.

(defonce state (reagent/atom [1 2]))

(defn big-component []
  (let [[a b] @state]] ;; deref a reagent atom
    [:div
      [my-component a]]))

This big-component derefs a Reagent Atom. The Atom keeps track of all of the components that do so. And whenever that Atom changes, all of the components that derefed it up to that point are re-rendered. That's the second way to re-render a component. Since big-component doesn't have any arguments, reacting to the changing Atom must be how it got re-rendered.

React node lists and keys

React lets you return embed an array of DOM elements inside of a parent element. The elements of the array become the children of the parent. In order to support a fast way to detect changes inside of this array, React suggests that you add a unique and stable key attribute to the elements of the array.

Similarly, Reagent's Hiccup lets you embed seqs as children of other nodes. These are converted to JavaScript arrays when the Hiccup is converted to React DOM. When using seqs of elements, you need to provide keys as well.

The keys should be strings. They should be unique for that seq. And they should be stable. The key is your chance to tell React that this element is the same as the one you rendered last time with the same name.

Here's an example:

(defn student-list [students]
  [:ul
    ;; for returns a seq
    (for [student students]
      [:li {:key (:id student)} ;; stable and unique key
        [:a {:href (:url student)} (:name student)]])])

Reagent components and lazy seqs

There's one more thing. In the above example, where I created a seq, I actually created a lazy seq. This is normally okay. No problem. But sometimes it's not okay. Check out this code:

(defonce student-urls (reagent/atom {}))

(defn student-list [students]
  [:ul
    ;; for returns a lazy seq
    (for [student students]
      [:li {:key (:id student)}
        ;; deref the atom
        [:a {:href (get @student-urls (:id student))}
          (:name student)]])])

Well, this looks almost the same, except with one important difference: you are derefing a Reagent Atom. Why does this matter? Well, the elements of the lazy seq are not created right away. That means that this function will return before the body of the for is run. Since the function has already returned, the Atom doesn't know which Reagent Component it was part of and it won't know to re-render it when it changes.

The trick is to force the lazy seq to be created before you return. Just wrap the lazy seq in a doall.

(defonce student-urls (reagent/atom {}))

(defn student-list [students]
  [:ul
    ;; for returns a lazy seq
    (doall
      (for [student students]
        [:li {:key (:id student)}
          ;; deref the atom
          [:a {:href (get @student-urls (:id student))}
            (:name student)]]))])

Permalink

5 Programming Languages You Should Really Try

For some strange reason, the vast majority of my blog readers are Python Developers. I wrote two articles on Python a long time ago and honestly try to avoid python when I can. So here's an article for you purveyors of Python -- you sultans of snakes.

Note: This article is still likely relevant even if you're not a Pythonista.

For those who aren't aware, Linguistics and Grammars are particularly interesting to me. I really, really enjoy looking into new languages and comparing them to what I already know. Originally, this started as a purely syntactic thing, but as I learned more about compilers, virtual machines, and performance I started to compare those as well. We'll cover a little bit of everything in this post as I suggest a few great languages that you've probably not tried yet. I'll count down in terms of favorites:

5. Nim

Efficient and expressive programming. Nim is a systems and applications programming language. Statically typed and compiled, it provides unparalleled performance in an elegant package.

Nim is a language near and dear to my heart, although I'll be honest and admit that I haven't had as much time with it as I wish. The little I have toyed with the language was a delightful experience. Nim is interesting as it compiles down to C, C++, or JavaScript. This allows you to tackle systems programming in Nim with (almost) the gusto that you'd expect in C or C++. Nim also takes a page from Clojure's book in that it allows you to compile to JavaScript. The build process for Nim is what any systems developer would expect. It's compiled, so you produce a nice portable (dependency-free) binary. Just target your build and run!

Nim is also high extensible via templates and macros. These are processed as compiler time transformations. That's pretty cool, but what if I told you the compiler was extensible too? Well great news, in nim, it is!

Python Developers: Nim takes a ton of concepts from Python's book. Specifically several of the constructs in Nim's standard library are pretty Pythonic.

C, C++, Java Developers: Nim should syntactically look comfortable, but one interesting benefit you'll get with Nim is a configurable garbage collector. You can choose to use a deferring garbage collector or something real-time and deterministic. Pretty neat!

To give you some syntax to compare, here's quicksort in Nim, courtesy of Rosetta Code:

proc quickSort[T](a: var openarray[T], inl = 0, inr = -1) =  
  var r = if inr >= 0: inr else: a.high
  var l = inl
  let n = r - l + 1
  if n < 2: return
  let p = a[l + 3 * n div 4]
  while l <= r:
    if a[l] < p:
      inc l
      continue
    if a[r] > p:
      dec r
      continue
    if l <= r:
      swap a[l], a[r]
      inc l
      dec r
  quickSort(a, inl, r)
  quickSort(a, l, inr)

var a = @[4, 65, 2, -31, 0, 99, 2, 83, 782]  
quickSort a  
echo a  

4. Go

Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.

Google's Go is an interesting language. In fact, Python used to be what I would recommend to people getting into development, but I think I'm at the point that I would recommend go instead now. For those unaware, Go has been around since 2007 although it has only recently caught fire with it's popularity and wasn't announce by Google until 2009. I really like how simple and straightforward Go is. It's easy to accomplish a lot in a relatively small amount of time -- one of my initial selling points on Python many years ago. The build process for Go is similar to Nim's. You get a nice portable binary and can run with that!

Async in go is simplified into the concept of channels which are a breeze to work with. You'll see these in async code alongside of goroutines which simplify the concept of multithreading.

Python Developers: Go clearly emanates from C, but with an interesting twist focused on brevity, simplicity and safety. Similarly to Python's "Batteries Included" go ships with a really great package manager to help you get started as quickly as possible.

C, C++, Java Developers: Syntactically, Go is really similar to this suite of languages. Go is (almost certainly) going to be slightly less performant than C, but still very fast. Another great selling point for Go is it's focus on types and interfaces (if you're not using interfaces you really should be).

To give you some syntax to compare, here's quicksort in Go, courtesy of Rosetta Code:

package main

import "fmt"

func main() {  
    list := []int{31, 41, 59, 26, 53, 58, 97, 93, 23, 84}
    fmt.Println("unsorted:", list)

    quicksort(list)
    fmt.Println("sorted!  ", list)
}

func quicksort(a []int) {  
    var pex func(int, int)
    pex = func(lower, upper int) {
        for {
            switch upper - lower {
            case -1, 0: // 0 or 1 item in segment.  nothing to do here!
                return
            case 1: // 2 items in segment
                // < operator respects strict weak order
                if a[upper] < a[lower] {
                    // a quick exchange and we're done.
                    a[upper], a[lower] = a[lower], a[upper]
                }
                return
            // Hoare suggests optimized sort-3 or sort-4 algorithms here,
            // but does not provide an algorithm.
            }

            // Hoare stresses picking a bound in a way to avoid worst case
            // behavior, but offers no suggestions other than picking a
            // random element.  A function call to get a random number is
            // relatively expensive, so the method used here is to simply
            // choose the middle element.  This at least avoids worst case
            // behavior for the obvious common case of an already sorted list.
            bx := (upper + lower) / 2
            b := a[bx]  // b = Hoare's "bound" (aka "pivot")
            lp := lower // lp = Hoare's "lower pointer"
            up := upper // up = Hoare's "upper pointer"
        outer:
            for {
                // use < operator to respect strict weak order
                for lp < upper && !(b < a[lp]) {
                    lp++
                }
                for {
                    if lp > up {
                        // "pointers crossed!"
                        break outer
                    }
                    // < operator for strict weak order
                    if a[up] < b {
                        break // inner
                    }
                    up--
                }
                // exchange
                a[lp], a[up] = a[up], a[lp]
                lp++
                up--
            }
            // segment boundary is between up and lp, but lp-up might be
            // 1 or 2, so just call segment boundary between lp-1 and lp.
            if bx < lp {
                // bound was in lower segment
                if bx < lp-1 {
                    // exchange bx with lp-1
                    a[bx], a[lp-1] = a[lp-1], b
                }
                up = lp - 2
            } else {
                // bound was in upper segment
                if bx > lp {
                    // exchange
                    a[bx], a[lp] = a[lp], b
                }
                up = lp - 1
                lp++
            }
            // "postpone the larger of the two segments" = recurse on
            // the smaller segment, then iterate on the remaining one.
            if up-lower < upper-lp {
                pex(lower, up)
                lower = lp
            } else {
                pex(lp, upper)
                upper = up
            }
        }
    }
    pex(0, len(a)-1)
}

3. F#

F# is a mature, open source, cross-platform, functional-first programming language. It empowers users and organizations to tackle complex computing problems with simple, maintainable and robust code.

Let's get into my favorite territory - functional programming languages. Have you had the chance to check out F# yet? No? Well you're missing out on a lot. Let's clear the air about the negatives - It was created as a Microsoft language. You're going to get the most from the language if you can leverage the .NET framework. You don't HAVE to do this, however, and can build F# against Mono, too.

I was first exposed to Metalanguages in college and they blew my mind really frustrated me. During the final weeks of my course on Functional Programming (with PolyML), it all kind of clicked and I really started to dig the language family. That being said, after doing a little bit of research, I felt that Metalanguage's like PolyML and F# (wasn't aware of F# at the time) just weren't practical. Later in my life I found F# and fell in love. If I ever end up working in a .NET shop, you can bet your ass I'm working with F#.

The language is syntactically extremely different from everything you've seen above. Functional languages often take a very declarative approach on problem solving and leverage recursion and pattern matching to make the most of their toolkit. F# is no exception to this paradigm.

.NET Developers: A functional approach on your standard toolkit. If you want to try F# and need help introducing it to your team consider building a CLI with the language. It's an excellent tool for this and really showcases its strengths.

Python Developers: Python is an outstanding tool for writing CLIs. F#, too, is an outstanding tool for writing CLIs. The language feels like a strong scripting language but provides so much more. In fact, tools like Pattern Matching make writing a CLI tool such an ease!

C, C++, Java Developers: Take a walk on the wild side. In my opinion, the biggest growth moment in my career as an engineer was the day I committed to learning functional programming. I still write Java a lot but you can see functional influence in a lot of ways. F# provides a great opportunity to help teach you these functional programming skills that can be applied in any language. It will also make you want to file an RFC for pattern matching in Java.

To give you some syntax to compare, here's quicksort in F#, courtesy of Rosetta Code:

Some things to keep in mind - rec defines a function as recursive so that the function has access to a binding of itself. The line under the function definition is a base-case pattern matcher against an empty list. The one below that matches on a list with a head element and a tail.

let rec qsort = function  
    [] -> []
    | hd :: tl ->
        let less, greater = List.partition ((>=) hd) tl
        List.concat [qsort less; [hd]; qsort greater]

2. Rust

Rust is a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety.

Above is a quote from the Rust website. I couldn't give a better quick summary of this language if I tried. Rust is fantastic. I first got into Rust with hardware hacking on the Arduino and just fell in love with the language. Rust focuses on the things that I love about Clojure but provides them in a systems language. The language itself focuses on immutability and thread-safety. The community is wonderful, supportive, and very responsive and open to feedback.

The difficult and sometimes discouraging part of writing Rust is "fighting" the compiler. The reason that the compiler seems so aggressive is because it's helping you prevent issues and write safe code. Mainly, new Rustaceans fight the borrow checker as the idea of borrowing is usually a very new concept. For those who are unaware, the way Rust maintains its ability to stay threadsafe is by "borrowing" references from one scope into another. This can be really difficult at first but once you learn how borrowing works (as well as the object lifecycle) Rust becomes a delightful experience. Plus, it runs blazingly fast!

Python Developers: If you want a new experience that will focus on teaching you the values of immutability and the merits of a compiler (you may already know these things), look no further. The community is one of the few communities that I feel is better (that's right, better) than the Python community. If you've ever wanted to get into systems programming but have had fear of SegFaults or memory management, try Rust.

C, C++, Java Developers: Another language in a style that should be syntactically familiar to you, but Rust is a completely different paradigm on memory management. The Lifecycles cause heap values to drop once they leave scope which helps maintain a manageable set of memory addresses. Rust also supports the unsafe keyword, should you feel the need to get down and dirty with C like code, however writing unsafe always makes me feel guilty and usually leads to refactoring.

To give you some syntax to compare, here's quicksort in Rust, courtesy of Rosetta Code:

fn main() {  
    println!("Sort numbers in descending order");
    let mut numbers = [4, 65, 2, -31, 0, 99, 2, 83, 782, 1];
    println!("Before: {:?}", numbers);

    quick_sort(&mut numbers, &|x,y| x > y);
    println!("After:  {:?}\n", numbers);

    println!("Sort strings alphabetically");
    let mut strings = ["beach", "hotel", "airplane", "car", "house", "art"];
    println!("Before: {:?}", strings);

    quick_sort(&mut strings, &|x,y| x < y);
    println!("After:  {:?}\n", strings);

    println!("Sort strings by length");
    println!("Before: {:?}", strings);

    quick_sort(&mut strings, &|x,y| x.len() < y.len());
    println!("After:  {:?}", strings);    
}

fn quick_sort<T,F>(v: &mut [T], f: &F)  
    where F: Fn(&T,&T) -> bool
{
    let len = v.len();
    if len >= 2 {
        let pivot_index = partition(v, f);
        quick_sort(&mut v[0..pivot_index], f);
        quick_sort(&mut v[pivot_index + 1..len], f);
    }
}

fn partition<T,F>(v: &mut [T], f: &F) -> usize  
    where F: Fn(&T,&T) -> bool
{
    let len = v.len();
    let pivot_index = len / 2;

    v.swap(pivot_index, len - 1);

    let mut store_index = 0;
    for i in 0..len - 1 {
        if f(&v[i], &v[len - 1]) {
            v.swap(i, store_index);
            store_index += 1;
        }
    }

    v.swap(store_index, len - 1);
    store_index
}

1. Clojure

Clojure is a robust, practical, and fast programming language with a set of useful features that together form a simple, coherent, and powerful tool.

If you didn't see this coming, then thanks for checking out my blog for the first time! Clojure is a Lisp that (often) runs on the JVM. It's a symbiotic language which means that I can be ran anywhere that it has a host for. In fact, another common use-case for Clojure is compiliation down to JavaScript, called ClojureScript. If you're in the web development community, you've probably heard of ClojureScript as it's really caught on in regards to it's popularity lately thanks to Om and Om Next.

Clojure is the brainchild of the wizard known as Rich Hickey. The community as a whole provides a refreshing perspective on software development and having Rich at the helm is nothing to discount. There's a database written with Clojure in mind (Datomic) and the tooling for the language is fantastic.

The structure of lisp and the paradigms behind it are nothing short of liberating. When functions dictate your code everything becomes easier to reason with. In fact, it allows you to easily write and reason about macros and I've struggled with these concepts historically in other languages that support them.

Speaking of tools, on the JVM, you can leverage any and all Java libraries in your Clojure code. This interoperability gives Clojure a massive collection of libraries despite the community being smaller than the Java community. A downside of Clojure is that it's limitation is often the same that confines the JVM (no tail call recursion), but Clojure makes a strong effort to abstract these concerns or provide alternatives.

In my opinion, Clojure is a tool that can be used for almost any job and I love the idea of that. There's even a library for writing Android applications in Clojure (and a pretty notable app called Swiftkey written in Clojure) and a ton of libraries for graphics processing.

I'll try to avoid ranting for hours about clojure, but if you're interested in learning more about it, you can find my articles on the language here.

Python Developers: If you're one of the python developers that keep coming back to my blog for some reason, you'll see most of my new articles are in Clojure. I am so very happy to teach you or work with you to help you learn about this language. As for everyone else, Clojure gives you an exciting approach on new paradigms in programming that you won't ever find in Python.

C, C++ Developers: Clojure probably won't be much of a help if you're looking for systems development, however, if you've never touched Lisp you can learn a ton from writing the language. And if you've never written Lisp, I can't recommend a better Lisp than Clojure. C and C++ developers will likely love the power behind Macros so be sure to give that a shot!

Java Developers: You can try Clojure without ever leaving your JVM. Clojure is catching on quickly in the financial tech industry and makes for excellent DSLs that interop with Java in an immaculate fashion.

To give you some syntax to compare, here's quicksort in Clojure, courtesy of Rosetta Code:

(defn qsort [[pivot :as coll]]
  (when pivot
    (lazy-cat (qsort (filter #(< % pivot) coll))
              (filter #{pivot} coll)
              (qsort (filter #(> % pivot) coll)))))

Permalink

ClojureScript Const Var Inlining

The ClojureScript 1.9.655 release introduced ^:const Var inlining. This is an exciting new feature—upgrade your compiler and give it a spin! This post will provide some detail on this new feature, covering some of its more subtler aspects.




Review and Definition

Previously, adding :const metadata to a Var, as in

(def ^:const foo 3)

would have two effects in ClojureScript:

  • It prevents re-definition within the same namespace.
  • It allows case test constants which are symbols resolving to ^:const Vars to represent their values.

Now, with ClojureScript 1.9.655 and later, a new behavior is introduced:

  • Compile-time static edn values are inlined.

This means, for example, with the Var foo as defined above,

(+ foo 12)

effectively acts as if converted to

(+ 3 12)

What is a compile-time static edn value? It can be defined recursively as a value produce by:

  • A literal which is any of nil, a Boolean, a number, a character, a string, a keyword, a symbol, an #inst, or a #uuid.
  • A (potentially empty) persistent collection literal (any of set, map, vector, or list) containing compile-time static edn values.

As expected, quoted versions of the above are fine. This is essential for creating symbol and list constants, and also allows you to easily create, say, a set collection constant containing symbols.

Examples include 1, "foo", and {:a 'sym}.

If you define a ^:const Var initialized with something that is not a compile-time static edn value, then the value will not be inlined (but the no re-definition rule will still apply).

Also note that, while a value could effectively be considered a compile-time constant, this

(def ^:const foo (str "bar" "baz"))

won't be inlined owing to the compilation and evaluation model. The initializer will evaluated in the target JavaScript environment; not at compile time.

While it is tempting to consider having the compiler calculate initializer values for pure functions (producing the constant "barbaz" above), this would fail to work properly for hosty values: (+ 16r1FFFFFFFFFFFFF 2) would produce two different values if evaluated at compile-time vs. runtime for non-self-hosted ClojureScript.

Performance and Behavior

The primary benefit of using ^:const is avoiding Var indirection and having constants directly embedded in the emitted JavaScript.

You can look at the JavaScript produced in a REPL by using the :repl-verbose REPL option. (More: See JS in CLJS REPL)

The JavaScript produced for (+ foo 12), where foo was defined as above is:

((3) + (12))

This can clearly be a win for “small” constants, leading to more compact and direct code.

On the other hand, if you have something like a map value, depending on access patterns, it might be more efficient to not define it as a constant. For example

(def ^:const m {:a 1 :b 2 :c 3})

(defn lookup [] (:a m))

(simple-benchmark [] (lookup) 1e7)

yields a timing of 1629 milliseconds on my machine, but if I leave the ^:const off, I get a timing of 480 milliseconds.

If you look at the JavaScript produced, you can see that the difference boils down to either constructing a new map value each time lookup is called (the inlined constant map value), or referring to a single instance of the map via a JavaScript variable. (In effect, leaving ^:const off, in this case, leads to a result that is somewhat akin what occurs when you use the :optimize-constants compiler option for keywords and symbols.)

If you'd like to have a ^:const Var not be inlined, you can defeat inlining by simply wrapping the value with a call to identity. For the example above: (def ^:const m (identity {:a 1 :b 2 :c 3})).

What about case? With the new compiler, test constants which are symbols resolving to ^:const Vars will be inlined with their values, instead of representing their values.

For example, this case at the beginning of this post compiles down to JavaScript that looks like this:

switch (x) {
  case 3:
    return 1;
    break;
  case 4:
    return 2;
    break;
  case 7:
    return 3;
    break;
  case "hi":
    return 4;
    break;
  default:
    return new cljs.core.Keyword(null,"no-match",
     "no-match",(568148921));
}

Notice that the JavaScript now has case 3 and case 4 instead of case foo.bar.n and case foo.bar.m.

Identity

Another difference in behavior that can be observed is with the use of identical? in the case where inlined constants involve allocation. This code

(def ^:const kw :foo)

(identical? kw kw)

now yields false, where it would yield true without ^:const. But, of course, since keywords and symbols are not interned, keyword-identical? and symbol-identical? can be used for efficient comparison, even in the case of different object instances; keyword-identical? returns true for the example above.

Caching

One final caution with respect to inlining behavior: If you have a namespace that uses ^:const Vars from another namespace, and you change the value of such a constant, you my need to ensure that the consuming namespace is re-compiled so that the updated constant value is re-inlined.

For example, let's say foo/core.cljs contains:

(ns foo.core)

(def ^:const a 1)
(prn a)

and bar/core.cljs contains:

(ns bar.core
  (:require foo.core))

(def b foo.core/a)
(prn b)

If at the REPL, you (require 'bar.core) you will see 1 printed twice. If you then quit the REPL, change foo.core/a to be initialized with 2 and then go back into the REPL, you will see 2 printed, followed by 1.

You could fix this by either deleting your cache, or by touching bar/core.cljs and re-doing the require.

Summary

For most existing code making use of :^const, you need do nothing—things will just run faster. I hope the above gives further insight into how this feature works. I think it is exciting—you should give it a try!

Permalink

Clojure + Kibit & Eastwood

I've been writing Clojure for a while now, but my day job is still predominantly JavaScript and Java. There are two tools that I use every single time I write JavaScript and Java code. Respectively, a linter and a static code analyzer. Recently, I set out to search for similar tools in the Clojure domain.

Enter Eastwood

Named after a fantastic actor, Eastwood is a linter for Clojure code. Also like the many roles the actor plays, Eastwood is pretty aggressive in the checks that it runs against your code. However, like Clint Eastwood in The Bridges of Madison County, Eastwood can also be understanding. You can configure Eastwood to meet the demands of your project, but it ships with a great default configuration too!

Implementing Eastwood is extremely simple. You can add the Eastwood plugin to your project if you're using leinengen or incorporate the library into your build pipeline if you're using boot. I've still yet to be sold on boot (and this post is a bit pressed for time), so I'll only be showing you how to incorporate the plugins into leinengen. Modify your project.clj to include the Eastwood plugin:

(defproject myproject "0.0.1"
  :description "Eastwood Sample Project"
  :license "Eclipse Public License 1.0"
  :url "http://www.bradcypert.com"
  :dependencies [[org.clojure/clojure "1.8.0"]]
  :plugins [[lein-tar "3.2.0"]
            [jonase/eastwood "0.2.4"]])

Once you've done this step, you can simply run lein eastwood from the terminal to lint your clojure application! An example output from one of my application is as follows:

== Eastwood 0.2.4 Clojure 1.9.0-alpha16 JVM 1.8.0_31
Directories scanned for source files:  
  src test
== Linting app.routes.users ==
src/app/routes/users.clj:133:43: suspicious-expression: -> called with 1 args.  (-> x) always returns x.  Perhaps there are misplaced parentheses?  
src/app/routes/users.clj:115:3: constant-test: Test expression is always logical true or always logical false: true in form (if true (do (users/update-user-password {:hash (:id params), :pass (:pass params)}) (ok)) (bad-request))  
== Linting app.routes.login ==
== Linting app.helpers.helpers ==
== Linting app.routes.inbox ==
== Linting app.middleware ==

You can see from the example output that Eastwood found an issue with users.clj line 133. The issue is that there's a suspicious expression: specifically, we're threading x into nothing. Seems like a good thing for us to clean up! Below that, you'll see that our if expression is always checking against true. Specifically, because our code is (if true ... ...). It looks like this was probably added as a quick solution, and I wouldn't be surprised to find a TODO above that expression. Regardless, that's an example of how to use Eastwood to help lint your Clojure code.

Kibit

Kibit is another tool, specifically for static analysis of your codebase. Kibit is literally one of my favorite tools in the clojure ecosystem and I can't recommend this enough to newcomers to Clojure. Kibit provides a great opportunity to write code and learn a more idiomatic way to solve the same problem. It also introduces you to some of the "combination" expressions like if-let. Kibit can be incorporated similarly to Eastwood, but serves a different purpose. Let's go ahead and add kibit to the above project definition as well. Note: You don't need Eastwood for Kibit or vice-versa.

(defproject myproject "0.0.1"
  :description "Eastwood Sample Project"
  :license "Eclipse Public License 1.0"
  :url "http://www.bradcypert.com"
  :dependencies [[org.clojure/clojure "1.8.0"]]
  :plugins [[lein-tar "3.2.0"]
            [jonase/eastwood "0.2.4"]
            [lein-kibit "0.1.5"]])

Let's run lein kibit, you'll see output like this:

At /Users/brad/Projects/podcasts/app/src/app/db/processors.clj:14:  
Consider using:  
  (update-in podcast [:feed] podcast-service/parse-feed)
instead of:  
  (assoc podcast :feed (podcast-service/parse-feed (:feed podcast)))

At /Users/brad/Projects/podcasts/app/src/app/db/processors.clj:30:  
Consider using:  
  (when (not exists?)
    (doall
      (map
        (partial notifications/new-episode podcast episode)
        subscribed-users)))
instead of:  
  (if (not exists?)
    (doall
      (map
        (partial notifications/new-episode podcast episode)
        subscribed-users))
    nil)

At /Users/brad/Projects/podcasts/app/src/app/modules/auth.clj:17:  
Consider using:  
  (if-not (some nil? [item source]) (hashers/check item source) false)
instead of:  
  (if (not (some nil? [item source])) (hashers/check item source) false)

Kibit will actually scan your code and check it against patterns with core.logic to help determine how to simplify and reduce your code complexity. There output excerpt here shows two different suggestions: Simplifying an if to a when and condensing an if and not to an if-not. You can actually run lein kibit --replace and it will fix these issues for you. If you're afraid of letting it automatically replace everything, you can even choose to run Kibit in interactive mode via lein kibit --replace --interactive. This will walk you through each occurrence and ask if you'd like to replace it with the suggestion provided.

We've recently added Kibit and Eastwood into our codebase for Porios and hope to see cleaner, more consistent code in the future. Have you had experience with Linters or Analyzers in Clojure? Let me know below!

Permalink

True. Designing a language entails making tradeoffs.

True. Designing a language entails making tradeoffs. I’m not sure why the decision was made for Clojure to behave this way, but I’m confident it was considered.

Choosing a language entails tradeoffs, too. Languages like Haskell behave in ways Clojure doesn’t, and maybe some of those ways are better. But in aggregate, there’s a lot of big things Clojure does that other languages don’t. It may not be perfect, but I try not to let perfect be the enemy of the good.

Permalink

The Missing Guide to Elixir

When it comes to choosing passion projects and side studies, CircleCI engineers have considerable freedom. One of our support engineers, Zachary Scott, has been spending some of his free time tinkering with Elixir, a dynamic, functional language. It has enough in common with Clojure — our language of choice here at CircleCI — that we thought folks would enjoy a deep dive into this (relatively) new language. Enjoy!

It’s probably no surprise that we’re excited about Elixir, a functional language built on Erlang VM that shares many of Clojure’s philosophies. Before I talk about Elixir’s design and why it’s so amazing, I’d like to share how I stumbled on this beautiful language.

Permalink

Documenting your architecture: Wireshark, PlantUML and a REPL to glue them all.

This article originally appeared on my blog

I recently had to document the results of the evaluation of a new system.

The proof of concept for the system included six possible configurations, each option having a significant architectural impact on the system.

To understand all six, I have been squinting at the logs from the servers plus the Chrome DevTools network panel, trying to correlate the requests with the responses and the traffic between the servers.

As part of the documentation I thought it would be important to have some sequence diagrams to explain the protocol between the different parts of the system.

But when trying to draw the sequence diagrams, I realized that all that squinting had just allowed me to grasp the general feeling of the difference between the options, but not enough to write down a proper and accurate description of each one.

Also, the prospective boredom of opening my least hated UML tool and spending some hours dragging and dropping boxes and fiddling around with lines, didn't fill me with joy.

Given that I already had the six combinations running for the proof of concept, couldn't I leverage on that?

The tools

First, we need to find out all the traffic between the components of the system.
For this we will use the venerable Wireshark.

Wireshark will allow us to capture any network traffic, filtering out anything unnecessary, plus it comes with a handy export to json feature to simplify the parsing of the output.

A snippet of what a HTTP request looks like:

wireshark-json-sample

Second, we will need to generate the UML diagrams. For this we will use PlantUML, which is a text based UML DSL with the accompanying libraries to generate images. Being text based, our problem of generating UML diagrams becomes one of string concatenation.

Lastly, we need some glue to transform the Wireshark JSON files to PlantUML text files. We will use Clojure but any Turing complete language would do. Of course, a Clojure REPL makes the task more pleasant.

The result

First, to show off, lets look at how one of the diagrams looks like:

keycloak-uma

This diagram requires 40 lines of PlantUML that look like:

browser -> backend: /api/datasets/ds-1 (536.0B)
browser <-- backend: 200 json (0.7KB)
browser -> backend: /api/library (525.0B)
browser <-- backend: 200 json (1.0KB)
note over browser, nginx: ->1.2KB/<-532.0B
note over browser, backend: ->4.4KB/<-5.3KB

The whole PlantUML code is here and the code can be found here.

If you are curious, the diagram corresponds to loading a Single-page application, doing authentication with OpenID Connect and authorizing an API endpoint with User-Managed Access.

Benefits

The benefits of using these three tools are:

  1. We are able to generate a set of diagrams that are accurate, giving you the confidence that you are not missing anything. Assuming no bugs in the parsing code.
  2. As the set of diagrams are generated using the same code, they all look consistent, both in the data that they contain and in their look and feel.
  3. The data, the diagrams and the code to generate them are all text, which means that can be version control and manually inspected or tweaked if required.
  4. If we decide to change any details about the diagrams, it will take no time to update all diagrams.
  5. Maybe the code to generate the diagrams can be used in other projects.
  6. The diagrams have the desired level of detail. For example, in the diagrams we have removed the loading of images, css and javascript files.
  7. You can add a great deal of detail to the diagrams, as the data capture has even the request/response, so you could parse them and extract the information that was relevant to your system.
  8. You can do all from your favourite IDE in an interactive fashion:

Drawbacks

Of course there are some drawbacks:

  1. We have to have the system working and we have to be able to sniff the traffic.
  2. The data capture can be huge, so some pre-filtering during the capture phase maybe necessary.
  3. There can be sensitive data in the capture. Be careful with the security!

More benefits!

Last, but probably the most important benefit, is that we have converted a tedious task into an enjoyable one.

I never thought I would say this but ... Happy documenting!

Permalink

ClojureScript method head recur in defrecord

An update in the ClojureScript 1.9.655 compiler release eliminates a difference with respect to Clojure for code making a recur to a defrecord method head. Hopefully this post is useful in the event that you encounter this situation!




Let's look at some example code to make things concrete.

Let's say you have a protocol:

(defprotocol ISearch
  (search [this coll]))

And, let's say you are making an instance using defrecord. Notice that the recur is to the search method head (and not a loop target):

(defrecord Search [item]
  ISearch
  (search [this coll]
   (when (seq coll)
    (if (= item (first coll))
     item
     (recur (rest coll))))))

The above is a contrived example. It will scan for and return an item if it is found in a collection. For example, this

(-> (->Search 1)
  (search [:a 1 "b"]))

yields 1, while

(-> (->Search :z) 
  (search [:a 1 "b"]))

yields nil.

The code above works fine in Clojure, but if you try it in ClojureScript 1.9.562 or earlier, you will get the following when attempting to evaluate the defrecord form:

recur argument count mismatch at line 7
…

“Ahh, of course,” I'm thinking, “I need to add this to the recur call.” And I revise it so that part looks like:

     (recur this (rest coll))

Things are working now. ¯\_(ツ)_/¯

But, this is actually not the right thing to do—the docstring for defrecord has this to say:

… Note also that recur calls to the method
head should *not* pass the target object,
it will be supplied automatically and can 
not be substituted.

If you are trying to write portable code (say, using .cljc), then you'd need to deal with this discrepancy.

This has been fixed with CLJS-2085, making it so that you can now compile the code as initially written above. Note that this applies to defrecord, deftype, and reify.

In order to not break existing ClojureScript code that is passing this (or some other value) as the first argument to recur, the compiler will continue to accept the code, but it will emit a diagnostic like this:

WARNING: Ignoring target object "this" passed in recur to protocol method head at line 7

So, if you happen to see this warning, and you know your code will only be used in ClojureScript 1.9.655 or later, you can safely remove the first argument to recur.

If you are seeing this warning being emitted for library code that cannot be updated, you can suppress :protocol-impl-recur-with-target. See Compiler Warnings.

If you are a library maintainer and wish to continue supporting ClojureScript 1.9.562 and earlier, prior code will continue to work, albeit while emitting a warning. If you'd like to avoid this warning, one optional workaround to consider is adding an explicit top-level loop target in your method implementation.

Permalink

Not at all.

Not at all. I didn’t attempt it, but I have thought about it. I’m not sure how it would result in a situation much different from the one I described, or one that would be equal or better than Clojurescript. If you know Clojurescript you know Clojure, so you can write programs that compile to Java and C#. It’s a Lisp, where the syntax is represented entirely in terms of the language’s data structures, which makes writing macros and metaprogramming very easy. I don’t think I can achieve those things with a vanilla JS library.

Even if I gave up some of that, other people on my team or in open source would need to learn my library in order to work with me or understand the code I write. And even if people were willing to take the time to learn it, that knowledge would only be applicable in a very limited context (my projects). At best it would be another ramda or lodash/fp, which would seem to add to the problem I describe.

So I don’t think the solution lies within JS. I think you have to go above it.

Permalink

Copyright © 2009, Planet Clojure. No rights reserved.
Planet Clojure is maintained by Baishamapayan Ghose.
Clojure and the Clojure logo are Copyright © 2008-2009, Rich Hickey.
Theme by Brajeshwar.