digitalmars.D - Nullable types
- Lionello Lunesu (16/16) Oct 20 2008 Hi,
- samabeau (6/7) Oct 20 2008 C# does. Nullable types have a question mark after them.
- Lionello Lunesu (21/32) Oct 20 2008 In C#, that "?" basically wraps (boxes?) a value type into a reference
- Olli Aalto (10/48) Oct 20 2008 In Objective-C you can call methods on null(nil in Obj-C) objects. The
- Lionello Lunesu (8/14) Oct 20 2008 :-O That sounds disastrous!
- bearophile (5/9) Oct 20 2008 Again, see the Maybe of Haskell:
- Sergey Gromov (4/20) Oct 21 2008 Yeah, I've spent some time hunting that NaN. I wish I had an exception
- Bent Rasmussen (6/38) Oct 20 2008 Not true. It wraps the value type in a struct with a boolean field
- Lionello Lunesu (5/9) Oct 20 2008 Indeed. Thanks for pointing that out.
- Bill Baxter (10/19) Oct 20 2008 Now it makes sense. Yes the C# feature is apparently just a
- Andrei Alexandrescu (6/26) Oct 20 2008 Not a very clever design. If they took a hit of a Boolean field (= a
- Bill Baxter (19/49) Oct 20 2008 Hmm, I was thinking storing a pointer to the value itself would make
- Denis Koroskin (2/56) Oct 21 2008 That's an overkill, operation cost gets too high for absolutely no reaso...
- Bent Rasmussen (4/65) Oct 21 2008 Precisely. The solution they chose was adequate for the need at hand.
- Bill Baxter (13/33) Oct 20 2008 Also C++ has *non*-Nullable types in the form of references.
- Lionello Lunesu (5/41) Oct 20 2008 But C++ references behave very differently from non-null-references. For...
- Bill Baxter (15/63) Oct 20 2008 Yep, that's different. As I understand it C++ disables rebinding just
- Denis Koroskin (6/43) Oct 21 2008 That's not entirely true:
-
Stewart Gordon
(17/20)
Oct 20 2008
"Lionello Lunesu"
wrote in message - bearophile (6/8) Oct 20 2008 Cyclone has a quite refined (and it looks over-engineered) view of nulla...
- Jarrett Billingsley (5/15) Oct 20 2008 I just read up on Delight for the first time last night, and I didn't
- Bent Rasmussen (6/24) Oct 20 2008 Far more interesting that nullability of value types is non-nullability ...
- Lionello Lunesu (4/8) Oct 20 2008 I agree. The constant wondering "what's null, what isn't" is driving me ...
- Bruce Adams (22/40) Oct 25 2008 In C++ I've always used a very simply rule.
Hi, nullable types: using the type-system to check for "nullness" the way it does for constness*. I haven't used either one of those two languages, but since having read about both systems, I can't help keeping a tag in my mind for each variable; "this one can be null", "this one can't be null"... Delight? * Are there any other languages with this concept? * I personally think it would be nice for D too. Your opinions? L. PS. I have the feeling this also can be generalized, like the green-code-red-code system. It's like a compile-time tagging of variables, with some added syntactic sugar (the ?-token). [1] http://delight.sourceforge.net/null.html [2] http://research.microsoft.com/fsharp/manual/import-interop.aspx#Nullness
Oct 20 2008
Lionello Lunesu Wrote:* Are there any other languages with this concept?eg:- int? num = null; http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx
Oct 20 2008
samabeau wrote:Lionello Lunesu Wrote:type. Once you have an object reference (either an instanced class or such a wrapped value type) you still must check for null everywhere you use it. And in some situations you just know it's never null and you would like to use that information. At the moment, the way you can tell that an object is never null is by (1) using an assertion; (2) mentioning it in a comment; (3) using some hungarian-like naming scheme; None of which have any value at compile-time. In fact, if you think those 3 alternatives are good enough, you could drop all the compile-time type checking. And what happens nowadays when none of those 3 is present? You check for null, whether the check makes sense or not. If I'd only get a penny for every if-null check I've encountered... Letting the type system track whether a reference is null or not should result in more readable code. No more wondering "What if x is null? Where's it checked?" and no more "let's check for null, just in case." L.* Are there any other languages with this concept?eg:- int? num = null; http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx
Oct 20 2008
Lionello Lunesu wrote:samabeau wrote:In Objective-C you can call methods on null(nil in Obj-C) objects. The call is silently ignored. So no more crashes or NPEs. The problem with this is that if you call a method on a null object and try to use the return value as an initializer for a local variable, it will be set to 0 for numbers, nil for objects, and so on. This can lead to hard to find bugs. I'm not an expert Objective-C programmer, not even close, so I cannot say if this system is preferable to crashing the whole application. O.Lionello Lunesu Wrote:type. Once you have an object reference (either an instanced class or such a wrapped value type) you still must check for null everywhere you use it. And in some situations you just know it's never null and you would like to use that information. At the moment, the way you can tell that an object is never null is by (1) using an assertion; (2) mentioning it in a comment; (3) using some hungarian-like naming scheme; None of which have any value at compile-time. In fact, if you think those 3 alternatives are good enough, you could drop all the compile-time type checking. And what happens nowadays when none of those 3 is present? You check for null, whether the check makes sense or not. If I'd only get a penny for every if-null check I've encountered... Letting the type system track whether a reference is null or not should result in more readable code. No more wondering "What if x is null? Where's it checked?" and no more "let's check for null, just in case."* Are there any other languages with this concept?eg:- int? num = null; http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx
Oct 20 2008
"Olli Aalto" <oaalto gmail.com> wrote in message news:gdhud3$1o0o$1 digitalmars.com...In Objective-C you can call methods on null(nil in Obj-C) objects. The call is silently ignored. So no more crashes or NPEs. The problem with this is that if you call a method on a null object and try to use the return value as an initializer for a local variable, it will be set to 0 for numbers, nil for objects, and so on. This can lead to hard to find bugs.:-O That sounds disastrous! Although it sounds like D's NaN initializer: if there's even one NaN somewhere in a big calculation, the result of the calculation will likely be NaN as well. And here it helps finding bugs. Now, if only ints and object references had a real NaN equivalent.... :-) L.
Oct 20 2008
Lionello Lunesu:Although it sounds like D's NaN initializer: if there's even one NaN somewhere in a big calculation, the result of the calculation will likely be NaN as well. And here it helps finding bugs. Now, if only ints and object references had a real NaN equivalent.... :-)Again, see the Maybe of Haskell: http://en.wikibooks.org/wiki/Haskell/Hierarchical_libraries/Maybe Bye, bearophile
Oct 20 2008
Tue, 21 Oct 2008 09:25:56 +0800, Lionello Lunesu wrote:"Olli Aalto" <oaalto gmail.com> wrote in message news:gdhud3$1o0o$1 digitalmars.com...Yeah, I've spent some time hunting that NaN. I wish I had an exception instead.In Objective-C you can call methods on null(nil in Obj-C) objects. The call is silently ignored. So no more crashes or NPEs. The problem with this is that if you call a method on a null object and try to use the return value as an initializer for a local variable, it will be set to 0 for numbers, nil for objects, and so on. This can lead to hard to find bugs.:-O That sounds disastrous! Although it sounds like D's NaN initializer: if there's even one NaN somewhere in a big calculation, the result of the calculation will likely be NaN as well. And here it helps finding bugs.
Oct 21 2008
Not true. It wraps the value type in a struct with a boolean field expressing whether it is null or not. http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx - Bent "Lionello Lunesu" <lio lunesu.remove.com> skrev i meddelelsen news:gdhs01$1jnp$1 digitalmars.com...samabeau wrote:Lionello Lunesu Wrote:type. Once you have an object reference (either an instanced class or such a wrapped value type) you still must check for null everywhere you use it. And in some situations you just know it's never null and you would like to use that information. At the moment, the way you can tell that an object is never null is by (1) using an assertion; (2) mentioning it in a comment; (3) using some hungarian-like naming scheme; None of which have any value at compile-time. In fact, if you think those 3 alternatives are good enough, you could drop all the compile-time type checking. And what happens nowadays when none of those 3 is present? You check for null, whether the check makes sense or not. If I'd only get a penny for every if-null check I've encountered... Letting the type system track whether a reference is null or not should result in more readable code. No more wondering "What if x is null? Where's it checked?" and no more "let's check for null, just in case." L.* Are there any other languages with this concept?eg:- int? num = null; http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx
Oct 20 2008
Bent Rasmussen wrote:Not true. It wraps the value type in a struct with a boolean field expressing whether it is null or not. http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspxIndeed. Thanks for pointing that out. nullness checking. L.
Oct 20 2008
On Tue, Oct 21, 2008 at 9:11 AM, Lionello Lunesu <lio lunesu.remove.com> wrote:Bent Rasmussen wrote:convenient way to create a value type with a special "none-of-the-above" value. I guess this feature is driven by need to connect with databases that often have nullable types. with that assessment : http://www.springerlink.com/content/w2mh0571776t3114/ --bbNot true. It wraps the value type in a struct with a boolean field expressing whether it is null or not. http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspxIndeed. Thanks for pointing that out. checking.
Oct 20 2008
Bill Baxter wrote:On Tue, Oct 21, 2008 at 9:11 AM, Lionello Lunesu <lio lunesu.remove.com> wrote:Not a very clever design. If they took a hit of a Boolean field (= a word field when padding is accounted for), they might as well have added a reference to Exception. That way, you not only know the value is null, you may also have info on why. AndreiBent Rasmussen wrote:convenient way to create a value type with a special "none-of-the-above" value. I guess this feature is driven by need to connect with databases that often have nullable types. with that assessment : http://www.springerlink.com/content/w2mh0571776t3114/Not true. It wraps the value type in a struct with a boolean field expressing whether it is null or not. http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspxIndeed. Thanks for pointing that out. checking.
Oct 20 2008
On Tue, Oct 21, 2008 at 9:40 AM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Bill Baxter wrote:Hmm, I was thinking storing a pointer to the value itself would make more sense than a bool. Along these lines: struct Nullable(T) { private T _value; private T* _ptr; // maybe points to _value, maybe null T* ptr { return _ptr; } T value() { return *_ptr; } void value(T v) { _value = v; _ptr = &_value; } void value(T* v) { if (v is null) { _ptr = null; } else { _value = *v; _ptr = &_value; } } } That way you just get a null pointer exception for free when you try to use the nulled value. --bbOn Tue, Oct 21, 2008 at 9:11 AM, Lionello Lunesu <lio lunesu.remove.com> wrote:Not a very clever design. If they took a hit of a Boolean field (= a word field when padding is accounted for), they might as well have added a reference to Exception. That way, you not only know the value is null, you may also have info on why.Bent Rasmussen wrote:convenient way to create a value type with a special "none-of-the-above" value. I guess this feature is driven by need to connect with databases that often have nullable types. with that assessment : http://www.springerlink.com/content/w2mh0571776t3114/Not true. It wraps the value type in a struct with a boolean field expressing whether it is null or not. http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspxIndeed. Thanks for pointing that out. checking.
Oct 20 2008
On Tue, 21 Oct 2008 05:02:48 +0400, Bill Baxter <wbaxter gmail.com> wrote:On Tue, Oct 21, 2008 at 9:40 AM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:That's an overkill, operation cost gets too high for absolutely no reason.Bill Baxter wrote:Hmm, I was thinking storing a pointer to the value itself would make more sense than a bool. Along these lines: struct Nullable(T) { private T _value; private T* _ptr; // maybe points to _value, maybe null T* ptr { return _ptr; } T value() { return *_ptr; } void value(T v) { _value = v; _ptr = &_value; } void value(T* v) { if (v is null) { _ptr = null; } else { _value = *v; _ptr = &_value; } } } That way you just get a null pointer exception for free when you try to use the nulled value. --bbOn Tue, Oct 21, 2008 at 9:11 AM, Lionello Lunesu <lio lunesu.remove.com> wrote:Not a very clever design. If they took a hit of a Boolean field (= a word field when padding is accounted for), they might as well have added a reference to Exception. That way, you not only know the value is null, you may also have info on why.Bent Rasmussen wrote:convenient way to create a value type with a special "none-of-the-above" value. I guess this feature is driven by need to connect with databases that often have nullable types. with that assessment : http://www.springerlink.com/content/w2mh0571776t3114/Not true. It wraps the value type in a struct with a boolean field expressing whether it is null or not. http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspxIndeed. Thanks for pointing that out. nullness checking.
Oct 21 2008
Precisely. The solution they chose was adequate for the need at hand. - Bent "Denis Koroskin" <2korden gmail.com> skrev i meddelelsen news:op.ujds70e7o7cclz proton.creatstudio.intranet...On Tue, 21 Oct 2008 05:02:48 +0400, Bill Baxter <wbaxter gmail.com> wrote:On Tue, Oct 21, 2008 at 9:40 AM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:That's an overkill, operation cost gets too high for absolutely no reason.Bill Baxter wrote:Hmm, I was thinking storing a pointer to the value itself would make more sense than a bool. Along these lines: struct Nullable(T) { private T _value; private T* _ptr; // maybe points to _value, maybe null T* ptr { return _ptr; } T value() { return *_ptr; } void value(T v) { _value = v; _ptr = &_value; } void value(T* v) { if (v is null) { _ptr = null; } else { _value = *v; _ptr = &_value; } } } That way you just get a null pointer exception for free when you try to use the nulled value. --bbOn Tue, Oct 21, 2008 at 9:11 AM, Lionello Lunesu <lio lunesu.remove.com> wrote:Not a very clever design. If they took a hit of a Boolean field (= a word field when padding is accounted for), they might as well have added a reference to Exception. That way, you not only know the value is null, you may also have info on why.Bent Rasmussen wrote:convenient way to create a value type with a special "none-of-the-above" value. I guess this feature is driven by need to connect with databases that often have nullable types. with that assessment : http://www.springerlink.com/content/w2mh0571776t3114/Not true. It wraps the value type in a struct with a boolean field expressing whether it is null or not. http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspxIndeed. Thanks for pointing that out. nullness checking.
Oct 21 2008
On Tue, Oct 21, 2008 at 9:35 AM, Bill Baxter <wbaxter gmail.com> wrote:On Tue, Oct 21, 2008 at 9:11 AM, Lionello Lunesu <lio lunesu.remove.com> wrote:Also C++ has *non*-Nullable types in the form of references. void aFunction(ref Struct xyz) { // &xyz is a pointer that can't be null } ref Struct anotherFunction() { ... } &(anotherFunction()) --> can't be null I think that may be a C++ FAQ for "When do I use references vs pointers?" One answer to that is that if you don't want to allow NULLs, use a reference. If you do, then use a pointer. --bbBent Rasmussen wrote:convenient way to create a value type with a special "none-of-the-above" value. I guess this feature is driven by need to connect with databases that often have nullable types. with that assessment : http://www.springerlink.com/content/w2mh0571776t3114/Not true. It wraps the value type in a struct with a boolean field expressing whether it is null or not. http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspxIndeed. Thanks for pointing that out. checking.
Oct 20 2008
"Bill Baxter" <wbaxter gmail.com> wrote in message news:mailman.176.1224549806.3087.digitalmars-d puremagic.com...On Tue, Oct 21, 2008 at 9:35 AM, Bill Baxter <wbaxter gmail.com> wrote:But C++ references behave very differently from non-null-references. For one, you can't change what is being referenced. L.On Tue, Oct 21, 2008 at 9:11 AM, Lionello Lunesu <lio lunesu.remove.com> wrote:Also C++ has *non*-Nullable types in the form of references. void aFunction(ref Struct xyz) { // &xyz is a pointer that can't be null } ref Struct anotherFunction() { ... } &(anotherFunction()) --> can't be null I think that may be a C++ FAQ for "When do I use references vs pointers?" One answer to that is that if you don't want to allow NULLs, use a reference. If you do, then use a pointer.Bent Rasmussen wrote:convenient way to create a value type with a special "none-of-the-above" value. I guess this feature is driven by need to connect with databases that often have nullable types. with that assessment : http://www.springerlink.com/content/w2mh0571776t3114/Not true. It wraps the value type in a struct with a boolean field expressing whether it is null or not. http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspxIndeed. Thanks for pointing that out. nullness checking.
Oct 20 2008
On Tue, Oct 21, 2008 at 10:33 AM, Lionello Lunesu <lionello lunesu.remove.com> wrote:"Bill Baxter" <wbaxter gmail.com> wrote in message news:mailman.176.1224549806.3087.digitalmars-d puremagic.com...Yep, that's different. As I understand it C++ disables rebinding just because rebinding would require introducing a new "reference assignment" operator to distinguish from plain a=b which operates on the thing referred to not the reference itself. And Bjarne thought that would introduce too much complexity for too little benefit. Most of the time if you need to rebind a reference, you can just create a new local variable for it. My hunch is that covers about 90% of use cases. Anyway, maybe Bartosz will solve all our problems when part 2 of his blog post comes out: http://bartoszmilewski.wordpress.com/2008/10/18/who-ordered-rvalue-references-part-1/ ;-) --bbOn Tue, Oct 21, 2008 at 9:35 AM, Bill Baxter <wbaxter gmail.com> wrote:But C++ references behave very differently from non-null-references. For one, you can't change what is being referenced.On Tue, Oct 21, 2008 at 9:11 AM, Lionello Lunesu <lio lunesu.remove.com> wrote:Also C++ has *non*-Nullable types in the form of references. void aFunction(ref Struct xyz) { // &xyz is a pointer that can't be null } ref Struct anotherFunction() { ... } &(anotherFunction()) --> can't be null I think that may be a C++ FAQ for "When do I use references vs pointers?" One answer to that is that if you don't want to allow NULLs, use a reference. If you do, then use a pointer.Bent Rasmussen wrote:convenient way to create a value type with a special "none-of-the-above" value. I guess this feature is driven by need to connect with databases that often have nullable types. with that assessment : http://www.springerlink.com/content/w2mh0571776t3114/Not true. It wraps the value type in a struct with a boolean field expressing whether it is null or not. http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspxIndeed. Thanks for pointing that out. nullness checking.
Oct 20 2008
On Tue, 21 Oct 2008 04:43:18 +0400, Bill Baxter <wbaxter gmail.com> wrote:On Tue, Oct 21, 2008 at 9:35 AM, Bill Baxter <wbaxter gmail.com> wrote:That's not entirely true: void foo(Bar& bar) { ... } Bar* bar = NULL; foo(*bar); // reference is NULL In practice, however, I never got a NULL-reference passed.On Tue, Oct 21, 2008 at 9:11 AM, Lionello Lunesu <lio lunesu.remove.com> wrote:Also C++ has *non*-Nullable types in the form of references. void aFunction(ref Struct xyz) { // &xyz is a pointer that can't be null } ref Struct anotherFunction() { ... } &(anotherFunction()) --> can't be null I think that may be a C++ FAQ for "When do I use references vs pointers?" One answer to that is that if you don't want to allow NULLs, use a reference. If you do, then use a pointer. --bbBent Rasmussen wrote:convenient way to create a value type with a special "none-of-the-above" value. I guess this feature is driven by need to connect with databases that often have nullable types. with that assessment : http://www.springerlink.com/content/w2mh0571776t3114/Not true. It wraps the value type in a struct with a boolean field expressing whether it is null or not. http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspxIndeed. Thanks for pointing that out. nullness checking.
Oct 21 2008
"Lionello Lunesu" <lionello lunesu.remove.com> wrote in message news:gdhd0f$g3v$1 digitalmars.com... <snip>[1] http://delight.sourceforge.net/null.htmlIt seems that Delight had the same idea as Nice. Which was first? classes are always nullable. Is there any language where you can have multiple levels of nullness? Something like Type?? which could represent, along with a Type object or lack thereof, a lack of any (Type object or lack thereof). If that makes sense. (It could be done with pointers in C/C++/D, but that adds levels of indirection and requires the programmer to allocate little bits of memory to deal with them.)[2] http://research.microsoft.com/fsharp/manual/import-interop.aspx#NullnessThis might take a bit of studying to make sense of.... Stewart. -- My e-mail address is valid but not my primary mailbox. Please keep replies on the 'group where everybody may benefit.
Oct 20 2008
Stewart Gordon:It seems that Delight had the same idea as Nice. Which was first?Nice was first, of course.Is there any language where you can have multiple levels of nullness?Cyclone has a quite refined (and it looks over-engineered) view of nullable pointers and the like. Boxes similar to nullable types are used often in Haskell, see the Maybe monad, etc. Bye, bearophile
Oct 20 2008
On Mon, Oct 20, 2008 at 3:34 AM, Lionello Lunesu <lionello lunesu.remove.com> wrote:Hi, nullable types: using the type-system to check for "nullness" the way it does for constness*. I haven't used either one of those two languages, but since having read about both systems, I can't help keeping a tag in my mind for each variable; "this one can be null", "this one can't be null"... Delight? * Are there any other languages with this concept? * I personally think it would be nice for D too. Your opinions?I just read up on Delight for the first time last night, and I didn't know it was more than just a syntactic wrapper around D. The maybe types sound like something I'd really like to try out.
Oct 20 2008
Far more interesting that nullability of value types is non-nullability of - Bent "Lionello Lunesu" <lionello lunesu.remove.com> skrev i meddelelsen news:gdhd0f$g3v$1 digitalmars.com...Hi, handle nullable types: using the type-system to check for "nullness" the way it does for constness*. I haven't used either one of those two languages, but since having read about both systems, I can't help keeping a tag in my mind for each variable; "this one can be null", "this one can't be null"... Delight? * Are there any other languages with this concept? * I personally think it would be nice for D too. Your opinions? L. PS. I have the feeling this also can be generalized, like the green-code-red-code system. It's like a compile-time tagging of variables, with some added syntactic sugar (the ?-token). [1] http://delight.sourceforge.net/null.html [2] http://research.microsoft.com/fsharp/manual/import-interop.aspx#Nullness
Oct 20 2008
"Bent Rasmussen" <IncredibleShrinkingSphere Gmail.com> wrote in message news:gdisrd$15a6$1 digitalmars.com...Far more interesting that nullability of value types is non-nullability of reference types. The potential extinction of null-pointer exceptions. follow.I agree. The constant wondering "what's null, what isn't" is driving me mad. L.
Oct 20 2008
On Mon, 20 Oct 2008 08:34:30 +0100, Lionello Lunesu <lionello lunesu.remove.com> wrote:Hi, handle nullable types: using the type-system to check for "nullness" the way it does for constness*. I haven't used either one of those two languages, but since having read about both systems, I can't help keeping a tag in my mind for each variable; "this one can be null", "this one can't be null"... or Delight? * Are there any other languages with this concept? * I personally think it would be nice for D too. Your opinions? L. PS. I have the feeling this also can be generalized, like the green-code-red-code system. It's like a compile-time tagging of variables, with some added syntactic sugar (the ?-token). [1] http://delight.sourceforge.net/null.html [2] http://research.microsoft.com/fsharp/manual/import-interop.aspx#NullnessIn C++ I've always used a very simply rule. If it can possibly be null use a pointer. If it should never be null use a reference. In languages like Java where there is no such distinction life is difficult. Of course you can still (I find its quite rare) have null references. This indicates a programming error and is usually caused by the ground shifting under your feet. For example append to a std::vector and it may need to be re-allocated in order to accomodate it, which will invalidate any previous references. This is another place where invariant would come in handy. A reference to an invariant can never be invalidated. I'm not sure how this pattern can be applied in D, as it seem to follow the Java mould mixing the semantics of pointers and references. (disclaimer: I haven't been doing much D programming lately) Regards, Bruce.
Oct 25 2008