[Mono-dev] Lang Theory Question

Jonathan Pryor jonpryor at vt.edu
Fri Feb 1 22:10:06 EST 2008


On Fri, 2008-02-01 at 20:56 -0500, Scott Peterson wrote:
> I'm a sucker for syntactic sugar. There is one little trick which I've
> been trying and failing to do - it turns about to be impossible

It's not as impossible as you think, depending on the tradeoffs you're
willing to make.

> One nice thing about nullable types is the non-standard behavior of
> the assignment (=) operator. For example:
> 
> int? val = 5;
> val = 6;
> 
> is shorthand for:
> 
> Nullable<int> val = new Nullable<int> (5);
> val.Value = 6;
> 
> I am working with a struc similar to Nullable and I'd like to be able
> to use the assignment operator in a similar way.

And you can, you just can't think of it in terms of overloading
assignment.  Instead, think of in terms of overloading the object
coercion operators...because that's what you can do:

        struct MyNullable<T> where T : struct {
          public bool HasValue { get; private set; }
          public T Value { get; private set; }
        
          public MyNullable (T t)
          {
            Value = t;
            HasValue = true;
          }
        
          public static implicit operator MyNullable<T> (T value)
          {
            return new MyNullable<T> (value);
          }
        
          public static implicit operator MyNullable<T> (T? value)
          {
            if (value == null)
              return new MyNullable<T> ();
            return new MyNullable<T> ((T) value);
          }
        }

This _almost_ allows your desired usage:

        MyNullable<int> a = 5;           // works
        MyNullalbe<int> b = null;        // error
        
        MyNullable<int> c = (int?) null; // works

Of course, this always works too:

        MyNullable<int> d = new MyNullable<int> ();

Or we could do `MyNullable<int> e = MyNullable<int>.Null;` if we modify
MyNullable<T> to add:

        public static readonly MyNullable<T> Null = new MyNullable<T>
        ();

I'm partial to the `(int?) null` version, as it's shorter.

And then, for complete insanity...use a Monad; from:

http://blogs.msdn.com/wesdyer/archive/2008/01/11/the-marvels-of-monads.aspx

Relevant excerpt:

        class Maybe<T>
        {
            public readonly static Maybe<T> Nothing = new Maybe<T>();
            public T Value { get; private set; }
            public bool HasValue { get; private set; }
            Maybe()
            {
                HasValue = false;
            }
            public Maybe(T value)
            {
                Value = value;
                HasValue = true;
            }
        }
        
        public static Maybe<T> ToMaybe<T>(this T value)
        {
            return new Maybe<T>(value);
        }
        
        public static Maybe<U> SelectMany<T, U>(this Maybe<T> m, Func<T, Maybe<U>> k)
        {
            if (!m.HasValue)
                return Maybe<U>.Nothing;
            return k(m.Value);
        }
        
        var r = from x in 5.ToMaybe()
        from y in Maybe<int>.Nothing
        select x + y;

        Console.WriteLine(r.HasValue ? r.Value.ToString() : "Nothing");
        
Quoth the article:

        The result is "Nothing".  We have implemented the null
        propagation of nullables without explicit language support.

Tell me that isn't cool. :-)

 - Jon





More information about the Mono-devel-list mailing list