Closures and Objects Are Equivalent
c2.com
c2.com
Here it is:
The venerable master Qc Na was walking with his student, Anton. Hoping
to prompt the master into a discussion, Anton said "Master, I have
heard that objects are a very good thing - is this true?" Qc Na looked
pityingly at his student and replied, "Foolish pupil - objects are
merely a poor man's closures."
Chastised, Anton took his leave from his master and returned to his
cell, intent on studying closures. He carefully read the entire
"Lambda: The Ultimate..." series of papers and its cousins, and
implemented a small Scheme interpreter with a closure-based object
system. He learned much, and looked forward to informing his master of
his progress.
On his next walk with Qc Na, Anton attempted to impress his master by
saying "Master, I have diligently studied the matter, and now
understand that objects are truly a poor man's closures." Qc Na
responded by hitting Anton with his stick, saying "When will you
learn? Closures are a poor man's object." At that moment, Anton became
enlightened.
Now I will be the first to admit that I usually just don't get koans. But I think I get this one. Objects and closures are equivalent in the sense that what you can do with one you can do with the other. However, for each particular case one may be better (easier to use, more natural, whatever) than the other. You should use which ever one is the best for each particular problem.This is of course easier if you are using a programming language that natively supports both closures and objects...
foo.DoSomething()
... // remember not to return
// without foo.Done() called
// (EDITed for clarity:
// foo is the state, that changes,
// so you have to keep track of
// its changes)
foo.Done()
vs DoSomething (func(){
... // don't have to remember
// a thing, no side-effects,
// equivalent of .Done() is
// called afterwards for you
})
EDIT2: exact behavior is not the point, keeping track of things is. DoSomething(func() { ... })
becomes DoSomething(new Runnable() {
public void run() { ... }
});
or the longer form class MyAction implements Runnable {
public void run() { ... }
}
DoSomething(new MyAction());If you're considering a language deficient of functions then we can take advantage exactly of the idea that objects can embed functions by having a "callable" thing.
foo#doSomething (object
method call : unit -> unit =
...
end)Of course it's not a hard-and-fast distinction: you can have a closure that dispatches on one of its parameters to do one of several different things, and you can have an instance with only one method. But it's usually valid.
Imagine you have a closure with a function that takes in a string and a list and returns a list. Depending on implementation of the function, you could have the string be the operation you wish to perform. The method name, and the list be the parameters. The returned list is the output.
Getters could pass an empty list and return a list with one entry
Setters could pass a list with a value and return an empty list
And so on :)
Like this:
func NewClosure() func(string, ...float64) []float64 {
x := float64(0)
return func(method string, args ...float64) []float64 {
if method == "setX" && len(args) > 0 {
x = args[0]
return nil
} else if (method == "getX") {
return []float64 { x }
} else {
panic("invalid method")
}
}
}
a := NewClosure()
b := NewClosure()
a("setX", 50)
b("setX", 12)
fmt.Printf("a.X = %v, b.X = %v", a("getX")[0], b("getX")[0])
Runnable example here: http://play.golang.org/p/68NTyEx6_PI like it.
[edit: added working example .. and realized I'm adding to what my parent poster was saying]
Consider this simple syntactic rule: `obj.x` <=> `obj("x")`. With this rule, the usual syntax for a method call, `obj.method(x)`, literally becomes the curried application of a closure, `obj("method")(x)`. You could also add a rule like `obj(x) = y` <=> `obj(set(x, y))`. Then you could define objects a bit like this:
point = (x, y) -> method ->
match method:
"x" -> x
"y" -> y
set("x", newx) -> x = newx
set("y", newy) -> y = newy
"add" -> (pt) -> point(x + pt.x, y + pt.y)
p = point(1, 2)
p.x = 5
print p.add(point(3, 4))
All closures. And the nice thing with that scheme is that meta-programming and reflection become completely trivial. Control over the interface is total. What use is there for "real" objects in this situation?(Functions + tuples + recursion) is powerful enough to embed objects very nicely though!
In OOP, there are pieces of data that have operations associated with them. Two objects are free to have their own "version" of the same operation (same-named), and when you invoke it on an object, you get that object's version. In writing one of those operations, you have a handle on the thing you're operating on without having to take it as an argument. This specifies what result you'll compute and what side effects you'll cause by invoking an operation (i.e., the semantics). It does not specify things like where in program memory the code for that operation will live or how invoking it will work (implementation).
Gamma, x : a |- e : b
--------------------------
Gamma |- \x -> e : b
But you could also have "bare functions" if you liked x : a |- e : b
----------------------
. |- \x -> e : b
This would force all names to be explicitly applied, I think.Similarly, “implementation inheritance” (where every class is either sealed/final or abstract) is how we express sum types.
We can simulate type classes in C# by using implicit casts to abstract classes (interestingly, it’s not so straightforward to simulate the awesomeness of type classes in F#).
The key to all of this is to realize that “types” and “classes” are not equivalent, even though C# and Java conflate them.
If you mean "Are Haskell type classes equivalent to Go interfaces?", the answer is no, Haskell type classes are substantially more powerful, even before you start turning on extensions. For instance, "Go" can not express the Monad typeclass at all.
At this point I start trying to turn toward System F, but that's my hammer for this particular nail and I don't know an equivalent one in the object side of things. I'm certain you can express higher-level things in System F which are equivalent to interfaces. I know there's a translation of typeclasses to System F—it's called Haskell, har har—although you have to recognize that the "search" component of typeclasses will be lost.
But actually I don't think that this duality is related to types: in a static language, the types of captured variables does not appear in a value's type. And for the object side, the type of instance variables is hidden behind the public interface too.
So it's really more about techniques for creating abstractions than how the values are composed together.
Of course you can dispatch anything you like within that call, turning a closure back into "methods", although in most languages that's a fairly painful way to operate even though if it is possible. Personally over the years I've come more around to tel's point of view, which is that as related as objects and closures may be, they aren't quite just two sides of the same coin, as further evidenced by the fact that pretty much all modern OO languages also include closures. If they really were the same thing in two guises somebody would probably have fully unified them by now, but they aren't the same thing. As much fun as the koan is, I think it's false wisdom.
a struct of three closures :)
EDIT:
I'm not sure I understand your point. Here's how to return three closures without the struct.
Objects are more useful as you don't need to repeat the environment to implement more than 1 operation.
Both objects and closures can be type erased so that the environment is not part of their type.
A clojure carries its own states (variables) that it, only, can modify. While the states (variables) of an object can be changed by another method for the same object, or by a class method, or even methods from another object if it uses method variables.