This is the mail archive of the kawa@sourceware.cygnus.com mailing list for the Kawa project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: workaround for compiling gnu.expr.PrimProcedure literals?


brlewis@alum.mit.edu writes:

> When I try to compile the function below, I get ten errors like this:
> 
> (compiling httpfun.scm)
> <unknown>:0: unimplemented support for compiling gnu.expr.PrimProcedure literals
> [...]

We probably should add support for PrimProcedure as a literal.
It is easier now, with the new literal framework:  just have
PrimProcedure implement Externalizable, add write suitable
writeExternal/readExternal methods.  (I need to document the
details.  Basically, there needs to be either a static "make" method
or a constructor whose signature matches the calls made by
writeExternal.)

> Will it work if I rewrite it to use (primitive-interface-method ...)
> only as an argument to a procedure and don't try to assign it to a
> variable?  

Not as an argument - only as the function.

> Or can I only use (primitive-interface-method ...) directly
> in procedure application?

You can use (primitive-interface-method ...) otherwise, but
only in interpreted code, as (primitive-interface-method ...) is
a macro that gets expanded at compile-time, yielding a
PrimProcedure.  If the PrimProcedure is used in a procedure
application, then it gets inlined to a invokeinterface bytecode
instrcution, but otherwise the PrimProcedure needs to emitted
as a literal - which Kawa current can't do.  (But see above.)

Note that using (primitive-interface-method ...) directly in
procedure application (where it can be inlined) is *much* more
effcient, as it does not require reflection.

Actually, I recommend using (invoke ...) instead of
((primitive-interface-method ...) ...) as the former is easier
to read, more compact, and just as efficient.

If you need methods as explicit object, it is more efficient
to use a procedure.  For example:

  (let ((method
	 (cond ((eq? cgi-variable 'SERVER_NAME)
		(lambda ((req :: <javax.servlet.ServletRequest>))
                 (invoke req 'getServerName))
                ...

But better to just invoke the methods.

  (lambda ((req :: <javax.servlet.ServletRequest>))
    (case cgi-variable
      ((SERVER_NAME) (invoke req 'getServerName))
      ((SERVER_PORT) (invoke req 'getServerPort))
      (else ...)))

Note the use of case, which should be just as efficient as the
cond-eq-chain you wrote.  (While R4RS requires the keys to be
compared using eqv?, it is smart enough to realize that if one
of the operands of an eqv? is a symbol, then it might as well
use the faster eq? instead, since the result is the same.)
-- 
	--Per Bothner
per@bothner.com   http://www.bothner.com/~per/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]