[xquery-talk] Type system extensions: best syntax for foreign generic types

Pavel Minaev int19h at gmail.com
Mon Sep 8 19:11:14 PDT 2008


I'm working on a conforming XQuery implementation for the .NET
platform. Naturally, to be useful, it would require first-class
interop with .NET libraries, both stock and third-party. I've seen the
way Saxon does it, but I'd rather have the entire .NET type system
available for use in XQuery - so that you could not just call a .NET
method, but declare an XQuery function that takes a reference to a
.NET object, and so on. It seems that XQuery spec gives specific
permission to do this sort of thing:

"An XQuery implementation may augment the type system of [XQuery/XPath
Data Model (XDM)] with additional types that are designed to
facilitate exchange of data with host programming languages, or it may
provide mechanisms for the user to define such types. For example, a
type might be provided that encapsulates an object returned by an
external function, such as an SQL database connection. These
additional types, if defined, are considered to be derived by
restriction from xs:anyAtomicType."

So far, so good. Initially, I wanted to map .NET namespaces directly
to XML namespaces (using the same "clr-namespace" URI schema that
Microsoft uses for XAML for the same purpose), .NET types directly to
xs:anyAtomicType-derived final XML Schema types, and methods to
functions by prefixing their names with class name and dot. An example
of such mapping would be:

 declare namespace sys = "clr-namespace:System;assembly=mscorlib";
 declare function local:foo(s as sys:String) {

This seems to work fine and look nice, but problems begin when generic
types are brought into the picture. XQuery has its own set of what are
effectively parametrized types (e.g., element(...)), but it is a
closed, non-extensible set. I considered a language extension,
something along these lines:

 (: The corresponding .NET type is System.Func<System.String, System.Int32> :)
 declare function local:foo(fun as generic-instance(sys:Func,
sys:String, sys:Int32)) { ... };

The problem is that there is nothing in XQuery spec to guarantee that
this won't clash with any future language developments. Nor does it
seem to be possible to namespace-qualify "generic-instance" here in an
extensible way (who's to say that a future XQuery version won't allow
something like xs:integer(1, 100) as a type?). And I would really like
to stay within the boundaries permitted, either explicitly or
implicitly, by the standard.

It seems that a more "proper" way to handle this is via "declare
option". Perhaps something along the lines of:

 (: Instantiate and bind to name :)
 declare option my:generic-instance "local:FuncOfStringToInt32 =
sys:Func(sys:String, sys:Int32)";
 (: Use the bound name :)
 declare function local:foo(fun as local:FuncOfStringToInt32) { ... };

However, this seems to be a particularly verbose and ugly way of doing it.

I'm also considering just dropping the idea of mapping namespaces
altogether, and requiring fully qualified names for everything, all
mapped to a single namespace such as "clr". Some name mangling could
be devised for generics, as well. For example:

 declare namespace clr = "urn:uuid:...";
 declare function local:foo(fun as
clr:System.Action-of-System.String-and-System.Int32) as
clr:System.Object { ... }

Also verbose, but still (IMO) easier to understand than the mapping.

Which approach would you recommend? Is one of the methods outlined
above preferrable, or perhaps there is some other more intuitive
schema? Or, perhaps some extensibility hooks in XQuery spec that I've
missed that allow me to do what I want?

More information about the talk mailing list