[exprla-devel] Re: [XPL] The structure of classes in XPL
Status: Pre-Alpha
Brought to you by:
xpl2
From: reid_spencer <ras...@re...> - 2002-01-31 09:02:58
|
--- In xpl-dev@y..., Jonathan Burns <saski@w...> wrote: Some commentary on the thread so far: Alexander Gutman (Sunday 11/06/00) leads off: At this moment I am thinking about how classes will be declared in XPL. And I encountered a problem. AG (if I may) has a <me> element, with <human>, <mathematician> and <programmer> elements nested within. And he wants to know how this XPL classic would be expressed as a class (or strictly, object) in standard OOP languages. The obvious way to start off, would be to define a class for each of the inner elements, and then to define a class <me>, whose objects contain one instance each of the three, as private data. So then the question is, how does he want class <me> to look from the outside? Again, the obvious way is to add methods to the <me> interface: get_human, get_mathematician, get_programmer. Each of these methods will return a copy of the private instance of the element. What's nice is that methods so named can return lists of the desired element; a null list if the element isn't there in an instance of <me>, or a list of several, if <me> is a programmer at two different workplaces. So it's obviously feasible. As a variation, one can define class <occupation>, and subclass <mathematician> and <programmer> from it. Then we could define method: get_occupation, to return both kinds of element in a list. Richard Hein (11/06/00) replies: So if you use overloading, you call <human>, [etc] as if they were different functions in the class? Answer: Yes. But there's no special need for overloading. If what we want is to provide special interfaces for <me>, then the interfaces of classes <human>, <mathematician> etc are just what we want. OOP is working as advertised. The "different functions" in the class will just be the different methods, get_human etc, which extract the desired instances from an instance of <me>. Then Kurt Cagle comes in with the OTHER side of the question (11/06/00): [...] an XML Schema definition is more like a VB type statement than a Java class -- the schema defines the type and positional characteristics of an XML structure, but not any associated methods or events. However, you could make a superclass structure that might actually include a schema and an associated stylesheet with named templates, with templates acting as methods. The other side of the question is, can we implement some simple methods using off-the-shelf XML tech? Answers: (1) A schema or a DTD for <me> will define the element types and placement of its private data; e.g. can we have zero or multiple private instances of <human>? But a schema or a DTD will not provide us with methods for getting the private elements out of <me> - or doing anything with them if we could. (2) XPath will get the inner elements. child::mathematician() will do that job directly. And other facilities of XPath will extract elements of much more complicated documents; and count and compare and filter them besides. The limitation of XPath is that all these operations are read-only - they only ever copy data from a document. There is no provision for binding additional methods to elements on extraction. But it is worth noting, that if we are content with public nested state data in our objects, the get_ methods are built-in with XPath. To that extent, all XML documents with some defining schema or DTD are objects already. (3) XSLT will apply template operations to <me>, acting on any pattern (i.e. XPath expression) which we provide in an XSL Transform. This is the means to provide class <me> with a proper interface. But, it is not directly adapted to providing the kind of interface with which we are familiar in OOP. As far as I can make out, an XSL Transform defines one method, together with its implementation. The standard OOP interface consists of many methods, with or without implementations. This isn't much of a problem, as far as I can see. We can certainly have a transform which calls a proxy template - a stub, which can go on to call the real method implementation. And we can define an XPL class interface as a collection of transforms. Kurt goes on to say: Keep in mind that the one primary difference between XML and procedural objects is that the XML instance of a schema may not necessarily be physically connected with the methods that operate on it. We should thus ask whether XPL works by keeping the XML instance data of a class as part of the object -- i.e., the XML acts as the local variables -- or the XML data arrives as input and is processed in real time against the XPL/XSLT templates (in which case the XPL objects are methods only). The former is a statist approach -- the data needs to be retained between calls, while the latter is stateless. Well, I'm not necessarily against statist approaches. The data has to be stored somewhere, after all - it's just a matter of how far away we want to push the commitment to stored data. But we will want to provide an indirection mechanism, where the data for the pattern to be recognized in a transform is not present in the object, but is assembled on the fly. It looks as if such a mechanism has to be built into XPath, though. For our purpose here, XPath needs to recognize: <programmer ref=[URI] > </programmer> or some such. I will say, that if we develop XPL as statelessly as possible, we will wind up in the company of the extreme functional languages, which have to admit constant data eventually; but by that time, they have pushed it into an obscure corner of the syntax, which nobody can quite remember. (E.g., you get a major realm tacked on, of addresses trying to pretend they are get_ functions and failing.) Such languages do produce some beautiful dataflow plumbing, however. Alexander replies (12/06/00): Hmm... Could you clarify this idea? Somewhat clarified, I hope. As far as I know, the output of a transformation procedure is always an XML document/object and, furthermore, we cannot perform any actions during transformation other than those which reflect the output (probably, the 'eval'; XSL element can produce some side-effects during transformation, I do not know). This raises the question, Is XSLT as powerful as we would like? I'm undecided so far. XSLT provides quite the arsenal of tree- building operations, and on first glance I can't gauge the extent of the programming paradigms it supports. Sometime soon, I'll give you at considerable length the benfits of my experience with Mathematica, which is based on transformation rules for tree-structured expressions. It looks very much like XSLT to me. Mathematica demonstrates that you an do a LOT, just by munging trees around. Now my intuition is, when we want to bind "side-effects" to XSLT, the way to do it is not to embed one dinky external- language call in every production rule we recognize, but rather to produce a complete document for whatever we want an external system to perform. And we pass that document to a special parser, which has the total API for the external system bound into it. If we do it that way, then XSLT only needs to transform trees for us. So, how can an XSL template act as a method? It seems that the only thing such a method can do is returning an XML object. Do you mean that this object is the body of the method? Or its return value? The way I've been describing, the XML object is indeed the return value of the transform, I mean method. Actually, I thought about methods and discovered another possibility of associating a method with an element type: via an attribute whose name is that of the method and default value the method's body (or its identifier). However, I am not quite sure that this is a good idea. We probably wouldn't want to do it with a raw instance of <me>. In fact I'd argue most strongly that at a deep level we want it hardwired in that clients' parsers IGNORE any references to executable stuff, except under very specific conditions - e.g. their trusted browser detects an <xpl:method> tag, and stops to verify that the XPL document is from a trustworthy source. However, the place we would actually like to put method bindings is in XPL-enhanced schemas, which are XML documents. The way I'm coming to see it, we would like to provide a schema for each external API we address. Oh! But didn't I say above that the place for our methods was XSLT? Not any more. Let XSLT munge trees. But look, there's a major redundancy in XML technologies. Everything which takes XML documents as input, does some kind of traversal on the tree. Verifying parsers, XPath, XSLT - they all do it. The fact is, they are all just different flavours of Parser. They all recognize productions in XML - that is, elements - as they wander up and down the tree. They just take different actions at different points. So there are various places in the XML accessory equipage, where one might want to tack method hooks on. What we want to do, is identify the best place to tack them, in order to provide the standard OOP interface. (1) Schema or DTD provides a map of the public interface. (2) XPath, working on the schema, provides a general read-only navigation interface, with actual get_ methods of many kinds. (3) XSLT transforms, working on the elements returned by XPath, provide the set_ methods which rearrange the tree, and present the results as output. (4) XSLT transforms also produce output trees (XML documents) which define actions to be taken by external APIs. (5) And special external-system parsers take those documents, and traverse them so as to make the external-system calls which implement the actions. And NOW we have separation of interface from implementation. Well, almost. Above, the schema maps the interface, inasfar as the interface defines what kinds of elements are present. It doesn't tell you want non-get_ methods are available. The XSLTs in (4) and (5) do tell you what those methods are; in fact so far, we're talking about on transform document per method. But those transforms are the ones that actually execute the methods, external side-effects aside. So we probably do want a method-annotated Schema type for XPL, which defines the available method interfaces by name and parameter valence - but leaves the method actions to the XSLTs. Alexander has further questions on the OOP issue, but it seems to me that the picture I'm drawing has a bearing on them all. What do you think, AG? Finally (so far), Garreth Galligan (12/06/00) puts the whole OOP paradigm to the question. <occupation id="occupation1"> <title>mathematician</title> <workplace>An Institute</workplace> <alias>Some Guy</alias> </occupation> <occupation id="occupation2"> <title>programmer</title> <workplace>A Company</workplace> <alias>Some Guy</alias> </occupation> <me> <human> <name>Alexander Gutman</name> <birthdate>1996-07-01</birthdate> </human> <prototype obj="occupation1"> <workplace>BlahBlah Institute</workplace> <alias>Alex Goodman</alias> </prototype> <prototype obj="occupation2"> <alias>Alex Softman</alias> <workplace>Foobar Software</workplace> <prototype> <description>My main job</description> </prototype> </prototype> </me> What we have here is fairly close to the Mathematica style. Aggregates, let's call them objects, are written out arbitrarily. By default, they are available as prototypes. When reused, an object brings in all the data with which it was defined. But any of that data may be overridden. Thus "occupation2" comes with <title>, <workplace> and <alias> values as originally defined; but the latter two get new overriding values. The whole <me> object is available as a new prototype. It's actually quite elegant - but there are things it can't tell me. For instance, what if I now want to produce a second <me> instance, for someone working two shifts as a mathematician. Do the default rules state that the <programmer> element is copied to the new <me>, or absent? This kind of information - elements required, forbidden, unique, many, etc - is easily included in a schema, once one has gone to the trouble of building one. With OOP - classes, schemas, interfaces, whatever - you get control, for an effort upfront. How did Mathematica make out, without it? Not badly, for the most part. What you could do, with a bit of manual work, was take any hand-made expression and substitute variable names - named blanks - for chosen elements; the result was then available as an expression pattern, which would match the original and anything like it except for the values of the blanked-out elements. And then, you made the pattern one side of a rule, which produced a new expression from those values. When it came to Real OOP, there was a tendency to tie oneself in knots. The problem was, if you had a complex structure, you had to write horrible indexing expressions in quantity, to abstract out the stuff you wanted to reuse. I wouldn't rule out this bottom-up prototyping idea. If we can hand-build this stuff, we can hand-convert it to schema form with about the same effort. All the best, cats Jonathan --- End forwarded message --- |