From: [EMAIL PROTECTED] Date: Thu, 28 Aug 2008 12:43:20 -0700 (PDT) Author: allison Date: Thu Aug 28 12:43:19 2008 New Revision: 30622
I've not responded to all your comments, just some of the key ones that I hope will promote understanding. I won't commit any changes until after I hear what you have to say. (Some of the hunks have been reformatted for readability.) @@ -41,6 +41,13 @@ case, some translation may be required by both the calling language and the called language: +{{ There seems to be an implied basic assumption here that language +interoperability is the responsibility of the language +implementor. It is not. We cannot require that language +implementors design and implement their languages according to some +global specification. If you are not happy with that assumption, then I'm surprised you bothered to commit this draft at all, even as a starting point. Even then, surely, it must *still* be the responsibility of the language implementor not to introduce gratuitous barriers to interoperability? As a case in point, consider keyword (named) parameters in Lisp. Kea-CL does not use Parrot named parameters to implement "&key", partly for ANSI compliance and partly for efficiency. This currently makes it problematic (though not impossible) for other languages to call Lisp functions that accept keywords. You can either say I'm a bad boy for not fully using Parrot features and "require" me to "design and implement ... according to some global specification," forcing me to solve the performance vs. compliance vs. interoperability tradeoff in each sub, or allow me to do my own thing internally and accept the need for glue around the edges (which in turn requires compliance with another specification). Another example is object system metamodel compatibility. I am not an expert on metamodels, but all the ones I *think* I know make it very hard for me to imagine inheritance across language boundaries without some very careful design and coding on the part of language implementors on both sides of the boundary. (Who will no doubt be grateful for "some global specification" to help them in that work. ;-) +Any interoperability +infrastructure must be provide by Parrot, and must work for all languages. +--allison }} Do you really think that Parrot can subsume all object system metamodels well enough to provide all the infrastructure? Just the CLOS and Perl 6 MOPs are each complicated enough on their own; I'm tempted to advocate $n^2$ metamodel interfaces in order to break the problem down into manageable chunks. (And, not incidentally, push the problems onto the people who understand them.) @@ -117,6 +132,8 @@ call intra-language subs, they should be very sure they understand that language's calling conventions. +{{ It's not possible to define a sub that can't be called externally --allison }} Not now, true. Except that we currently support ".sub foo :anon ..." for compilation-unit scoping. Are you saying you object to language scoping of subs? @@ -139,13 +156,22 @@ access the module API (though it may need additional hints). Of course, that also requires a PIR API for accessing this metainformation . . . +{{ Exporting is very much a Perl idea, not much applicability for exporting +outside of Perl. --allison}} Eh? I think we are having another terminology issue. By "export" I meant "make public." Perl is not the only language to use this term; just off the top of my head I can think of CL and Erlang. @@ -175,6 +201,10 @@ functions, i.e. a method defined for C<VECTOR> must be considered when passed a string as a parameter. +{{ Common Lisp (for example) will have its own set of type relationships, +because it will have its own set of types . . . I *could* represent CL strings explicitly as vectors of characters instead of using the String type. But that would mean that I couldn't use the wealth of Parrot string ops, and would be inviting more interoperability problems to boot. Ditto for Integer and Float, which are exactly what I need in terms of representation. CL does not need new types for these. And that is a good thing. @@ -235,6 +275,12 @@ floating-point result from Common Lisp code that happens to get two integers from Perl or Lua (or both!). +{{ Not a bug, it's the expected result. Divide operations are multi-dispatched. +If you pass two Common Lisp integers into a divide operation in Perl 5, it'll +search for the best matching multi, and if it finds one for Common Lisp +integers (an exact match), it'll run that and return a Common Lisp ratio. +--allison }} We are at an impasse, then. But I suppose it doesn't matter. If language implementers believe that is OK, then they can accept whatever the builtin returns. If not, they can use MMD to define any exceptions they require. @@ -242,6 +288,10 @@ inputs to these operations differently; they can all be represented by the same C<Integer> PMC class. +{{ The whole point of having sets of PMCs in different languages is to handle +the case where "it's an integer, but has a different division operation than +other languages" --allison}} You are not persuaded by my argument that PMC classes are about representation, and "multi variants" are about operation semantics? In any case, language-specific PMC classes are not needed for this purpose, only language-specific operations. @@ -278,6 +331,10 @@ specialize the other operands, in the hope that other exotics are subclasses of these. +{{ It is perfectly fine for a Lisp arithmetic operator to return a RATIONAL +subtype. Please don't define methods for a pile of operations that already have +vtable functions --allison }} When I said "methods" here, I was actually speaking of defining "multi variants" for that Lisp arithmetic operator. Does that help? @@ -287,10 +344,18 @@ responsibility of the language that defines the exotic class, since it is in charge of its internal representation. +{{ The default multi for a common operation like division will call the PMC's +C<get_number> vtable function, perform a standard division operation, and +return a standard Integer/Number/BigNum. --allison }} ??? C<get_number> always returns a float, which would force the answer to be a float (in all languages I can think of). But, yes, this is a reasonable default. {{ We can define multimethods on another language without loading it, can't we? If not, then making this work may require negotiation between language implementors, if it is feasible at all. -- rgr, 31-Jul-08. }} +{{ I'm not sure what you mean by defining multimethods on another language. +Perhaps you're asking if it's possible to declare a multisub for a type that +doesn't exist yet? --allison }} I would like to be able to define a "multi variant" on another language that handles my language's types, without loading the other language, so that *if* the other language is ever loaded, it handles the new types gracefully. @@ -301,20 +366,31 @@ Define language-specific operations using multimethods (to avoid conflict with other languages). +{{ Clarify? How would non-multi's conflict? --allison }} Method dispatch is done by string lookup on the operation name; there are no package names to bind the operation to a language implementation. =item 2. Define them on the highest (most general) possible PMC classes (in order that they continue to work if passed a subclass by a call from a different language). +{{ Define them on the class that makes sense. There's no point in targeting any +particular level of the inheritance hierarchy. --allison }} Yes, but I'm trying to explain what makes sense. But I'll add "... the highest ... PMC classes that make sense" if you like. @@ -328,6 +404,12 @@ {{ This section is meant to answer Geoffrey's "What does Lisp do with a Perl 5 Scalar?" question. I gotta think about this more. -- rgr, 29-Jul-08. }} +{{ The scalar decides when to morph, not the language. All the languages that +have morphing scalars implement them in such a way that they know how to +handle, for example, morphing when a string value is assigned to an integer +scalar, and what to do if that value is later used as an integer again. +--allison }} This is not about assignment, but about use: If you pass a "5" from Perl to a Lisp function that tries to use it as a number, Lisp would normally barf. Arguably, it should just coerce it to a number (not least because it may be hard to control the representation from the Perl side), but that still leaves the question: How does Lisp recognize that it's OK in this case? @@ -372,10 +467,14 @@ . . . Several questions arise for languages with multiple representations for aggregate types. Typically, this is because these types are more restricted in some fashion. [finish. -- rgr, 29-Jul-08.] +{{ Not clear where you're going with this --allison }} Neither was I. ;-} In one of the inter-HLL thread in late July, somebody mentioned Tcl aggregates as being problematic: Sometimes they act as arrays, and sometimes as hashes (IIRC). This is where I wanted to address such things, but didn't have enough of a clue. @@ -383,6 +482,9 @@ hand, if a language doesn't support functional arguments, then there is no hope of using an API written in another language that requires them. +{{ Hmmm? They're just subs, how would they not be callable from another +language? --allison }} If the *calling* language doesn't have a syntax for "pass this function to this other function," then there's no hope of using a foreign API that requires that. (Not that there are many such languages targeted by Parrot.) @@ -397,6 +499,10 @@ could Ruby do with a Scheme list when it can't even get to the Scheme C<car> function? +{{ Except that Ruby would never even get a Scheme list in the first +place if it hadn't loaded a Scheme library of some sort. And, being +a list, the Scheme list would still support the standard vtable +functions for lists. --allison }} ??? What "standard vtable functions for lists"? What's a "standard list" in this context? @@ -408,9 +514,14 @@ not need anything out of the ordinary, from either language or the called module author. -- rgr, 29-Jul-08. }} +{{ There is a common introspection API, the 'inspect' vtable +function. But what you're describing here isn't introspection, it's +actually the standard vtable functions. --allison }} If we're lucky, yes. If not, we'll have to define more. But I'm still fuzzy on what's needed here, so I'm afraid I can't be more concrete. @@ -430,10 +545,20 @@ necessary) around it. It is therefore not expected that all compilers will provide a way to define methods on all foreign classes for all language pairs. +{{ These should generally be handled by subclassing the parent +language class, and adding your method to the subclass. Possibly. But you may have trouble getting the called module to create instances of your new class. +Monkeypatching is certainly possible, but not encouraged. Cool; a new term in Allison-speak! ;-} But it need not apply. If your application defines a new "multi variant" that dispatches on a class you define, then it cannot conflict with other uses of the multisub. And even for methods (as you define them), I understand this is acceptable Ruby, for example, where it is also called "duck punching." +And, there really isn't any distinction between "treating the new +method as part of the calling language" and "treat[ing] the new +method as part of the foreign language". It's a method, you call it +on an object, the class of the object determines how it's found and +invoked. --allison }} If that's true, then great. It may be that I'm being too pessimistic, worrying about how to achieve CL AMOP compliance *and* be Parrot-friendly at the same time. (But that only affects multis, since Lisp doesn't do single-dispatch per se.) @@ -441,10 +566,16 @@ specialized only on Parrot or called-language classes, then the compiler should take care to make it generally usable. +{{ Not sure what you mean here. --allison }} Again, by "method" I meant "multi variant." If the new variant defined in the called-language multisub is specialized on at least one calling-language class, then it can only be invoked by code that is already aware of both languages, and less care is required. (I think.) =head3 Subclassing across language boundaries {{ This is an important feature, but requires compatible metamodels. -- rgr, -29-Jul-08. }} +29-Jul-08. + +Or Proxy PMCs, which is how we're currently handling inheritance across +metamodel boundaries. --allison +}} Which means we probably need a section describing how those proxy PMCs get created. @@ -458,6 +589,11 @@ hack for obligate OO languages like Ruby.) Defining methods across the boundary is harder, and may not be worth the trouble. -- rgr, 29-Jul-08. }} +{{ That's "multiple dispatch" and "single dispatch". In general, +defining code in one language and injecting it into the namespace of +another language isn't the primary focus of language +interoperability. Using libraries from other languages is. +--allison }} I don't see a sharp boundary between "using libraries" and "injecting [code] into the namespace" myself. -- Bob