Clojure 2014 Year in Review
stuartsierra.com
stuartsierra.com
http://iloveponies.github.io/120-hour-epic-sax-marathon/
Teaches you TDD in Clojure and "forces" you to use git / Github / Travis to test your code.
Highly recommended.
edit: style.
I believe the official link is http://mooc.cs.helsinki.fi/clojure
I used it only once at work to develop a stress test for a Java based game server. It was great fun to build, worked like a charm and ended up taking less than a thousand lines of code to implement the communications, bots and their execution scripts.
Furthermore, the company just bought a copy of The Joy of Clojure and there's already a bunch of my coworkers interested in reading it. Good times!
https://www.google.com/url?q=http://www.braveclojure.com/&sa...
However, I found it easier to digest than Let Over Lambda which was a real mind bender for me a few years ago. Being a LISP fan before learning about Clojure definitely made learning it much, much easier. It also made me appreciate the language early on for its impressive beauty, elegance and simplicity.
My latest site is now written in it and clojure script, and I see no reason to not continue. Though cljs is definitely a few years behind on the stability curve.
I've had some issues with the Austin REPL however, there is sometimes random disconnections and it was hard to setup the first time, but using it is so much fun it completely shadows these issues.
I've switched to using the Weasel[1] REPL instead and haven't had any disconnect problems since. Its also a little easier to setup (although still not "easy").
Great work Clojure community.
Not to start a flame war, but it seems that Clojure/Rich's strong anti-OO stance is almost a selling point of the language.
IMHO, OO just put some lipstick on the procedural pig.
Nope. http://www.tiobe.com/index.php/content/paperinfo/tpci/index....
First functional language on that list is F# at 19.
I don't know if the trend will continue (my guess is yes), but you shouldn't dismiss it just because C, C++, and Java are still the most widely-used programming languages in the world.
From: https://lispjobs.wordpress.com/2014/11/25/clojure-software-d...
CORTEX is our next generation platform that handles real-time financial data flows and notifications. Our stateless event-driven compute engine for dynamic data transforms is built entirely in Clojure and is crucial to our ability to provide a highly agile response to financial events. We leverage AWS to operate on a massive scale and meet high-availability, low-latency SLAs.
That list's methodology seems somewhat arbitrary, but let's go with it.
If you look at many top languages in use by a lot of companies, many have increasing functional aspects: Java (#2), Python (#8), and R (#12). (I may have left out some, too.) Python has many functional aspects. Java 8 brings lambda expressions. R has first-class functions and lazy evaluation.
I'd say this is less about functional programming "destroying" OO and more about programmers reaching for some aspects of FP when OO brings too much complexity. For example, why create a new class just to write an event handler? Even Java is getting the picture!
OO will continue to be successful for accessibility reasons, and it's demise will continue to be predicted to have arrived.
But i don't think Clojure is just continuing the (equally immortal!) LISP subculture. I think LISP is growing by recruiting people from OO-ish languages like Java, Python, and Ruby, rather than from existing LISPs. This is the first time in a long time that a LISP has done that. It's also the first time in a long time that a LISP has got even this glimmer of mainstream use. pg wrote 'Beating the Averages' in 2001 [1], and even after that, everyone still thought LISPers were freaks. But announce you're using Clojure in production today, and nobody bats an eye.
People were using LISP in production in the 90s as an advantage, but then they were also using Smalltalk or Objective C also (ironically often in the same places...on Wall street). A new generation is discovering LISP while learning other languages first, but the phenomena is the same: OO was just less popular in the past and so they would come from C or Perl instead of Java.
[edit: not sure why you were downvoted, I thought your post was completely reasonable]
http://en.wikipedia.org/wiki/Mixin#In_Common_Lisp
In RPG's inconsumerability essay [1], he describes it like:
> In that paper they described looking at Beta, Smalltalk, Flavors, and CLOS, and discovering a mechanism that could account for the three different sorts of inheritance found in these languages—including mixins from Flavors and CLOS.
They did come from Flavors first regardless (mixins being named after an ice cream shop with mixins near MIT, so I heard). I think it was also the first system to allow for aspect advice via a first-class construct.
http://lispm.de/docs/Publications/Flavors/Flavors,%20a%20non...
'aspect advice' was mostly introduced in Lisp in 1966 by Warren Teitelman: http://dspace.mit.edu/handle/1721.1/6905 See the discussion of ADVISE and a BEFORE example in the paper... From there it came to Interlisp, Maclisp, Flavors and CLOS...
But I only see that argument giving an advantage to some weird language that doesn't have structures. In C, Pascal, COBOL, you have "objects"....you just don't have any methods attached to them.
And the biggest pushers of objects in the early day were CLOS people like Richard P Gabriel, and CLOS (edit: Flavors actually as lipsm points out) gave us mixins, which are a pretty advanced OO construct (though RPG argues the mixins that got adopted in OO languages were not the ones CLOS intended).
I'd argue that methods and data don't belong together (like in CLOS), but don't have the inclination to argue it right now. I'll just say it's never felt natural to me, and actually hurts reusability.
When I encoded my own objects in C, I definitely had v-tables (though I didn't know they were called that at the time).
> I'd argue that methods and data don't belong together (like in CLOS), but don't have the inclination to argue it right now.
It is difficult not to put behavior and data together while still having encapsulation (it is still possible). It makes much more sense for functional programming since values lack identities (they are completely defined by their structure), but objects have state that need to be protected for sanity reasons.
Also encapsulation happens quite well in languages that do not have the "private" or "protected" keywords. In Javascript encapsulation happens by closures and local scoping. In Python it happens by convention. Also, take most software developed ever in an OOP style and you'll find plenty of examples of leaky encapsulation (i.e. APIs that leak restricting implementation details), starting with the popular Iterator. IMHO, the best abstractions I know come from languages that are not OOP at all.
I'd also argue that the encapsulation you're talking about doesn't have much to do with OOP in general, only with a particular flavor of it. But that's the problem in all conversations about OOP - take any 2 random people and they'll have different opinions about what OOP is.
For me OOP is about subtyping or more specifically a form of ad-hoc polymorphism that's solved at runtime. It's very convenient for modeling certain kinds of problems for sure - graphical UIs are the best example, or a browser's DOM and even die-hard detractors would find it hard to argue that a Monoid isn't a Semigroup, or that a Set shouldn't be a Function. In fact, objects in OOP do not necessarily need an identity, in which case they are just values, yet you can still put that polymorphism to good use.
But then OOP as implemented and used in mainstream languages is truly awful, being no wonder that people still consider C with half-baked object systems as being something acceptable.
Of course, encapsulation can occur at module boundaries, and even when programming with objects, a notion of "internal, package private, or friendship" is often useful. But it is pretty well acknowledged in the PL community that Javascript does encapsulation in the worst way possible (something OOP and FP people can actually agree on).
> But that's the problem in all conversations about OOP - take any 2 random people and they'll have different opinions about what OOP is.
Most people focus on laundry list of pet or hated features when defining OOP, but to me, its all about the objects and if you are thinking in terms of objects in your design. So...
> For me OOP is about subtyping or more specifically a form of ad-hoc polymorphism that's solved at runtime.
I think these are very useful when thinking in terms of objects, but that features like this do not "define objects" but rather that "working with objects make these features desirable." Since you mention it...
> In fact, objects in OOP do not necessarily need an identity, in which case they are just values, yet you can still put that polymorphism to good use.
I would say subtyping is useful for values, but not that anonymous value have somehow become objects since you are manipulating them with subtyping! If I have two values, say 42 and 42, they are the same value no matter how they were computed, stored, retrieved, and so on. They cannot have state (since you can't have state without identity), the different 42s are indistinguishable. In fact, since values are defined solely by their structure, other forms of subtyping might be considered over nominal, like structural, and you might want to abstract over them using type classes. But the reasoning is math-like equational, you aren't really doing OOP at that point from even a design perspective (this is my position, of course it is wide open to debate in the community).
I like C# since it provides both values and objects, and they are adequately separated even if some subtyping still applies to values. But when I am manipulated structs, my design perspective has shifted away from objects; I don't think of them as objects.
> being no wonder that people still consider C with half-baked object systems as being something acceptable.
Back in the 90s, we didn't have much else, C++ still wasn't very trusted; Java was very new. Or if you are referring to C++ and Objective C today, I really couldn't disagree with that.
I don't think the distinction is so clear cut. An immutable List is a value, because it is clearly defined by its structure, yet you need heap-allocated values in C# (so objects) because you need pointers. An immutable List would also implement various interfaces, like Iterable, so polymorphism is useful as well.
I also forgot to say that the polymorphism that we get with OOP is NOT enough. Static languages also need generics and all languages also need type-classes or something similar. Type-classes are different and useful for different use-cases than OOP, because the dictionary is global per class and not per instance. And if it is solved at compile time, like in Haskell or Scala, it also has some performance benefits.
Clojure's protocols for example are pretty neat and get pretty close to type-classes.
I don't think there's much of a connection to natural language. OO is about commanding objects through messages; if we must make a connection to language, it would be equivalent to the imperative tense.
> Heck, even Clojure has its own object systems; they just often call them entities rather than objects
Which object systems would these be?
I've designed non-imperative OO languages before; e.g. http://research.microsoft.com/apps/pubs/default.aspx?id=1793...
The community didn't scream out and say "but that language doesn't have messages, it can't be object oriented!" Of course, Alan Kay wasn't at ECOOP that year, but I did get an argument from Ralph Johnson that what I did was just Smalltalk :p.
> Which object systems would these be?
Clojure's (Rich Hickey's?) ideas about OO are surprisingly close to my own:
> OO is, among other things, an attempt to provide tools for modeling identity and state in programs (as well as associating behavior with state, and hierarchical classification, both ignored here). OO typically unifies identity and state, i.e. an object (identity) is a pointer to the memory that contains the value of its state.
The important thing about objects is their identity; they have names like Fred or Bob; they aren't anonymous values that can only be identified by their structure 42 or (2, 3).
> There is no way to observe a stable state (even to copy it) without blocking others from changing it.
He is not against objects, just how they are realized in imperative languages.
> OO doesn't have to be this way, but, usually, it is (Java/C++/Python/Ruby etc).
Yep. So he solves the problem in a smart way:
> In coming to Clojure from an OO language, you can use one of its persistent collections, e.g. maps, instead of objects. Use values as much as possible. And for those cases where your objects are truly modeling identities (far fewer cases than you might realize until you start thinking about it this way), you can use a Ref or Agent...
I will disagree, as soon as you have a collection with a key that is a GUID (or a name like Fred or Bob), you've just invented an object, whether its properties are embedded in the object or not.
Clojure just has its own ways of doing OO programming. If you hate OO, then you might simply claim "it is not OO", but this definitely is not pure functional programming that lacks identity at all (and pure Haskell solutions really do avoid all of this, Haskell is very non-OO in ways that pragmatic LISPs are not).
Note that there are other ways of fixing this problem, one can manage time so that object properties are always observed safely; this is the approach I'm currently taking with my own research:
That's an unusually broad definition of an object. Is that the only criteria you have? Does the key need to be unique?
Even if you didn't have these features in your language, they are fairly straightforward to construct in an ad hoc way as long as you have identity (that includes aliasing, obviously). Some kind of object system is often invented while building C programs of non-trivial size.
If the key isn't unique, then multiple objects could share the same state...they would be the same object!
Values are anonymous in contrast: you can't really tell the difference between this 42 and that 42.
> In computer science, an object is a location in memory having a value and possibly referenced by an identifier.
Not useful huh?
I would say, if the memory location is heap allocated and has mutable fields, then it is probably acting like an object (it could also be a value, it depends if its identity is important or not).
> An object has state (data) and behavior (code).
Which is the definition I'm most familiar with. I wouldn't class a Clojure reference as an "object", as it has state but no inherent behavior.
> I would say, if the memory location is heap allocated and has mutable fields, then it is probably acting like an object
So a reference to an immutable map wouldn't count as an object for you, because there are no mutable fields?
Ya, the wiki article makes a distinction between programming and designing with objects, and object-oriented programming. It really. All my arguments are about designing and programming with objects vs. designing and programming with values, call it "programming with objects" if you must.
What I meant was is there a significant portion of corporate decision makers that don't look at OO as the default programming methodology, than say 10 years ago?
I'm actually pretty surprised at the uptake of Clojure, especially compared to Scala, which would intuitively be the next language for corporate adoption on the JVM.
I think there are many developers and decision makers that are looking for simplicity now.
And this is coming from someone that isn't particularly keen on s-expressions or dynamic typing. Like I said in my first comment, I'm pretty much amazed at the adoption of Clojure by some mainstream companies.
When your base is high, adoption trajectories are pretty high, but level off fairly quickly. We still need a few years to tell what is actually going on.
The xkcd cartoon is obviously exaggerated satire.
As programmer that feels quite at home with OO idioms - Clojure distills it down to the parts I actually like.
I wouldn't be so sure of that.
If on the other hand we restrict the term to languages where values are essentially identity + a record of methods (whether through the indirection of a class v-table or directly stored in the value as in prototype based languages), I do think that model has largely run its course. It will certainly remain popular in the near future, but people are increasingly realizing that modeling everything as a record of methods + identity (+ state?) isn't a good way to do it. There are certain things that lend themselves to that way of modeling, but most things are best modeled in some other way. Records of functions + identity is just one particular data type among many, and it's not any more special than any other data type. Modeling everything as an object is like TCL where you model everything as a string. OOP is nice on the surface because you have some vague analogy to real world objects, but that does more harm than good. It is similar to agile or TDD where people try to sit down at the computer and immediately start typing code without any careful thinking beforehand. Like TDD and agile, OO also facilitates that kind of programming because people can take the concepts in their head and immediately start typing class definitions. It works for easy problems, but even there it does not lead to a pretty end result (one of the symptoms that sticks out most is the question 'on which class does this method belong?'). Rather than designing your program to model the real world, it usually works much better to design your program around the problem you're trying to solve. Rather than starting with the real world and making an analogue to it in your program, you start with the problem you're trying to solve and come up with a data model that facilitates solving that problem. A famous example of the former style gone wrong is Ron Jeffries who tried to write a sudoku solver with an OO + TDD approach in a series of blog posts. He modeled his program with classes that seem natural for the problem, and he wrote tests for those. Unfortunately writing a sudoku solver is not one of those problems where you can just start banging out code without any thought and get it to work, so he got stuck because he did not think about how to actually solve the problem, he only thought about how to model the real world with OO.
But how often do you know the right solution to a problem? Not very often, and many problems are ill defined from the start. Objects are just units of natural language: we can lie about their relationships, include bias and stereotypes, and be wrong, but it doesn't come with the not often realistic requirement that we be right. OO is agile, it allows us to start working on the solution right away, and that gives us experience about the problem.
But it won't always work! Sometimes you really do need to sit down and work out the math, turn off your natural thought biases by not using objects. And there definitely aspects of a problem that are more mathy and not very suitable for object based design and programming.
So if objects are the only tool in your bag, you are gonna get hurt, but if values are the only tool in your bag, well the same.
Personally, I like Clojure (which I am just learning now) in spite of the lack of objects. I think that the ability to write a Point class, encapsulate the coordinates, and expose an API is great. In my opinion, representing a Point as a vector or map, and then having a set of unassociated functions operating on these point-like collections sacrifices some good ideas that came from object-orientation.
Since you mentioned you were learning, I thought I'd share that, although I like functions-on-data as much as the next guy, I often use protocols and records for tasks like this, generally for no reason other than organization and self-documentation:
(defprotocol Pointy
(add-vectors [this other])
; ...
)
(defrecord Point
Pointy
(add-vectors [{this-x :x this-y :y} {other-x :x other-y :y}]
(->Point (+ this-x other-x) (+ this-y other-y)))
;...
)
I think this has more to do with type-safety than object-orientation though. (defalias Point
(HMap :mandatory {:x Num, :y Num}
:complete? true))
(ann add-vectors [Point Point -> Point])
(defn add-vectors [a b]
{:x (+ (:x a) (:x b))
:y (+ (:y a) (:y b))})Have you tried implementing a numeric tower with proper OO in Smalltalk? Would you describe the experience as wonderful and the program as beautiful? Rinse and repeat for any other problem that requires simultaneous pattern matching on several values.
I do think Smalltalk's style of single-receiver message passing is a sweet spot for structuring many kinds of programs.
The number of languages that I've seen with a proper numeric tower that aren't Scheme (or direct descendants of Scheme like Racket) are zero, so "OO makes it hard to do something almost no one ever does"...?
> Rinse and repeat for any other problem that requires simultaneous pattern matching on several values.
No problem requires pattern matching, much less on several values, any more than a problem requires OOP. Pattern matching and OOP are idioms that can be used to solve problems, but they are never the exclusive idiom that can be used to solve a problem (though either might be the only one that a particular language provides.)
It doesn't have to be an elaborate Scheme or Common Lisp numeric tower. I mean any kind of lattice ("X and Y gives Z") that would normally be implemented with case analysis. Especially if that lattice has symmetries (e.g. commutativity).
> No problem requires pattern matching, much less on several values
Of course, but I think you know what I mean. Take any of the standard problems that are not amenable to natural forms of cascaded single dispatch. Pattern matching has its own limitations, but sometimes it's the right tool for the job.
However there are times when the OO approach makes sense and you have a full range of tools from multimethods to protocols. In ClojureScript you even have Self-like functionality in the form of `specify`.
[1] http://dev.clojure.org/display/design/specify+i.e.+reify+for...
(I need to update my github link to point to a static version of Om's code!)
<sarcasm> Not to start a flame war, IMHO functional bigots just like to incite language wars rather than solving real problems. </sarcasm>
http://clojure.com/blog/2013/06/28/clojure-core-async-channe...
All of the operations are expressions (not statements)
This is a library, not syntax
alts! is a function (and supports a runtime-variable number of operations)
Priority is supported in alt
--
Quil is a Clojure and ClojureScript library for creating interactive drawings and animations using Processing (https://en.wikipedia.org/wiki/Processing_%28programming_lang...).
--
Om is actually an interface to Facebook's React. Ironically, the terminology, and the feature set of Om has little, if any, resemblance to React. Om specifically transforms Clojure data so that it can be represented in a way that React can uderstand.
In the Clojure world, we build on top of React and stay away from anything that resembles JavaScript and it's behavior. React provides a virtual DOM and we just use Clojure to talk to the rendering engine.
https://gist.github.com/runexec/6efb322f29fc790a98a1
--
Chestnut allows live coding in the browser. This means all changes are visible without having to reload the page.
2 Minute video of Om using Chestnut. https://www.youtube.com/watch?v=gI3fJKmvgq4
https://github.com/om-cookbook/om-cookbook
--
Apache Cordova is the Apache License version of Adobe PhoneGap. ClojureScript compiles to highly optimized JavaScript already, so you can make mobile apps using ClojureScript and Apache Cordova.
Pulsar looks nice, but I'm not quite sure why users (especially new ones) should prefer it.
Most notably, you can block with any arbitrary function, not just the specially-designated parking functions in core.async. Furthermore, they need not be visible to the go macro, unlike core.async (so you can call them in a compiled closure, for example, and it will just work).
I've been interested in this mixture recently. I use PhoneGap quite a bit. Currently my favorite combination is Sencha Touch Framework with CoffeeScript. IMO, this is a really simple way to develop mobile apps. Do you know of any open source examples of ClojureScript + Apache Cordova?
https://github.com/celwell/wesawit-st2-app
When you start to veer away from a top-notch framework like Sencha Touch, you can run into a lot of performance issues that a good framework would take care of for you. For example, your scrollable components should probably be using CSS translate3d() to make use of hardware accelerations; and myriad other tricks.
The future looks bright for the language, especially with applications like this.
When I use clojure, it's typically for companies who need to get something done and then I choose clojure to do it, but only once someone specifically asked me for clojure (but it was an American company).
I don't find it as easy to work as clojure guy in Europe.
In comparison, in the US there's much more demand but many companies refrain from remote contracting Europeans (even though I think my background is quite good ML, Data Science, Statistics, ..)
So IMO the TL;DR is: filling clojure positions is only a problem in the US, not in Europe.
Edit: making it clearer.
Most people who I see using clojure are bored ruby programmers and they bought their open source culture with them to clojure.
Clojure is not even in top 50 on TIOBE index http://www.tiobe.com/index.php/content/paperinfo/tpci/index....
Even though this is 2 years old it's still the case that the Clojure folks are heavily dominated by users who have already invested in the JVM. The other largest group seems to be split evenly between Python & Ruby as reflected in this survey.
The "index" is calculated (http://www.tiobe.com/index.php/content/paperinfo/tpci/progra...) by searching the 25 highest ranked web sites on Alexa which have a search box and meet some basic criteria then magically weighting them as follows:
- Google - 7.7% - YouTube - 7.4% - Baidu - 7.1% - Amazon - 6.8% - Google India - 6.5% - Yahoo Japan - 6.2% - Hao123.com - 5.8% - Google Germany - 5.5% - Microsoft Bing - 5.2% - Google Japan - 4.9% - Google UK - 4.6% - AliExpress - 4.3% - Alibaba - 4.0% - Amazon Japan - 3.7% - Google Brazil - 3.4% - 360.cn - 3.1% - Google Italia - 2.8% - Amazon Germany - 2.5% - Google Spain - 2.2% - Amazon UK - 1.8% - Google Mexico - 1.5% - Google Canada - 1.2% - Google Ad Services - 0.9% - Amazon China - 0.6% - Google Poland - 0.3%
I might buy that a general internet or e-commerce search might tell you one (low-signal, high-noise) piece of data about popularity. Some of these sites seem highly questionable to tell you anything meaningful. Garbage in / garbage out.
I think use of more specific numbers from sites like Stack Overflow or GitHub seems far more likely to give you relevant information.
I was at first turned down by the JVM (not knowing any better back then), but it turns out being a hosted language is one of the best aspects of Clojure.
the scheme shell maybe? scsh.net
here's some snippets:
But Clojure has a strong opinion on immutability and functional programming. I'm not sure those Schemes do.
In any case, if you were to introduce a Scheme, I would do Racket for it's significant community within the larger Scheme ecosystem.
Scheme programmers emphasize the very same things.
>I would do Racket for it's significant community within the larger Scheme ecosystem.
Yeah, Racket would make sense, though I'm personally attached to Guile.