From: Allison Randal <[EMAIL PROTECTED]> Date: Tue, 02 Sep 2008 01:15:18 +0200
Thank you for responding so promptly; I doubt I will be able to "return fire" on your schedule. Bob Rogers wrote: > As a case in point, consider keyword (named) parameters in Lisp. > Kea-CL does not use Parrot named parameters to implement "&key" > . . . Well, my main question from that is what it is about Parrot named parameters that don't work for Kea-CL. (It may be something we can fix.) I will answer this now, since you ask, and because I had written it up for the previous post and then decided that it was too much detail. Please see below. But, what I expect from Kea-CL with a unique parameter-passing style is that your libraries clearly document how to call the subroutines. That's all. If people find libraries written in your language too obtuse to bother with, then they simply won't use them. Yes. If I do nothing else, then this corresponds to "option c" below, which meets my criteria for "too obtuse." There are an awful lot of "must"s in the draft, where there should be only free will. Guilty as charged. My intent is usually "must do X in order to maximimize interoperability", but that is not clear. "Should" is much better. And the rest will have to wait until I have more time. -- Bob ------------------------------------------------------------------------ To explain why I think it is inevitable that language implementors will have to shoulder at least some of the burden, let me describe an interoperability problem that affects Kea-CL (and ANSI-compliant Common Lisp implementations in general). The ANSI spec says two things about keyword parameters [1] that constrain how they can be implemented in Parrot: 1. Keyword parameters are typically named by symbols in the KEYWORD package, but are permitted to be named by any object; such objects are tested for identity when binding keyword parameters. Therefore, the symbols ":foo" and "frobboz::foo" are distinct as keyword parameter names, even though they might stringify the same [2]. 2. At the point of call, there is no distinction between different kinds of parameters. For example, in the call (test-function foo "bar" :start1 17) the last two arguments could supply values to a single keyword parameter named :start1, or to the third and fourth positional parameters. Or the whole thing could be a single &rest (slurpy) parameter; the compiler is not allowed to guess here [3]. Because Parrot named parameters are handled as a separate class of parameter, and are always named by strings, that presents a severe problem. An implementation can choose to: a. Punt on ANSI compliance, mapping Lisp keywords onto Parrot named parameters. I don't think this possible, since there's no way to tell at the point of call. b. Adopt a hybrid approach and declare keyword parameters as Parrot named parameters, adding some extra processing logic to handle conversion; i.e. all functions support both protocols. If the named parameters are filled by a non-Lisp call, add them to any &rest list; if an &rest list has keyword values that are not yet supplied, stuff the values in the named parameters. This ought to work (I haven't tried it), but entails a certain amount of extra overhead, even for the Lisp-to-Lisp case. c. Use the straightforward Lispy implementation (i.e. by ignoring Parrot named parameters altogether) and insist that the caller supply &key arguments using Lisp symbols as positional parameters. Any caller would have to do the equivalent of (intern "FOO" (find-package "KEYWORD")) just to look up the parameter name for ":foo". (This is the current unsatisfactory state of affairs). d. Use the straightforward Lispy implementation (i.e. by ignoring Parrot named parameters altogether) and plan to provide a wrapper for each API function that has keywords for foreign calling. My proposal is about option d, because I think that is the best option for Lisp, and I think it should work well for other languages, too. [1] http://www.lispworks.com/documentation/HyperSpec/Body/03_dad.htm [2] But "stringification" is not a CL concept anyway. Coercion to string is usually tied up with printing, but printing yields different results depending on context. [3] Some compilers optimize based on prior knowledge of the definition being called, but that is not strictly legal, and always requires a non-default level of optimization.