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

Re: a table of c funtion pointers



On Mon, 24 Jul 2000 15:00:02 -0400 (EDT), Futeh Kao <fkao@infoware.com> wrote:

> Because of some other issues, I ended up having to resort to write some C
> glue
> code.  The C glue code is fairly small and entirely platform independent (no
> Win32 specific calls). In any case, I've successfully started a Java VM and
> called some methods.  I do have one additional problem:  there is a <C-long>
> class, however, it is the same size as <machine-word>, whereas Java long is
> 64 bit.  Hmm ... any clean solutions besides resorting to my C glue code
> again?

Fun-Dev includes a <double-integer> implementation in the big-integers library.
Take a look at the factorial example which doesn't use <double-integer>s
directly, but instead alters the normal module bindings so that <integer>
includes them.

> Another question I have, because of my limited few days of experience with
> Dylan,
> is that how does it support delegation and dynamic compiling.  In Smalltalk
> or
> Objective-C, when a method is not understood by an object, the object is
> given the chance to handle it by implementing the doesNotUnderstand: method.
> This is very useful when designing a generic proxy server system.  To do
> the same thing in Java, one can use the dynamic proxy interfaces newly
> introduced in JDK 1.3.  How does Dylan permit this behavior?  

As the others have pointed out, Dylan doesn't have this kind of technology. In
part this is because Dylan doesn't use message-passing OO, but instead uses
generic-function OO. With message-passing there is a principle object which you
can query, but with generic functions there isn't.

As Hugh hints, if the error class were better defined one could catch the error
and retry via some delegate function. Eg untested pseudo code:

define macro with-delegation
  { with-delegation ()
      ?body:body
    end; }
  =>
  { block
      ?body
    exception ( e :: <no-applicable-method> )
      delegate( e.arguments.first, e );
    end; }
end macro;

Then you could define a delegate method specializing on your proxy class that
trampolines to an inner object, eg

define method delegate
  ( object :: <proxy>, except :: <no-applicable-methods> )
  apply( except.function, except.args.first.inner, except.args.but-first );
end method;

And the default delegate method would be:

define method delegate
  ( object :: <object>, except :: <no-applicable-methods> )
  error( except );
end method;

This glosses over a lot of issues, but you get the idea.

--

The conventional way of doing proxy forwarding in Dylan is to define a proxy
mixin for the methods that you want. Then you can inherit this anywhere you
want to an only bother overriding the methods each class cares about.

eg

// framework class holds next in chain of delegates

define abstract class <proxy> ( <object> )
  slot next :: <object> = #f, init-keyword: next:;
end class;

// you define your proxy class that forwards all its methods to its delegate

define class <foo-proxy> ( <proxy> )
end class;

define method bar ( x :: <foo-proxy>, ... )
  bar( next( x ), ... );
end method;

define method baz ( x :: <foo-proxy>, ... )
  baz( next( x ), ... );
end method;

// you can then define other classes that act as proxies for this kind of 
// object by just mixing in the proxy class and overriding the methods you want

define class <quux> ( ... <foo-proxy> )
end class;

define method bar ( x :: <quux>, ... )
  ...
end method;

It is still labourious to define the proxy class though and it doesn't
automatically deal with new methods.

Ultimately you could move up a level an reify your function calls as objects in
their own right, then you could invoke them and delegate them as you wished. In
theory, you could still hide all this in function call syntax via macros.

Eg

define macro foo
  { foo( ?x:expression, ?y:* ) }
  =>
  { delegate( foo, ?x, ?y ) }
end macro;

define method delegate ( f :: <function>, x :: <bar>, ... )
  f( x.next, ... );
end method;

Or some such...

__Jason


Follow-Ups: References: