Hacker News new | past | comments | ask | show | jobs | submit login
Clojure 2014 Year in Review (stuartsierra.com)
261 points by fogus on Jan 2, 2015 | hide | past | favorite | 115 comments



For everybody who wants to start Clojure, I know that there are loads of good resources, but the best one which I had found is this online MOOC:

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 highly recommend this course as well.

I believe the official link is http://mooc.cs.helsinki.fi/clojure


Do you know of any other TDD MOOCs out there? It's my preferred learning method. Thanks!


This is great! Glad to see more Clojure adoption in the corporate world. It's definitely well deserved!

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!


Similar experience here. I wrote a log parser with indexing and hierarchical cache invalidation to deal with larger than memory amounts of logs quickly and in a natural coding style, and after that I was hooked. Tiny code base, good performance, little need for ugly hacks.

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 haven't had any major issues with cljs yet. I'm using it for personal side-projects where I prototype random ideas along with Om and React.

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 had some issues with the Austin REPL however

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").

[1] https://github.com/tomjakubowski/weasel


A word of advice with Joy of Clojure: take up meditation. That book is surprisingly dense. I had to research topics ever few paragraphs. It is not a beginners books. Rather pair it with Clojure for the Brave and True. Combined the language comes alive.

https://www.google.com/url?q=http://www.braveclojure.com/&sa...


Good advice! The book is definitely dense and packed with useful information. I didn't read Clojure for the Brave and True yet, I'll add it to my reading list, thanks!

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.


The amount of traction that Clojure is getting in companies like Walmart, Amazon, and elsewhere is surprising and impressive.

Great work Clojure community.


Are we beginning to see the tipping point where mainstream corporates are starting to question whether traditional OO is the right way to go?

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.


