On 5/10/05, Jim Hugunin <[EMAIL PROTECTED]> wrote: > >>> apt[0] = pt > What do we do here? We need to copy the data in pt into apt[0]. This > is what it means to have an array of structs. No matter what we do with > proxies or wrappers there's no way out of this copy. We could add some > kind of pointer to the ValueProxy<Point> keeping track of the fact that > there's a copy of this variable now held in apt[0]. This would need to > be an arbitrarily large list of pointers. This list would also be easy > to break with CLI code that directly modified apt or other containers > holding on to the value types.
I thought I understood this, but now I'm second guessing myself. Why can't >>> apt[0] = pt indicate a copy by value if apt is a CLI array? Python lists would still get a reference to ValueProxy. >>> pt = apt[0] Here ValueProxy would be a reference to apt[0], so pt.x += 10 is still fine. What am I missing? > > >>> pt.X = 0 > The only way this can modify apt[0] is if we keep the full list of > references in ValueProxy. See above for why keeping that full list > still wouldn't always work. > > >>> apt[0].X = 0 > This example would work using the ValueProxy that pointed to apt[0]; > however, when apt[0] is assigned to a variable the situation becomes as > bad as it is for pt. > > >>> for pt in apt: > >>> pt.X = 0 > The for loop uses an Enumerator to loop through the points in apt. > Without constructing a custom enumerator for arrays there's no way to > get anything but copy semantics here. While we could build a custom > enumerator for arrays this wouldn't solve the general case of value > types being returned from methods. > > When I played with this example in C#, I discovered something > interesting: > > Point[] pa = new Point[3]; > foreach (Point p in pa) { > pt.X = 10; > } > > The code above generates an error from the C# compiler: > "Cannot modify members of 'p' because it is a 'foreach iteration > variable'" > > The C# compiler is treating these iteration variables as semi-immutable > in order to minimize the confusion that can come from the copy semantics > of value types. This seems like a promising idea... > > > > (2) Make value types immutable (or at least the ones you grab from > > > collections) > > All of the problems with value types stem from their mutability. Nobody > ever complains that int, double, char, etc. are value types because > those are all immutable. For immutable objects there's no difference > between pass by reference and pass by value. > > The CLR team's API Design Guidelines say this: > - Do not create mutable value types. > http://blogs.msdn.com/kcwalina/archive/2004/09/28/235232.aspx > (or see here - http://peter.golde.org/2003/10/13.html#a16) > > In some ways, this would be just reflecting in IronPython this good > design sense. > > One advantage of immutability is that it would make failures like the > following much more obvious: > > >>> apt[0].X = 0 > If value types were immutable this would throw. The exception message > might give people enough information to get started tracking down the > issue and modifying their code to work correctly. > > What are the problems with this approach? > > 1. C#/VB examples won't port very naturally to IronPython and the docs > will need a section explaining the various workarounds to the fact that > IronPython doesn't support this idiom. This isn't ideal, but I could > easily live with this doc burden. > > 2. There's no way that I know of to make a value type 100% immutable > without controlling its implementation. IronPython could block setting > of fields and properties on value types, but there's no way to reliably > detect and block all sets that came through methods. Just getting the > properties and fields would probably cover 95% of the cases where people > try to mutate a value type, but it seems pretty awkward to me to say > that value types in IronPython are sort-of immutable unless there are > mutating methods. The fact that this is what the C# compiler does for > iteration variables is encouraging at least in that it's a precedent. > > 3. There might be things that are impossible to express with this > restriction. I don't think that's true, particularly with the use of > named parameters to initialize fields and properties in the value type's > constructor. However, one of the principles of IronPython is that it > should be able to use any CLS library and it's possible there's some > weird library design with value types that wouldn't work if they were > considered virtually immutable by IronPython. > > If we went down the immutable value type route, it would be interesting > to look at different kinds of sugar that could be provided to make the > impact on most programs less than it currently is. > > -Jim > _______________________________________________ > users-ironpython.com mailing list > users-ironpython.com@lists.ironpython.com > http://lists.ironpython.com/listinfo.cgi/users-ironpython.com > _______________________________________________ users-ironpython.com mailing list users-ironpython.com@lists.ironpython.com http://lists.ironpython.com/listinfo.cgi/users-ironpython.com