Does there exist anything like CLOS (Common Lisp Object System) for Clojure?
Have you considered Clojure's data types (especially defrecord), protocols, and multimethods? All three will always be more idiomatic within Clojure than a port of CLOS on top of these mechanisms.
Clojure itself doesn't have an object system, for two reasons:
Clojure is specifically designed to be hosted on an object-oriented platform and it then simply absorbs the underlying platform's object system. I.e. ClojureJVM has the JVM object system, ClojureCLR has the CLI object system, ClojureScript has the ECMAScript object system, and so on.
Rich Hickey hates objects.
But, you can obviously implement an object system in Clojure. Clojure is, after all, Turing-complete.
Mikel Evins is working on a new approach to OO which he calls Categories. He has implementations for several Lisps, including Clojure (although not all the ports are guaranteed to be up-to-date all the time).
Categories is slowly being subsumed by Bard, a new Lisp dialect that Mikel is designing, which has Categories built in. (Which then, in turn, may become the implementation language for Closos, an idea Mikel had for how to design an operating system.)
Clojure does not have CLOS and doesn't want CLOS but you could implement it.
Clojure wants to be immutable so to have mutable OO would be kind of stupid, but you can have a kind of OO.
http://clojure.org/datatypes (look at defrecord --> the best of classes and hash-maps)
http://clojure.org/protocols (kind of like interfaces but better)
http://clojure.org/multimethods (powerful because you can write your own dispatch functions)
With these three things you should be able to fulfill all your needs, but most of the time, its best to just use normal functions and the standard data structures.
Using the OO paradigm is ideal for writing loosely coupled code, mocking and testing. Clojure makes this so easy to accomplish.
One problem that I had ran into in the past was code depending on other code. Clojure namespaces actually exacebate the problem if not used well. Ideally, namespaces can be mocked out but as I have found... there are a lot of problems with mocking out namespaces:
https://groups.google.com/forum/?fromgroups=#!topic/clojure/q3PazKoRlKU
Once you start building bigger and bigger applications, the namespaces start depending upon each other and it gets really unweldy to test your higher-level components seperately without having a bunch of dependencies. Most of the solutions involve function re-binding and other black magic but the problem is that come testing time, the original dependencies are still being loaded -> which grows into big problem if you have a big application.
I was motivated to to look for alternatives after using database libraries. Database libraries have brought me so much pain - they take ages to load and usually are at the core of your application. Its very difficult to test your application without bring a whole database, the library and associated peripherals into your test code.
You want to be able to package your files so that parts of your system that depend on your database code can be 'swapped out'. OO design methodology provides the answer.
I'm sorry the answer is quite long... I wanted to give a good rationale for why OO design is used more so than how it is used. So an actual example had to be used. I have attempted to keep the ns declarations so that the structure of the example application will be kept as clear as possible.
existing clojure style code
This example uses carmine, which is a redis client. It is relatively easy to work with and is quick to start up compared to korma and datomic, but a database library is still a database library:
(ns redis-ex.history
(:require [taoensso.carmine :as car]
[clojure.string :as st]))
(defmacro wcr [store kdir f & args]
`(car/with-conn (:pool ~store) (:conn ~store)
(~f (st/join "/" (concat [(:ns ~store)] ~kdir)) ~#args)))
(defn empty [store kdir]
(wcr store kdir car/del))
(defn add-instance [store kdir dt data]
(wcr store kdir car/zadd dt data))
(defn get-interval [store kdir dt0 dt1]
(wcr store kdir car/zrangebyscore dt0 dt1))
(defn get-last [store kdir number]
(wcr store kdir car/zrange (- number) -1))
(defn make-store [pool conn ns]
{:pool pool
:conn conn
:ns ns})
existing test code
all the functions should be tested... this is nothing new and is standard clojure code
(ns redis-ex.test-history0
(:require [taoensso.carmine :as car]
[redis-ex.history :as hist]))
(def store
(hist/make-store
(car/make-conn-pool)
(car/make-conn-spec)
"test"))
(hist/add-instance store ["hello"] 100 100) ;;=> 1
(hist/get-interval store ["hello"] 0 200) ;;=> [100]
object orientated dispatch mechanism
The idea that 'OO' isn't evil but actually quite useful came to me after watching this talk Misko Hevery:
http://www.youtube.com/watch?v=XcT4yYu_TTs
The basic idea is that if you want to build a big application, you have to separate the 'functionality' (the guts of the program) from the 'wiring' (the interfaces and the dependencies). The less dependencies the better.
I use clojure hash-maps as 'objects' because they have no library dependencies and are completely generic (see Brian Marick talking about using the same paradigm in ruby - http://vimeo.com/34522837).
To make your clojure code 'object orientated' you need the following function - (send stolen from smalltalk) which just dispatches a function associated with a key in a map if it is associated with an existing key.
(defn call-if-not-nil [f & vs]
(if-not (nil? f) (apply f vs))
(defn send [obj kw & args]
(call-if-not-nil (obj kw) obj))
I provide the implementation in a general purpose utility library (https://github.com/zcaudate/hara in the hara.fn namespace). It's 4 lines of code if you want to implement it for yourself.
defining the object 'constructor'
you can now modify the original make-store function to add functions in the map. Now you have a level of indirection.
;;; in the redis-ex.history namespace, make change `make-store`
;;; to add our tested function definitions as map values.
(defn make-store [pool conn ns]
{:pool pool
:conn conn
:ns ns
:empty empty
:add-instance add-instance
:get-interval get-interval
:get-last get-last})
;;; in a seperate test file, you can now test the 'OO' implementation
(ns redis-ex.test-history1
(:require [taoensso.carmine :as car]
[redis-ex.history :as hist]))
(def store
(hist/make-store
(car/make-conn-pool)
(car/make-conn-spec)
"test"))
(require '[hara.fn :as f])
(f/send store :empty ["test"])
;; => 1
(f/send store :get-instance ["test"] 100000)
;; => nil
(f/send store :add-instance ["test"]
{100000 {:timestamp 1000000 :data 23.4}
200000 {:timestamp 2000000 :data 33.4}
300000 {:timestamp 3000000 :data 43.4}
400000 {:timestamp 4000000 :data 53.4}
500000 {:timestamp 5000000 :data 63.4}})
;; => [1 1 1 1 1]
build abstraction
so because the make-store function constructs a store object which is completely self contained, functions can be defined to take advantage of this
(ns redis-ex.app
(:require [hara.fn :as f]))
(defn get-last-3-elements [st kdir]
(f/send st :get-last kdir 3))
and if you want to use it... you would do something like:
(ns redis-ex.test-app0
(:use redis-ex.app
redis-ex.history)
(:require [taoensso.carmine :as car]))
(def store
(hist/make-store
(car/make-conn-pool)
(car/make-conn-spec)
"test"))
(get-last-3-elements ["test"] store)
;;=> [{:timestamp 3000000 :data 43.4} {:timestamp 4000000 :data 53.4} {:timestamp 5000000 :data 63.4}]
mocking with clojure - 'OO' style
So the real advantage of this is that the get-last-3-elements method can be in a completely different namespace. it does not depend on the database implementation at all and so testing this function now only requires a lightweight harness.
mocks are then trivial to define. Testing of the redis-ex.usecase namespace can be done without loading in any database libraries.
(ns redis-ex.test-app1
(:use redis-ex.app))
(defn make-mock-store []
{:database [{:timestamp 5000000 :data 63.4}
{:timestamp 4000000 :data 53.4}
{:timestamp 3000000 :data 43.4}
{:timestamp 2000000 :data 33.4}
{:timestamp 1000000 :data 23.4}]
:get-last (fn [store kdir number]
(->> (:database store)
(take number)
reverse))})
(def mock-store (make-mock-store))
(get-last-3-elements ["test"] mock-store)
;; => [{:timestamp 3000000 :data 43.4} {:timestamp 4000000 :data 53.4} {:timestamp 5000000 :data 63.4}]
The earlier posts address the question as a question about the value and possibilities of implementing specific support for various features of object-oriented programming in Clojure. However, there is a family of properties that are associated with that term. Not all object-oriented languages support all of them. And Clojure directly supports some of these properties, whether you want to call that support "object-oriented" or not. I'll mention a couple of these properties.
Clojure can support dispatch on hierarchically defined types using its multimethod system. The basic functions are defmulti and defmethod. (Maybe these weren't available when the question was first answered.)
One of the relatively unusual features of CLOS is its support for functions that dispatch on the types of multiple arguments. Clojure emulates that behavior very naturally, as an example here suggests. (The example doesn't use types per se--but that's part of the flexibility of Clojure's multimethods. Compare with the first example here.)
CljOS is a toy OOP library for Clojure. It is by no sense of the word complete. Just something I made to have fun.
It's an old post but I wanted to respond to it.
No clojure has no OO support, and no CLOS support. The underlying object system of the environment is only barely available in the sence of interoperability, not for making your own class/objects hierarchies in clojure. Clojure is made for easy access to CLR or JVM libraries, but OOP support end here.
Clojure is a lisp and support closures & macros. With thoses 2 features in mind, you can develop a basic object system in a few lines of code.
Now the point is do you really need OOP in a lisp dialect ? I would say no and yes. No because most problem can be solved without an object system and more elegantly in any lisp. I would say yes, because you'll still need OOP from time to time and it is then better to provide a standard reference implementation than having every geek implementing it's own.
I would recommand that you take a look at On Lisp book, from Paul Graham. You can consult it free of charge online.
This is really a good book, that really grasp the essence of lisp. You'll have to adapt the syntax a little to clojure, but concepts remain the same. Important for your question, one of the last chapter show how to define your own object system in lisp.
A side remark, clojure embrace immutability. You can make a mutable object system in clojure, but if you stick to immutability, you design, even using OOP will be quite different. Most standard design pattern and construction are made with mutability in mind.
Related
I was playing with this in 2018.01:
my $proc = Proc.new: :out;
my $f = $proc.clone;
$f.spawn: 'ls';
put $f.out.slurp;
It says it can't do it. It's curious that the error message is about a routine I didn't use and a different class:
Cannot resolve caller stdout(Proc::Async: :bin); none of these signatures match:
(Proc::Async:D $: :$bin!, *%_)
(Proc::Async:D $: :$enc, :$translate-nl, *%_)
in block <unit> at proc-out.p6 line 3
Everything inherits a default clone method from Mu, which does a shallow clone, but that doesn't mean that everything makes sense to clone. This especially goes for objects that might hold references to OS-level things, such as Proc or IO::Handle. As the person who designed Proc::Async, I can say for certain that making it do anything useful on clone was not a design consideration. I didn't design Proc, but I suspect the same applies.
As for the error, keep in mind that the Perl 6 standard library is implemented in Perl 6 (a lot like in Java and .Net, but less like Perl 5 where many things that are provided by default go directly to something written in C). In this particular case, Proc is implemented in terms of Proc::Async. Rakudo tries to trim stack traces somewhat to eliminate calls inside of the setting, which is usually a win for the language user, but in cases like this can be a little less helpful. Running Rakudo with the --ll-exception flag provides the full details, and thus makes clearer what is going on.
The Perl6 standard grammar is relatively large. Although this facilitates expression once mastered, it creates a barrier to mastery. For instance, core constructs often have multiple forms supporting different programming paradigms. A basic example is the variety of syntaxes for creating Pairs:
Pair.new('key', 'value'); # The canonical way
'key' => 'value'; # this...
:key<value>; # ...means the same as this
:key<value1 value2>; # But this is key => <value1 value2>
:foo(127); # short for foo => 127
:127foo; # the same foo => 127
Note, in particular, the comment on the first form: "The canonical way".
Another example is the documentation for method make:
This is just a little sugar for $/.made = $ast which is a very common operation in actions.
Is there a canonical form that one may output for a Perl6 program so that, having mastered the canonical sub-grammar, one may inspect any Perl6 program in that form to comprehend it?
I'd say that the Perl6 grammar (in particular the roast) is the canon, so all those forms are sort of 'canonical'. That comment refers to what is actually happening when any of the other forms are compiled/executed. The .new() method for the Pair class gets called to create the new Pair object. That happens, behind the scenes, so to speak, regardless of which of the options you use. The other syntaxes are just easier ways to express the same thing.
You might find the .perl() method helpful. It will describe the way any variable can be expressed in Perl:
> Pair.new('key', 'value').perl
:key("value")
> ('key' => 'value').perl
:key("value")
> (:key<value>).perl
:key("value")
I will use a simple example to illustrate my question. In Java, C, or any other OOP language, I could create a pie class in a way similar to this:
class Apple{
public String flavor;
public int pieces;
private int tastiness;
public goodness(){
return tastiness*pieces;
}
}
What's the best way to do that with Scheme? I suppose I could do with something like this:
(define make-pie
(lambda (flavor pieces tastiness)
(list flavor pieces tastiness)))
(define pie-goodness
(lambda (pie)
(* (list-ref pie 1) (list-ref pie 2))))
(pie-goodness (make-pie 'cherry 2 5))
;output: 10
...where cherry is the flavor, 2 is the pieces, and 5 is the tastiness. However then there's no type-safety or visibility, and everything's just shoved in an unlabeled list. How can I improve that?
Sidenote: The make-pie procedure expects 3 arguments. If I want to make some of them optional (like I'd be able to in curly-brace languages like Java or C), is it good practice to just take the arguments in as a list (that is treat the arguments as a list - not require one argument which is a list) and deal with them that way?
Update:
I've received a couple answers with links to various extensions/libraries that can satisfy my hunger for OOP in scheme. That is helpful, so thank you.
However although I may not have communicated it well, I'm also wondering what the best way is to implement the pie object above without such classes or libraries, so I can gain a better understanding of scheme best practices.
In some sense, closures and objects are equivalent, so it's certainly possible. There are a heaping helping of different OO systems for Scheme -- a better question might be which one to use!
On the other hand, if this is an educational exercise, you could even roll your own using the closure-object equivalency. (Please forgive any errors, my Scheme is rather rusty.)
(define (make-pie flavor pieces tastiness)
(lambda (selector)
(cond ((eqv? selector 'flavor) flavor)
((eqv? selector 'pieces) pieces)
((eqv? selector 'tastiness) tastiness)
((eqv? selector 'goodness) (* pieces tastiness))
(else '()))))
This is a simple constructor for a pie object. The parameter variables flavor, pieces and tastiness are closed over by the lambda expression, becoming fields of the object, and the first (and for simplicity's sake here, only) argument to the closure is the method selector.
That done, you can instantiate and poke at some:
> (define pie1 (make-pie "rhubarb" 8 4))
> (define pie2 (make-pie "pumpkin" 6 7))
> (pie1 'flavor)
"rhubarb"
> (pie1 'goodness)
32
> (pie2 'flavor)
"pumpkin"
Many Schemes allow you to define classes that contain fields and methods. For example, see:
Bigloo Object System
PLT scheme Classes and Objects
This is how I would recommend implementing this:
(define PersonClass (lambda (name age strength life)
(let ((name name)(age age) (life life) (strength strength))
(lambda (command data)
(cond
((< life 1)
"I am dead")
((equal? command "name")
name)
((equal? command "age")
age)
((equal? command "birthday")
(set! age(+ age 1)))
((equal? command "receive damage")
(begin (set! life(- life Data)) (display "I received damage\n")))
((equal? command "hit")
(data "receive damage" strength))
)))))
Use it like such: (Karl "name" 0)
Most schemes support SRFI-9 records or the similar R7RS records, and R6RS also provides records with slightly different syntax. These records are a way to make new types in scheme. In addition, most schemes, together with R6RS and R7RS, support modules or libraries, which are one way to encapsulate operations on such types.
Many scheme programmers use these instead of OOP to write their programs, depending on the nature of the application. The record provides the type and its fields; an associated procedure is provided which creates new objects of this type; other procedures which take the record as an argument (conventionally the first argument) provide the required operations on the type; and the module/library definition determines which of these are exported to user code and which are private to the implementation of the module/library.
Where a field of the record is itself a procedure, it can also have private data as a closure: but often you want to use the module definition for data hiding and encapsulation rather than closures (it is also usually more efficient).
Scheme uses a single namespace for all variables, regardless of whether they are bound to functions or other types of values. Common Lisp separates the two, such that the identifier "hello" may refer to a function in one context, and a string in another.
(Note 1: This question needs an example of the above; feel free to edit it and add one, or e-mail the original author with it and I will do so.)
However, in some contexts, such as passing functions as parameters to other functions, the programmer must explicitly distinguish that he's specifying a function variable, rather than a non-function variable, by using #', as in:
(sort (list '(9 A) '(3 B) '(4 C)) #'< :key #'first)
I have always considered this to be a bit of a wart, but I've recently run across an argument that this is actually a feature:
...the
important distinction actually lies in the syntax of forms, not in the
type of objects. Without knowing anything about the runtime values
involved, it is quite clear that the first element of a function form
must be a function. CL takes this fact and makes it a part of the
language, along with macro and special forms which also can (and must)
be determined statically. So my question is: why would you want the
names of functions and the names of variables to be in the same
namespace, when the primary use of function names is to appear where a
variable name would rarely want to appear?
Consider the case of class names: why should a class named FOO prevent
the use of variables named FOO? The only time I would be referring the
class by the name FOO is in contexts which expect a class name. If, on
the rare occasion I need to get the class object which is bound to the
class name FOO, there is FIND-CLASS.
This argument does make some sense to me from experience; there is a similar case in Haskell with field names, which are also functions used to access the fields. This is a bit awkward:
data Point = Point { x, y :: Double {- lots of other fields as well --} }
isOrigin p = (x p == 0) && (y p == 0)
This is solved by a bit of extra syntax, made especially nice by the NamedFieldPuns extension:
isOrigin2 Point{x,y} = (x == 0) && (y == 0)
So, to the question, beyond consistency, what are the advantages and disadvantages, both for Common Lisp vs. Scheme and in general, of a single namespace for all values versus separate ones for functions and non-function values?
The two different approaches have names: Lisp-1 and Lisp-2. A Lisp-1 has a single namespace for both variables and functions (as in Scheme) while a Lisp-2 has separate namespaces for variables and functions (as in Common Lisp). I mention this because you may not be aware of the terminology since you didn't refer to it in your question.
Wikipedia refers to this debate:
Whether a separate namespace for functions is an advantage is a source of contention in the Lisp community. It is usually referred to as the Lisp-1 vs. Lisp-2 debate. Lisp-1 refers to Scheme's model and Lisp-2 refers to Common Lisp's model. These names were coined in a 1988 paper by Richard P. Gabriel and Kent Pitman, which extensively compares the two approaches.
Gabriel and Pitman's paper titled Technical Issues of Separation in Function Cells and Value Cells addresses this very issue.
Actually, as outlined in the paper by Richard Gabriel and Kent Pitman, the debate is about Lisp-5 against Lisp-6, since there are several other namespaces already there, in the paper are mentioned type names, tag names, block names, and declaration names. edit: this seems to be incorrect, as Rainer points out in the comment: Scheme actually seems to be a Lisp-1. The following is largely unaffected by this error, though.
Whether a symbol denotes something to be executed or something to be referred to is always clear from the context. Throwing functions and variables into the same namespace is primarily a restriction: the programmer cannot use the same name for a thing and an action. What a Lisp-5 gets out of this is just that some syntactic overhead for referencing something from a different namespace than what the current context implies is avoided. edit: this is not the whole picture, just the surface.
I know that Lisp-5 proponents like the fact that functions are data, and that this is expressed in the language core. I like the fact that I can call a list "list" and a car "car" without confusing my compiler, and functions are a fundamentally special kind of data anyway. edit: this is my main point: separate namespaces are not a wart at all.
I also liked what Pascal Constanza had to say about this.
I've met a similar distinction in Python (unified namespace) vs Ruby (distinct namespaces for methods vs non-methods). In that context, I prefer Python's approach -- for example, with that approach, if I want to make a list of things, some of which are functions while others aren't, I don't have to do anything different with their names, depending on their "function-ness", for example. Similar considerations apply to all cases in which function objects are to be bandied around rather than called (arguments to, and return values from, higher-order functions, etc, etc).
Non-functions can be called, too (if their classes define __call__, in the case of Python -- a special case of "operator overloading") so the "contextual distinction" isn't necessarily clear, either.
However, my "lisp-oid" experience is/was mostly with Scheme rather than Common Lisp, so I may be subconsciously biased by the familiarity with the uniform namespace that in the end comes from that experience.
The name of a function in Scheme is just a variable with the function as its value. Whether I do (define x (y) (z y)) or (let ((x (lambda (y) (z y)))), I'm defining a function that I can call. So the idea that "a variable name would rarely want to appear there" is kind of specious as far as Scheme is concerned.
Scheme is a characteristically functional language, so treating functions as data is one of its tenets. Having functions be a type of their own that's stored like all other data is a way of carrying on the idea.
The biggest downside I see, at least for Common Lisp, is understandability. We can all agree that it uses different namespaces for variables and functions, but how many does it have? In PAIP, Norvig showed that it has "at least seven" namespaces.
When one of the language's classic books, written by a highly respected programmer, can't even say for certain in a published book, I think there's a problem. I don't have a problem with multiple namespaces, but I wish the language was, at the least, simple enough that somebody could understand this aspect of it entirely.
I'm comfortable using the same symbol for a variable and for a function, but in the more obscure areas I resort to using different names out of fear (colliding namespaces can be really hard to debug!), and that really should never be the case.
There's good things to both approaches. However, I find that when it matters, I prefer having both a function LIST and a a variable LIST than having to spell one of them incorrectly.
As a non-lisper coming to clojure how should I best understand the naming convention where vars get a name like *var-name*?
This appears to be a lisp convention indicating a global variable. But in clojure such vars appear in namespaces as far as I can tell.
I would really appreciate a brief explanation of what I should expect when an author has used such vars in their code, ideally with a example of how and why such a var would be used and changed in a clojure library.
It's a convention used in other Lisps, such as Common Lisp, to distinguish between special variables, as distinct from lexical variables. A special or dynamic variable has its binding stored in a dynamic environment, meaning that its current value as visible to any point in the code depends upon how it may have been bound higher up the call stack, as opposed to being dependent only on the most local lexical binding form (such as let or defn).
Note that in his book Let Over Lambda, Doug Hoyte argues against the "earmuffs" asterix convention for naming special variables. He uses an unusual macro style that makes reference to free variables, and he prefers not to commit to or distinguish whether those symbols will eventually refer to lexical or dynamic variables.
Though targeted specifically at Common Lisp, you might enjoy Ron Garret's essay The Idiot's Guide to Special Variables. Much of it can still apply to Clojure.
Functional programming is all about safe predictable functions. Infact some of us are afraid of that spooky "action at a distance" thing. When people call a function they get a warm fuzzy satisfaction that the function will always give them the same result if they call the function or read the value again. the *un-warm-and-fuzzy* bristly things exist to warn programmers that this variable is less cuddly than some of the others.
Some references I found in the Clojure newsgroups:
Re: making code readable
John D. Hume
Tue, 30 Dec 2008 08:30:57 -0800
On Mon, Dec 29, 2008 at 4:10 PM, Chouser wrote:
I believe the idiom for global values like this is to place asterisks
around the name.
I thought the asterisk convention was for variables intended for
dynamic binding. It took me a minute to figure out where I got that
idea. "Programming Clojure" suggests it (without quite saying it) in
chapter 6, section 3.
"Vars intended for dynamic binding are sometimes called special vari-
ables. It is good style to name them
with leading and trailing asterisks."
Obviously the book's a work in progress, but that does sound
reasonable. A special convention for variables whose values change (or
that my code's welcome to rebind) seems more useful to me than one for
"globals" (though I'm not sure I'd consider something like grid-size
for a given application a global). Based on ants.clj it appears Rich
doesn't feel there needs to be a special naming convention for that
sort of value.
and...
I believe the idiom for global values like this is to place asterisks
around the name. Underscores (and CamelCase) should only be used when
required for Java interop:
(def *grid-size* 10)
(def *height* 600)
(def *margin* 50)
(def *x-index* 0)
(def *y-index* 1)