[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: s-exprs + prototypes



James McCartney wrote:
> Consider that an object can be thought of as a function and a selector
> is its argument. Now lets say that you write a macro to define objects
> that have only one method 'apply' and you can elide that from the
> argument list.
> Now you have Lisp.

But you've built Lisp on top of a system which inside its objects, already
supported functions - it's a bit like building bricks out of houses.  It's
Lisp with unnecessary baggage.  Write up a formal model of this language
implementation and there's a whole lot of unnecessary stuff, serving no
purpose whatsoever, which can just be thrown away.  The same isn't true the
other way around.

I'd be more impressed if you could expose the function-like constructs used
in the implementation of methods, without having to create objects with an
apply method.

> So with my virtual machine you should be able to implement something
> like Lisp in a single macro.
> In Lisp it would take some work to implement prototype inheritance.

Right, but the only things you can implement "in a single macro" like that
are things that are already built into the language.  If that's a benefit,
then the ultimate language would be one in which an entire suite of useful
paradigms were already implemented, waiting to be revealed with a macro or
otherwise.  Done right, I'd buy that language.  But with only one paradigm
implemented, and pervasively deployed, you have to really love that
paradigm.  It's in this sense that I'm saying these languages are less
general.

* * *

BTW, Javascript seems pretty relevant to this discussion: it supports
standalone first-class functions, with full closure support, as well as
prototype-based objects.  I've written a fair amount of Javascript code, but
I only know a little about its internal design.  Its functions are in fact
"function objects", so perhaps this would be an example of the sort of
system you're talking about, where functions have been implemented on top of
a general object system.  However, their "apply" method is the normal
function call syntax, i.e. funcobj(foo) invokes the function object and
passes it the parameter foo; and there's no real difference between
functions and methods, i.e. obj.funcobj(foo) does the same thing except with
obj becoming an implicit "this".

This is all part of the design of the core language, and users can use these
functions directly, without having to explicitly package them in an object.
Internally, though, standalone functions are a kind of illusion - they
essentially become methods of a Global object.

Still, this has two related features that I like better than what I've been
hearing here: first, the functionality of standalone functions, with full
closures, is provided as a standard part of the language, making Javascript
at least dual-paradigm; and second, methods and functions are implemented by
the same construct, i.e. there isn't some inaccessible internal method
construct which has to be built on top of in order to create something more
like a function.

An interesting aspect of this dual behavior in Javascript is it means that
you can create two different kinds of instance variable in Javascript
objects: opaque closure-based variables, and more dynamic slot-based
variables, e.g.:

  function MyObj(x, y) {
    var product = x * y;  // local variable
    this.sum = x + y;
    this.getX = function () { return x; }
    this.getY = function () { return y; }
    this.getProduct = function () { return product; }
  }

  o = new MyObj(7,4);
  o.getX();       // 7, retrieved from closure of getX's function object
  o.sum;          // 11, retrieved from object slot
  o.getProduct(); // 28, retrieved from getProduct's closure
  o.x;            // doesn't exist
  o.product;      // doesn't exist

If you prototype fans will just make sure your languages can do this, I'll
stop bothering you.  ;)

Anton