Skip to content

Instantly share code, notes, and snippets.

@runexec
Last active June 17, 2020 03:47
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save runexec/786b92b97b5a3a0ffac7 to your computer and use it in GitHub Desktop.
Save runexec/786b92b97b5a3a0ffac7 to your computer and use it in GitHub Desktop.
Clojure Does Objects Better

Clojure does Objects Better

A hopefully short and concise explanation as to how Clojure deals with Objects. If you already write Clojure, this isn't for you.

You know what an Interface is if you write/read Java or PHP 5+. In Clojure it might be called defprotocol.

user> (defprotocol IABC
        (also-oo [this])
        (another-fn [this x]))
IABC

You might be tempted to use the classic implements or extends keywords when defining a new Class. In Clojure it might be called defrecord.

user> (defrecord ABC [name]
        ;; You can implement multiple Classes here
        IABC
        (also-oo [this]
          (str "This => " (:name this)))
        (another-fn [this x]
          (format "%s says: %s" (:name this) x)))
user.ABC

You might be tempted to use the classic new keyword to instantiate a new object. In Clojure it might be a simple decimal suffix added to the Class name so that it can be used as a predicate.

user> (def a (ABC. "Roger"))
#'user/a
user> (another-fn a "oo programing")
"Roger says: oo programing"
user> (also-oo a)
"This => Roger"

Clojure can just do it better.

user> (defmulti this-is-oo type)
nil
user> (defmethod this-is-oo ABC [this]
        (println (:name this)))
#<MultiFn clojure.lang.MultiFn@8625d0e>
user> (this-is-oo a)
Roger
user> (defmethod this-is-oo java.lang.String [this]
        "Got a string and not ABC!!!!")
#<MultiFn clojure.lang.MultiFn@8625d0e>
user> (this-is-oo "a")
"Got a string and not ABC!!!!"
@davelnewton
Copy link

@nilliams

[...] homoiconicity offers no practical benefit in the day-to-day, team-building-an-app environment

I'd argue that has more to do with (a) the apps you write, and/or (b) how you write them.

If you're not using anything macro-like then it's likely not a benefit. If you don't need highly-malleable functionality it may not be a benefit, but in my experience even a light layer of macros can vastly improve readability and communication.

Over the years it still seems to me that until you actually need and/or use it it will never be obvious why this is a good thing. This is partially because it's difficult to externalize what strikes Lisp-y people as obvious. Personally I advocate using the functionality until it's difficult to live without it--then the benefits are clear.

(Macros can be horribly, terribly abused, of course, perhaps to a greater degree than any other language feature. That's not a language issue, but one of discipline, documentation, and system-/environment-level knowledge.)

@nilliams
Copy link

nilliams commented Dec 4, 2014

@andrewchamer I'm not confusing readability with familiarity. I put myself in a camp that believes that code syntax like class makes code more expressive and I take my definition of readability from how well the code expresses its intention.

@davelnewton I've never met a programmer who wrote macros I've wanted to use. I'm yet to come across a macro in the Clojure book I want to use. Macros as far as I can tell have been considered a bad idea in the C world and C-style language worlds for a very long time, because if any one macro offered benefit enough that it warranted inflicting that macro on your teammates, it'd be added to the language.

Every now and then a framework in a non-macro-supporting language I use or am interested in proposes something that could likely be created with macros that seems genuinely useful, but that is really once in a blue moon. As a modern example I'm thinking of something like the annotations the Angular.js team are adding by creating AtScript for Angular 2.0.

Yet still I'd rather use their invented superset language and deal with all the drawbacks that brings abstraction-wise and tooling-wise than move to a language that completely sacrifices expressive syntax in the name of homoiconicity and reads like an AST.

@davelnewton I realise I've wandered off on a rant here - I guess I'm saying I don't believe that 'even a light layer of macros can vastly improve readability and communication', and even if I did I think I'd rather see those macros applied to a language with more syntax for day-to-day programming than Clojure offers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment