[rdnzl-devel] CL-CLR, an alternative way of working with RDNZL
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))
(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: http://22.214.171.124/cl-clr.zip
This message was sent using IMP, the Internet Messaging Program.
More information about the rdnzl-devel