[rdnzl-devel] CL-CLR, an alternative way of working with RDNZL

Dan Muller s8ctxw402 at sneakemail.com
Wed Mar 29 02:31:41 UTC 2006

Hi, it's just me talking to myself again.

I've discovered some shortcomings of System.Type.InvokeMember, which 
CL-CLR depends on, when it comes to passing null arguments. Also, 
there's a bug in CL-CLR with respect to ByRef types (which doesn't 
surprise me, since I hadn't looked at them in detail yet).

It will probably take me a few days to figure out how to work around 
them, while preserving some of the unique features of CL-CLR that I'm 
most interested in. If you do take a look at CL-CLR (and I still hope 
to get feedback on some of the ideas talked about in the README.txt 
file), be aware of these two problems:

- If you pass a null value as an argument, there is no type information 
for InvokeMember to use in resolving among overloaded members. If an 
ambiguity results, the call will fail.

- ByRef parameters (ref or out in C#) are not copied back out.

RDNZL containers carry quasi-static type information with them, and so 
a container representing a null object reference does, too. In CL-CLR, 
I'm experimenting with using the types derived from the object values, 
and it effectively ignores the types embedded in the containers. This 
has the interesting effect of making overloaded methods act much like 
Lisp methods (even more so than RDNZL already does), potentially 
run-time polymorphic on all parameters. And like Lisp methods, if you 
pass null (in analogy to NIL) for an argument, the only type it will 
really match is Object. But, interestingly, the default binding 
behavior in InvokeMember seems to allow a null argument to match 
anything at all, as long as there's no ambiguity -- in other words, as 
long as that particular parameter isn't overloaded.

RDNZL has some interesting problems of its own in handing ByRef 
parameters, mainly because REF modifies containers in-place. Assuming 
that some-type is a type object for SomeType, and MyStaticMethod 
returns a new value through its parameter:

(let* ((a (rdnzl:new some-type))
       (b a))
  (rdnzl:invoke "MyHandyClass" "MyStaticMethod" (ref a))
  (print a) (print b))

After the call to INVOKE, both a *and* b will reference the new object. 
Other even stranger things can happen:

(let ((a (rdnzl:new some-type)))
   (invoke a "AnInstanceMethod" (ref a)))

This fails entirely, because a becomes temporarily of type SomeType&, 
and the lookup of AnInstanceMethod fails on that type.

A possible strategy for fixing this in RDNZL: Make REF a macro taking a 
SETF-able form. It expands to a form that creates an instance of a 
RDNZL REFERENCE class, containing a reference to the result of 
evaluating the form, and a closure that will SETF the original form 
when called with a new value. INVOKE et al must detect these 
parameters, arrange to *clone* the input continer (with a new GCHandle 
value!), and use the cloned container to receive the result. Finally, 
after the member call, pass the new value to the closure.

CL-CLR is still available here for now:

Dan Muller

This message was sent using IMP, the Internet Messaging Program.

More information about the rdnzl-devel mailing list