[1160] in java-interest

home help back first fref pref prev next nref lref last post

Re: "perform:" and Java

daemon@ATHENA.MIT.EDU (Doug Lea)
Fri Aug 25 05:01:33 1995

Date: Tue, 22 Aug 1995 13:11:18 -0400
From: Doug Lea <dl@altair.cs.oswego.edu>
To: mikef@xnet.com, clp@home.HarvardSq.com
CC: java-interest@java.sun.com
In-reply-to: <199508171545.KAA25978@cyclone.xnet.com> (message from Mike
	Fleming on Thu, 17 Aug 1995 10:45:37 -0500 (CDT))


The lack of something analogous to smalltalk closures/perform, lisp
eval, and so on in an otherwise dynamic language is indeed a
challenge. Here are some thoughts about it.

As a bare running example, suppose for a moment that Java did in fact
have a generic `eval' operator, that could evaluate a message
represented by a string, as in:


class X {
  public Float foo(int i);
  ...
}

class User1 {
  void use(X x, int i) { Float f = (Float)(eval("x.foo(i)")); }
  ...
}

You can't do that in Java. But you can hand-translate this
particular message into a little helper class, such as:

interface Action { Object exec(); }

class XdoFoo implements Action {
  private X x_;
  private int i_;
  public XdoFoo(X x, int i) { x_ = x; i_ = i; }
  public Object exec() { return x_.foo(i_); }
}

(This little Thunk-like class is essentially what smalltalk, lisp, and
the like would construct as an intermediate form of the expression.)

... and then use it like this:

class User2 {
  void use(X x, int i) { Float f = (Float)(new XdoFoo(x, i)).exec(); }
  ...
}

... and/or pass it around:

class User3 {
  void use(X x, int i) { doIt(new XdoFoo(x, i)); }
  void doIt(Action t) { Float f = (Float)(t.exec()); }
  ...
}


Now, this is useless in the present context, since if you knew exactly
what message you wanted to send (i.e., foo(i)) in User.use, you'd just
send it directly without bothering to make a closure.

However, if you don't know (or, in the cases I'm most interested in,
you can't know, since such messages are going over a network to/from
remote objects), this intermediate form is very useful. Or would be,
if you could only build it on the fly (i.e., DURING program execution),
so you could pass it around, and generally use it in the same way you'd
use a smalltalk closure.

Which you can! There's nothing except a bunch of hard work stopping
you from actually compiling, loading, and executing a Thunk in the
midst of program execution. The Java compiler is just a set of java
classes that can be invoked at run time (and even if it weren't, you
could write it yourself in Java). Combined with the dynamic loading
facilities, you have the makings of `perform'.

In other words, the Java equivalent of performing a smalltalk closure
is something of the general form:

  1. Translate the message string into a class (i.e., like XdoFoo)
  2. Compile the class in the current context, generating bytecoded .class form
  3. Load the compiled .class form
  4. Create a new instance of this class with suppied arguments
  5. Invoke the sole method of this class on this object

(There are a couple of minor variants of this as well.)

Some advantages of thinking about the issue this way are:

  * It cannot possibly affect Java security provisions, since it is
       all done `on top of' basic Java functionality. Thus, for
       example, the compiled byte codes are verified while loaded, as
       is true for any class in Java. (Native `eval'-type constructs
       can be security problems.)
  * It does not require any language changes.
  * When combined with analogs of argument marshalling and unmarshalling,
       it provides the basis for a remote messaging facility.
  * It represents the small beginnings of lots of other kinds of
       run-time class generation, including those analogous to  
       C++ template instantiations.
  * It represents one of the beginnings of fuller meta-facilities in Java.

These advantages do NOT hold for any other similar scheme I've thought of.
But there are some disdvantages:

  * As described so far, this is hopelessly heavy (time/space consuming)
  * As described so far, this is hopelessly awkward to use.
  
While I haven't succeeded in solving them yet, I believe that these
problems are surmountable. Has anyone else tried something like this?

-Doug



    
-
Note to Sun employees: this is an EXTERNAL mailing list!
Info: send 'help' to java-interest-request@java.sun.com

home help back first fref pref prev next nref lref last post