Clojure's anti-OO stance is far subtler than people seem to understand. It's primarily about not reaching for classes as a first tool and eliminating local state (and even this is allowed!)

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`.


Is there any documentation on "specify"? I've seen it used from time to time (eg in your Om code), but the only documentation I've found is the dev wiki page[1].

[1] http://dev.clojure.org/display/design/specify+i.e.+reify+for...


At the moment there is not, someone should add something to the wiki. Basically it clones the target and adds the specified protocol implementations - basically instance level extend-type.


This is an old post but I talk about it a bit here (toward the bottom): http://www.davedellacosta.com/cljs-protocols

(I need to update my github link to point to a static version of Om's code!)


Multimethods and Protocols seem to get better results than what OO is trying to achieve...at least when it comes to polymorphism.


Clojure is continuing the LISP subculture that has existed for a long time, nothing new here.

OO will continue to be successful for accessibility reasons, and it's demise will continue to be predicted to have arrived.


I think you're right about OO's continued survival. I also think mikerichards is right that OO is just technicolor procedural programming. Moreover, i think these two things are related: OO is immortal in part because it's straightforward and obvious, just like procedural programming.

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.

[1] http://www.paulgraham.com/avg.html


The advantage of OO has always been its accessible constructs and abstractions that mirror how we talk about things linguistically. Nouns are just sticky that way. It isn't a big delta over procedural programming, and you can find object systems in many C programs written before OOP was even a word. Heck, even Clojure has its own object systems; they just often call them entities rather than objects (what is an entity? well, its an object, but not the object you are used to). I think our current OO abstractions suck, but the paradigm is OK, especially when considered in the abstract (go back to the treaty of Orlando to see how diverse objects can be!). 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).

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]


The advantage of OO has always been its accessible constructs and abstractions that mirror how we talk about things linguistically. Nouns are just sticky that way.

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.


> In C, Pascal, COBOL, you have "objects"....you just don't have any methods attached to them.

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.


Yeah, but your argument is kind of circular - we put behavior and data together because we need encapsulation and we need encapsulation because objects have an identity that needs protection, yet those objects need an identity because we are putting behavior and data together, in combination with mutability of course.

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.


Objects require encapsulation because they have something (mutable state and sensitive data) to protect. Also, I hope its obvious that with identity, you get mutability automatically (just use an immutable map as in Clojure!), and you can't really have meaningful mutability beyond global variables without identity.

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 like C# since it provides both values and objects

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.


Mixins are from Flavors, not CLOS. CLOS has no special support for mixins - they are just a sub-functionality of CLOS.


Thanks, my understanding of history is probably a bit confused:

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.

[1] http://www.dreamsongs.com/Files/Incommensurability.pdf


Mixins were introduced with Flavors by Howard Cannon in 1979. Flavors/Mixins were used to implement some of the early MIT Lisp Machine user interface, IO and networking code.

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...


Thanks. The Teitelman work is what I cite as the introduction of aspects, but I didn't realize it was more than just a pattern back then.


> The advantage of OO has always been its accessible constructs and abstractions that mirror how we talk about things linguistically.

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 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.

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:

http://clojure.org/state

> 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:

http://research.microsoft.com/pubs/211297/onward14.pdf


> 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

That's an unusually broad definition of an object. Is that the only criteria you have? Does the key need to be unique?


If you are contrasting objects to pure values, that is really the main distinction: objects have names at design time, compile time, and run-time, values do not. I don't think it is unusually broad (at least it is not considered a radical position in the academic OOP community). Everything else: encapsulation, methods attached to data, subsumption, nominal subtyping, require that an object has its own identity and further support its "objectness."

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!


I'm not sure what you mean by a "name". Do you mean the same thing as Hickey's definition of "identity", i.e. "a stable logical entity associated with a series of different values over time"?


Yes. To identify something whose fields change over time, it needs a name (even if that name is just a GUID or address). Well without fields, you don't need names, but this isn't a very interesting case (it is hard to scale up programs with just what are essentially global variables!).

Values are anonymous in contrast: you can't really tell the difference between this 42 and that 42.


So would you consider a pointer to a memory location to be an object?


Use the wiki [1]:

> 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).

[1] http://en.wikipedia.org/wiki/Object_(computer_science)


Wikipedia appears to distinguish between "object-based" languages and "object-orientated" languages. On the subject of object orientated languages, it says:

> 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?


The reference to the immutable map doesn't count (a immutable map is just a value), but keys into the map can form objects (in that they represent "object" properties). Actually, that is how you get objects without first class mutability (identities must still be generated, of course, which is the same thing).

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.


Because people come to the HN comments for stimulating, challenging, passionate expressions of thought, not reasonable ones!


Not sure what you are talking about - Clojure has a great many OO-ish constructs - even local state! The only thing that's really missing is deep support for static forms of inheritance.

As programmer that feels quite at home with OO idioms - Clojure distills it down to the parts I actually like.


I totally agree with this, and LISPs have always been pragmatic about state, although I get the feeling that Clojure emphasizes purity a bit more than other LISPs. I was replying to two separate points from parent, the points weren't meant to go together :)


Well, not all LISPs are considered friendly from our modern context. Just consider my favorite 'love to hate' Emacs Lisp example: http://www.emacswiki.org/emacs/DestructiveOperations Check out the bit where using 'sort' incorrectly can self-modify the function. Anyhow, maybe Clojure is "just" another LISP, perhaps, but it is really nice due to many small improvements making a big difference.


Well, it isn't very weird that today's LiSP is better than yesterday's. Clojure also takes purity a bit more seriously, though nowhere near as serious as something like haskell.


"Well, it isn't very weird that today's LiSP is better than yesterday's."

I wouldn't be so sure of that.


I wasn't predicting a demise, just like I wouldn't predict the demise of C, COBOL, or other procedural languages.

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.


Do you have any numbers on Clojure vs. Scala adoption? The Clojure community is definitely vocal, but Scala has made a lot of successes also, and at this level of marketshare, it is difficult to say if they are equal, or if adoption is off by an order of magnitude. Scala in particular has done well in the systems community, oddly enough.


Anecdotally, I've been applying for jobs using Scala and Clojure in Australasia and Europe and the Scala jobs seem more numerous and far better paid


I don't have any numbers, but given the relative youth of Clojure vs Scala, and the adoption that Clojure is getting, I'd say that the trajectory is pretty much on Clojure's side.

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.


Sean, I don't think that's really fair to either Scala or Clojure though. Yeah, both of their numbers are small potatoes next to Java or C#, but not insignicant...as in last week there was 4 Clojure users and now there's 16..OMG there's been a 400% jump!.


We are talking about adoption rates between Scala and Clojure. When Scala was a few years old, I am arguing that its adoption rate was similar to what Clojure is experiencing today. So looking at the "current trajectory" doesn't tell the whole story. It is adoption over the long term that will tell us who has won (or is winning) the language wars.

The xkcd cartoon is obviously exaggerated satire.


Well, there is always http://xkcd.com/605/

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.


"base is high" should be "base is low". Trajectories level off over time.


In order for that to be a testable prediction the terms need to be made precise. OO is a famously vague concept with many different concrete incarnations. There's single dispach vs multiple dispatch. Within single dispatch you have prototype based vs class based. You have objects as a record of closures. With multiple dispatch you have dispatch on class, or predicate dispatch, or full pattern matching. There's the question whether some form of identity or state is part of OO. The concept is broad enough that you can easily stretch it so that almost any modern language is OO in some form. A functional or logic programming language where functions can be split into multiple cases with pattern matching is arguably just a generalization of predicate dispatch.

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.


I honestly think people are becoming smarter and less ideological about this: values where they make sense, objects where they make sense. Values definitely are good because they don't lie, they aren't biased; you are basically doing math when manipulating them.

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.


Yes, that's exactly what it did. I started my programming career in FORTRAN and BASIC, and really appreciated the advances of structured programming and the control structures in the languages that supported it -- the Algol family, Pascal, C. I see OO as doing more of the same, providing language constructs for commonly used patterns, and I think it is very successful at doing that. I think that a lot of the OO hatred comes from OOs failure at meeting goals that were claimed during the peak of the OO hype cycle. I think that another, well-justified source of hatred is the architecture astronaut stuff -- AbstractFactoryProxyFactory and the like.

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.


> 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.


Protocols and records exist purely for polymorphism. If you want type safety, then perhaps try core.typed:

    (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))})


Scala remains ahead of Clojure because it permits traditional OO. OO is wonderful; try writing some programs in a language that forces you to do proper OO (e.g. Smalltalk). Even if you ultimately decide you prefer non-OO, you'll learn techniques that make your programs better, and you'll at least be able to understand the thing you're criticising.


> OO is wonderful; try writing some programs in a language that forces you to do proper OO (e.g. Smalltalk).

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.


> Have you tried implementing a numeric tower with proper OO in Smalltalk?

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.)


> 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"...?

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.


Pattern matching is overused in Scala, dispatch also works well via trait flexible compositions, which also provide a Wadler compliant solution to the extension/expression problem. But I guess it is a question of taste: Martin's 1000+ line mega match, or my 100 trait solution.


Scala does have more support for OO than Clojure with traits, case classes and pattern matching, and generics but Clojure does have enough support for OO for basic service creation. See https://github.com/gengstrand/clojure-news-feed as an example where Clojure's defprotocol, defrecord, defmulti, and defmethod are used to implement a basic CRUD style RESTful API for 4 entities in about 300 lines of code.


>Are we beginning to see the tipping point where mainstream corporates are starting to question whether traditional OO is the right way to go?

Nope. http://www.tiobe.com/index.php/content/paperinfo/tpci/index....

First functional language on that list is F# at 19.


Yes? No? Let's avoid false binary choices. A better question here is "to what degree?"

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!


"beginning to see" != "already at". There is TONS of existing code written in OO languages--you can't expect functional languages to replace that overnight. However, functional languages like Clojure and F# are starting to become more common, even in corporate environments. (I know eBay and Wallmart use Clojure for some of their projects, among others.)

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.


But uptick is not significant enough to say that they have enough momentum. Most companies like amazon write services in lots of different languages. Just using a language is not enough proof, do you have examples of major services written in functional languages at these enterprise companies?


Agreed there need to be "more" wins, but the amazon service seems like a pretty big one.

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.


> 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.

<sarcasm> Not to start a flame war, IMHO functional bigots just like to incite language wars rather than solving real problems. </sarcasm>


I've been writing Clojure almost exclusively for 3 or 4 years and it's just amazing. Core.async, Quil, Om, Chestnut, ClojureScript, ClojureScript + Apache Cordova, and I could go on forever.


Just learning Clojure now. Would you do us newbies a favor and say a few words about the projects you mention: what they do, why we should look into them? There is much to learn, so a shove in the right direction(s) would be useful.


Core.async is an official Clojure and ClojureScript library that takes channels from the Go language and adds them to Clojure in a much nicer way.

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.


> ClojureScript + Apache Cordova

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?


I don't know if they're any that have been open-source but I've made a few with ease. Cordova has a nice plugin repository so you can use pretty much the entire device with nothing but JavaScript calls via ClojureScript => http://plugins.cordova.io


How's the performance with Sencha & PhoneGap? I've made several apps (with Angular, Ionic & Ember) and the performance has always varied from bad to utter shit.


Sencha Touch is the most performant mobile framework that I've experienced. I will admit that it takes some time to get acquainted with Sencha Touch intricacies. If you pay no attention to resource control (primarily: how many elements you are creating without destroying them) you can get a bad experience. Of course, we're talking about apps that don't require a lot of non-traditional components. I think this route is the best choice for fast prototyping of cross-platform mobile apps. And, I think it's the ideal choice, unless you have a large enough team and budget to code out native versions for you target platforms. Here is an example of an app I did for a startup I was working on. It uses CoffeeScript + Sencha + PhoneGap + some custom native plugins for PhoneGap.

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.


Thanks. I might give phonegap one last try with Sencha.


Thanks!


New users on the JVM-only (no Clojurescript) may want to use Pulsar instead of core.async.


Can you explain why?

Pulsar looks nice, but I'm not quite sure why users (especially new ones) should prefer it.


It does everything that core.async does (in fact, it even has a compatible interface) and more.

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).


Thanks! That is interesting alright, will have to look into Pulsar some more, I guess.


I recommend checking out Reagent as an Om alternative. I've tried both and like how simple and "pure" Reagent is. There's almost nothing to it (where as Om is a bit more complicated)


Not mentioned in the article but most interesting to me this year is how these guys are "building a bank from scratch in Brazil with Datomic and Clojure": https://www.youtube.com/watch?v=7lm3K8zVOdY

The future looks bright for the language, especially with applications like this.


Clojure is awesome. However I don't want it to become too popular, as then those who do currently use it will lose all our magical powers if everyone has access to it :)


Are people finding it easy/easier to fill clojure positions?


My team which uses Clojure recently decided to grow. I regularly attend a local Clojure focused Meetup, and it is very easy to find interested developers there. The Meetup, which meets in Philadelphia, has over 150 members, so at least there is a large number of people interested.


I work 50%+ in Clojure as an IT Consultant and here in Europe it's not that easy to find a company that uses Clojure and embraces its benefits.

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.


I'd like to add that I'm starting a Clojure job next Monday at a "boring" company that you would never think would have a heavy reliance on Clojure. I think that there's a demand for Clojure developers that is unmet. I keep getting recruiters and etc. messaging me about Clojure.


Citi?


Nah, it's at a company called RentPath. They own Rent.com, Apartment Guide, etc. I'll be a remote engineer.


Apartment Guide gave me a mug at Clojure/West last year...I was a little surprised that they were so invested in Clojure that they were sending multiple devs with boxes of swag to a Clojure conference. The devs I talked to also said they weren't very experienced with Clojure yet.


Microsoft/Nokia is using Clojure to power the web services behind MixRadio.


I'm from MixRadio and we're actually about 40 engineers, not all doing Clojure. Pretty much all of our new micro-service work is done using Clojure. Not sure how many others in wider Microsoft/Nokia.

Edit: making it clearer.


I know that the Nokia Map people in Berlin use clojure.


I am surprised that no one here has yet mentioned Clojure in connection with Big Data. At OSCON 2014 ( see http://glennengstrand.info/analytics/fp ), I was first introduced to Cascalog which allows you to write Hadoop map reduce jobs in Clojure. Both Cloudera and Hortonworks support it.


I am not sure I would use RedMonk Index as popularity measure.

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....


Red Monk's inputs are at least numbers based on tracks left by actual programmers and not meaningless search results.

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.


Most Clojure programmers are Java programmers - http://cemerick.com/2012/08/06/results-of-the-2012-state-of-...

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.


Since Clojure adoption is picking up, what about convincing management to use other Lisps now? Clojure is okay, but I much prefer Scheme (Guile, Racket, Chicken, etc.).


Remember that the JVM is the major selling point for clojure. (that said there are many other lisps for the JVM)


Not only the JVM (which is rock-solid at this point) but also immutability, persistent data structures, the separation between values and identities and its solution to the expression problem which is protocols.

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.


I'm hoping it's just the gateway drug. The JVM is a monster.


Monster? It's the best and fastest JIT that exists...


Faster than LuaJIT? ;)


A good monster like Godzilla, or a bad one like King Ghidorah? Either way, could you explain why you think so?


Probably not yet. Clojure's greatest selling point to management is still that you can just drop in a jar.

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.


>Clojure has a strong opinion on immutability and functional programming. I'm not sure those Schemes do.

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.


Between Guile, Chicken and other *nix Schemes which would you recommend for general scripting and admin task automaton? Which has a more expansive library ecosystem? I found that Clojure isn't the best fit for thEse tasks because of the start-up time and the JVM dependency.


Have you read http://wingolog.org/archives/2013/01/07/an-opinionated-guide... ? It might help you weigh your options and make a pick that best suits your preferences. I don't think you could go wrong with Guile or Chicken. I use Guile pretty much exclusively and it has a good POSIX API, so I write scripts in Scheme instead of Bash or Perl or whatever.


Racket has loads of libraries and I used it happily for a long time for automating everyday tasks (recently I switched to Python since we use it at work and I needed to learn it.)


disclaimer: no actual experience of this but...

the scheme shell maybe? scsh.net

here's some snippets:

http://scsh.net/contrib/wiki/CodeSnippets.html


Racket is wonderful.


There is a r7rs scheme (kawa) that runs interpreted on the jvm and can compile down to class files.


We maintain a growing list of companies using Clojure here - http://clojure.org/companies




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: