[IronPython] Naming and resolution of generic types (complete!)

Brian Lloyd brian.d.lloyd at gmail.com
Sat Apr 1 18:06:06 CEST 2006

Well, I'd argue that its not about trying to be all things to all
programmers - its about finding the most reasonable way to handle one
of the (relatively few) ways that the meta-models of the CLR and
Python don't match up well.

In a way, this is not unlike the situation with methods. The fact that
Python doesn't have a concept of overloaded methods causes potential
ambiguity on the Python side, but luckily there is a relatively
elegant solution in that most of the time the runtime can do the Right
Thing on its own, and you can hint it with the [] syntax if you need

I'd like to find a similarly nice solution to this problem, but there
are more constraints here in that types are routinely named in import
statements. That makes a solution much harder in that you only have a
Python name to work with and not many sneaky tricks at your disposal

The more I think about it, I think the best solution might have to be
that given the following statement:

from System.Bunnies import Bunny

then the name 'Bunny' will be bound to something that is one of:

  - a (reflected) non-generic type (if there exists a non-generic type
of that name and no
    generic type definitions with the same base name). This type can
be instantiated with
    the standard () syntax.

  - a (reflected) generic type definition (if there exists a generic
type definition with the
    given base name, and no non-generic type with that name). This generic type
    definition can be bound into a closed generic type using the []
syntax. Trying to
    instantiate a generic type def using () raises a TypeError.

  - an object that represents more than one reflected type (if there
exists both a
    generic and a non-generic type with the same base name, or more than one
    generic type with the same base name). Calling this object with ()
would create
    an instance if there exists a non-generic type, else raise a
TypeError. Using the
    [] syntax would produce a closed type. There could be some sort of
syntax you
    could use to obtain a reference to a specific (but unbound and
    encapsulated type.

This seems like it retains the most simplicity for common uses, and
moves most of the
ambiguity into less common cases (mostly having to do with a
'reflection context', from
either the CLR or Python perspective). For example, what do you see if
you do dir() on
this pseudo-type? What would you pass to a System.Reflection method
that expected
a Type? Those still need to be answered, but I'd argue that for the
most part normal
users of the type from Python won't have to worry about it if we do the above.



On 3/31/06, Thane Plummer <thane at magna-capital.com> wrote:
> My vote is to keep Python pure, i.e. import SomeGeneric_TT or foo =
> TwoParamGeneric<<2 are simply un-Pythonic.
> It is amusing that the .NET framework has incorporated a feature
> --Generics-- that make it more useful, and indeed more like Python, and the
> Python community is now trying to emulate a solution that has already been
> solved in Python!  OK, I'm generalizing and I recognize that there are
> exceptions; but by and large, Generics give .NET programmers the flexibility
> that Python users have always had.
> The vast majority of programming objectives can be met using plain old
> Python.  Really.
> A problem arises when there is a .NET system call or 3rd party library that
> expects Generics in its interface.  In those cases, why not just coerce the
> native Python type and throw an exception if the programmer did something
> stupid?
> >>> import generic_interface_lib
> >>> int_list = [1, 2, 3, "Hey! A string!", 5, 6]
> >>> result = generic_interface_lib.Plot(int_list)
> Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
> Do_Not_Be_A_Bozo Exception: function requires a list of numbers.
> Yes, I do know the answer to the previous question, but this seems to be a
> more Pythonic solution.  Brian's question makes me wonder if Python can be
> all things to all programmers, and my thinking is: no, it can't.  Trying to
> make it so will just pollute the language.
> --Thane
> -----Original Message-----
> From: pythondotnet-bounces at python.org
> [mailto:pythondotnet-bounces at python.org] On Behalf Of Brian Lloyd
> Sent: Friday, March 31, 2006 3:43 PM
> To: pythondotnet at python.org
> Cc: users at lists.ironpython.com
> Subject: [Python.NET] Naming and resolution of generic types (complete!)
> Hi all - I'm cross-posting this to the IP list as the subject seems to
> be an open issue there too.
> I'm working on generics support for Python for .NET, and there a couple
> of thorny issues that could use some discussion regarding naming and
> resolution of generic types.
> In C# you can explicitly name a generic type, a la Dictionary<,>. That
> syntax won't work in Python, of course. Looking at IP, it seems to allow
> the apparent Python name to be the unmangled IL name so you can
> naturally use the name.
> The problem is that the mangled name is illegal as a python name, and
> the unmangled name isn't guaranteed to be unique - you can potentially
> have any number of generic types as well as a non-generic type with the
> same base name in the same namespace:
> namespace Spam {
>     public class SpamCan {}
>     public class SpamCan<T> {}
>     public class SpamCan<T, V> {}
>     ...
> }
> I imagine that maybe IP has enough information available at compile-time
> to do the right thing for some common usage (binding and instantiating
> the types), but the overloaded name can still be ambiguous. A real-life
> example of this is System.IComparable - in IP, it doesn't seem possible
> to get to the non-generic version of IComparable anymore (or at least it
> was not obvious to me how to do it):
> >>> import System
> >>> System.IComparable
> <type 'IComparable`1'>
> It seems like we need to figure out some acceptable way of spelling
> generic type names explicitly in Python (an equivalent to IComparable<>
> in C#) that works within the existing syntax.
> There don't appear to be a lot of great options :( It has to be a valid
> Python name to work in an import statement, so that rules out strange
> operator shenanigans akin to the [] hack used for generic type binding.
> One would be to mimic the existing IL mangling in some way, a la:
> >From System import IComparable   # the non-generic type
> >From System import IComparable_1 # the 1-param generic
> # or
> from System import IComparable_T
> from System.Collections.Generic import Dictionary_TT
> These are all pretty gross, and still don't totally prevent hiding of
> legit non-generic classes with those names (though it makes it less
> likely that names will be hidden than the current approach).
> I suppose another approach would be to continue to have only one type
> end up with the simple name, but provide a way to disambiguate it after
> the fact:
> >>> import System
> >>> System.IComparable
> <type 'IComparable`1'>
> >>> # abandon all hope, ye who enter here...
> >>> NonGenericIComparable = System.IComparable<<0
> >>> OneParamGenericIComparable = System.IComparable<<1
> >>> TwoParamVersionIfThereWasOne = System.IComparable<<2
> That feels to me like it violates Python Zen in several ways, though.
> Thoughts?
> -Brian
> _________________________________________________
> Python.NET mailing list - PythonDotNet at python.org
> http://mail.python.org/mailman/listinfo/pythondotnet
> _________________________________________________
> Python.NET mailing list - PythonDotNet at python.org
> http://mail.python.org/mailman/listinfo/pythondotnet

More information about the Ironpython-users mailing list