On Tue, Nov 10, 2009 at 11:13 AM, logicmoo@gmail.com wrote:
Oh the above was attempting to describe LarKC SubLisp implementation of this article: http://www.ibm.com/developerworks/java/library/j-dyn0610/ I couldnt find it before sending the email!
Hmm looks interesting, still haven't had the time to read it, but I'll surely do!
The intial LarKC implemention used reflection in the same maner as InlinedPrimive does. The after reading that article, I found I could replace Method[] cache inside InlinedPrimive with generated methodStubs produced runtime for reflection performance.
but consider also that the implementation through reflection is the default one, for convenience, but you can still override the various execute() methods and call the static method directly (of course, you have to make sure the method you call is the same as the one you pass in the constructor, or things start to behave differently in interpreted vs compiled code and that's definitely not good :D). Something like
new InlinedPrimitive(My.class, "myMethod", ...) { public LispObject execute(LispObject arg) { return My.myMethod(arg); } }
Yup, InlinePrimtive still leaves that option open. If someone really wanted to, they can do that with a couple of their InlinedPrimtives if they noticed one particualtar method was getting called quite a bit. Making the instance execute call the static function (Like EQ/EQL/EQUAL for instance avoiding reflection.)
The class I posted lacks the constructors taking the class and the method, because I have been lazy ;), but they can easily be added - with the caveat that, since the call to super() must be the first and for Function super() sometimes (always?) installs the function in a symbol (iirc), if you pass a wrong class/method to InlinedPrimitive and as a result an exception is thrown, you'll have a symbol pointing to an invalid function.
I realy do like how you did it as factory method:
public static final Primitive COPY_TREE = InlinedPrimitive.get(Primitives.class, "copyTree", Symbol.COPY_TREE, "object");
And depending on safety/speed you could save the string name of the class and method name for later and not even try to resolve the method[] until first time call.. and signal an error then if not found. This could be used like autoloading.
I have attached an updated patch that should do that: optionally only look for the methods on the first invocation (or compilation), based on a flag passed to the InlinedPrimitive when it's created (I can't probably depend on a Lisp variable because primitives are loaded very early on, but I haven't investigated in detail). In passing I also removed a check that was done on each invocation (interpreted), to see if the appropriate method existed or not: now methods are initialized with default implementations that signal a wrong number of arguments error, so they can be invoke()d without checks. I also changed a bit the static method get, naming it init() and making it accept a pre-created InlinedPrimitive. This is because otherwise I would have had to write a lot of get() overloads (one per constructor times 2, one with the "lazy" flag and one without, defaulting it to false for convenience), and it would have made subclassing InlinedPrimitive more awkward. So now the copy-tree example looks like:
public static final Primitive COPY_TREE = InlinedPrimitive.init(new InlinedPrimitive(Symbol.COPY_TREE, "object"), Primitives.class, "copyTree", true);
Not pretty as before, but still acceptable imho.
I haven't tested it much.
Bye, Ale