Re: Closures versus objects

"Joe Marshall" <[email protected]>
Newsgroups gmane.comp.lang.lightweight
Message-ID <[email protected]>
On 2/15/07, Mike Newhall <[email protected]> wrote:
>
> One topic that seems to have been a perennial or at least occasional
> topic of discussion is the relationship between closures and objects
> and their substitutability.  Chistian Queinnec mentions this
> dichotomy / competition in Lisp In Small Pieces.  I have not yet had
> the experience of witnessing such a fight so perhaps it would be
> educational to instigate one here. :-)

Troll!

> Some questions for your consideration:
>
> Closures clearly can be used to make object-like things, and objects
> can be used to make closure-like things.  Is one demonstrably
> "better" than the other, in a theoretic or practical sense, or both?

In a theoretic sense, objects and closures are isomorphic, or if your
theory is abstract enough, identical.  In a practical sense, however,
there are often restrictions on the use of one or the other that makes
it necessary to choose a particular one for a task.  I personally
favor closures because there are often fewer restrictions on their use
and the semantics of function calling is usually well supported in a
language.

The special syntax of objects has its advantages, though.  Objects
tend to have an ideomatic use pattern that the compiler can take
advantage of, and the special syntax can reduce the clutter associated
with building objects out of closures.  Other programmers may find it
easier to understand the code if the object parts are clearly
delineated.

> Concretely, from a language-design point of view, is it redundant to
> include both features?  (assuming a "general purpose" language is
> the goal, for some value of general) Or is it merely theoretically
> redundant, but in practice it is useful to have both?

I'd say it ought to be theoretically redundant.  If your language
doesn't support anonymous first-class procedures *and* proper tail
recursion, then the closures may not be powerful enough to do
everything you want.  In that case, you may need special objects to
work around some of these limitations.  But even if the closures have
the power to be objects, you still may want an `object system' for the
convenience.

> If the main use of closures is to associate data with code, and the
> mechanism of capturing the lexical context is merely a means to an
> end, then "closure-like" objects are possible even in languages with
> no concept of capturing the stack.

Only if they are first-class.  Some languages have closures that
cannot be returned from a function, only passed down.  Others require
explicit copying of the context.

> Nevertheless closures would seem to have the edge when you need
> something that behaves exactly like a function.

One particular advantage of a closure is that it unifies message
passing with function calling.

> But some OO languages allow you to invoke an object with
> function-like syntax.  In C++, this is merely syntactic sugar, but
> there's no reason a language couldn't be designed to allow objects
> to be invoked in a way semantically identical to functions (ignoring
> CLOS generics for the moment, surely some OO languages already do
> this; Python?  JavaScript?), invoking some default method.

C# has this with delegates.

> This equivalence can break down however when, for example, an
> external entity like the OS requires a callback function, and the
> semantics of invoking the callback are outside the playpen where
> this equivalence is implemented, so that only true closures would
> work in the context.  But this could be said of many language
> features.  It's of particular concern in the C++ world where C
> calling conventions for OS callbacks are the norm and object
> invocation is not an option.  (For that matter, any language with
> closures attempting to use a C callback has to solve this problem.)

There are standard tricks for dealing with this.

> Objects would seem to have the edge when you want the relationship
> between functions that share state to be explicit both syntactically
> and in the language.  This may be necessary to enforce inheritance &
> access rules and so on.  Also it would seem that if everyone rolled
> their own OO system with closures they would inevitably be
> incompatible, although a standard library might obviate that.

That is certainly one great advantage of a canonical `object system'.

> Or could closures and objects be unified into a single datum, such
> that foo() invokes "the" closure function but foo.method() invokes
> other functions sharing the same state?  (This is the same semantics
> suggested above but with the extension that lexical closures do
> exist in the language, and any time a closure is captured, it
> generates an object indistinguishable from those produced by
> constructors.)

Yes.  In fact Larceny does it this way.

> As a perhaps separate thought, what are closures useful for?

Programming.  It is really hard to program mechanism for binding data
to code.  Almost all languages supply some way to do this.  The
supplied mechanism may be very limited, but you can find something
isomorphic to some sort of closure hiding in there somewhere.

> That is, for those of you who have had the luxury of programming in
> a language with closures for many years, what uses have you found
> that might not be obvious to programmers that have grown up
> closure-deprived?  How would you "sell" closures to programmers
> steeped in old habits?  What's your "Top 10" (or Top 3) list of the
> cases where closures do the job better or make life easier?

#1: Continuation passing style.

#2: MAPCAR (and other higher-order functions, but this is the
    archetype)

--
~jrm
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.