Efficient compilation of functions with keyword arguments Lassi Kortela (22 Jul 2019 15:08 UTC)
|
Re: Efficient compilation of functions with keyword arguments
Per Bothner
(23 Jul 2019 00:31 UTC)
|
Efficient compilation of functions with keyword arguments Lassi Kortela 22 Jul 2019 15:08 UTC
Robert Strandh, author of the Common Lisp implementation SICL, graciously replied to my inquiry and took the time to explain keyword arguments to us in detail. - Option 1 is self-evaluating keyword objects that Common Lisp uses. - Option 2 is Racket/Kawa style keywords-as-argument-list-markers. -------- Forwarded Message -------- Subject: Re: Efficient compilation of functions with keyword arguments Date: Mon, 22 Jul 2019 From: Robert Strandh To: Lassi Kortela Hello, Option 1 is indeed very simple. There is no special ways to call a function. In fact, Common Lisp does not require &KEY parameters to be symbols in the KEYWORD package. Any symbol will do. You just have to use the syntax ((symbol variable) [init-form [supplied-p-parameter]]) for it, rather than (variable [init-form [supplied-p-parameter]]). Option 1 is quite costly for the callee. Common Lisp also allows the same keyword to occur multiple times in the argument list, in which case the first one is the one that counts. In addition, it is always possible to supply :ALLOW-OTHER-KEYS <true> to suppress the validity check for keyword arguments. This freedom implies that, for each keyword parameter, the callee needs to search the the argument list (after required and optional arguments have been removed) from the start to determine whether a value for the parameter was given. However, option 1 also gives a lot of flexibility. A common idiom is to have an intermediate function modify the argument list only slightly, perhaps prefixing a keyword/value pair, and then call a second function. That way, the intermediate function is ignorant of what keyword arguments the ultimate callee can handle, which improves modularity. Here is an example: (defun foo (arg &rest more-args &key &allow-other-keys) (apply #'bar arg :new-key val more-args)) I don't see how you can get this flexibility with option 2. The most common way of dealing with the performance problem of keyword arguments is to define a compiler macro that recognizes a direct call of the function (as opposed to through APPLY). It can then parse the argument list at compile time and turn the entire call into one that calls a special version of the callee, with only required arguments. It is not trivial, given the requirement that Common Lisp evaluate the arguments from left to right, but it can be done. I can't say much of the performance implications of option 2 since I am unfamiliar with the way it is typically implemented. Hope this helps. Regards, -- Robert Strandh