digitalmars.D - NULL indicator in Variant
- Steve Teale (8/8) Oct 27 2011 How big a deal would it be to add a NULL indicator to the VariantN struc...
- Dmitry Olshansky (4/12) Oct 27 2011 Surely Variant.init should do the trick?
- Steve Teale (3/5) Oct 27 2011 Dmitry,
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (4/9) Oct 27 2011 He is probably referring to the 'init' property on the *type*, i.e.
- Robert Jacques (2/14) Oct 27 2011 Init is a built-in property of all types and for Variant (both new and o...
- Steve Teale (4/19) Oct 27 2011 Same catch 22. In order to have an init property, the Variant would have...
- Steven Schveighoffer (13/32) Oct 27 2011 ve
- Steve Teale (13/51) Oct 27 2011 Exactly, and v has reverted to being typeless:
- Steven Schveighoffer (11/51) Oct 27 2011 say
- Steve Teale (7/59) Oct 27 2011 Well, yes, that was my first reaction, but I thought I'd ask - if there
- Robert Jacques (10/23) Oct 27 2011 Speaking as the one making over variant, let me see if I understand your...
- Steve Teale (25/68) Oct 28 2011 I want to be able to mark a Variant which is otherwise functional and
- Robert Jacques (28/75) Oct 28 2011 Okay, I think there was a bit of mis-communication here. What I'm asking...
- Steve Teale (16/133) Oct 29 2011 Robert,
- Robert Jacques (37/52) Oct 29 2011 Steve, when you state: "For the database case it would essentially serve...
- Steve Teale (18/76) Oct 29 2011 Robert,
- Regan Heath (32/41) Oct 28 2011 Could you wrap std.typecons.Nullable around it? It's currently disabled...
- Regan Heath (14/38) Oct 28 2011 err.. sorry, I meant:
- Steven Schveighoffer (24/82) Oct 28 2011 :
- Jonathan M Davis (4/6) Oct 28 2011 Agreed. Unless such a change has a real use case beyond databases, I do ...
- simendsjo (3/13) Oct 29 2011 This is basically what ADO.Net does:
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (5/13) Oct 27 2011 I'm not sure having three possible states in Variant is a good idea, but...
- Steve Teale (4/11) Oct 27 2011 Don't believe so. If you haven't set any value, hasValue() will return
- =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= (6/17) Oct 27 2011 You're completely right; brain failed me for a moment there.
- Robert Jacques (5/13) Oct 27 2011 Any reason making a custom NULL type wouldn't work? i.e:
- Steve Teale (5/12) Oct 27 2011 I don't think that is any improvement on hasValue(). It would tell you
- Kagamin (3/15) Oct 27 2011 SQL uses `NULL` for all types.
- Steve Teale (6/8) Oct 28 2011 Yes, but if you set a particular column value to NULL, it does not wipe
- kennytm (2/13) Oct 27 2011 Just store a std.typecons.Nullable!T in the Variant.
- Steve Teale (5/6) Oct 27 2011 Mmm - works to some extent, but by the time you'd wrapped it to make the...
How big a deal would it be to add a NULL indicator to the VariantN struct. I use the term NULL as opposed to null deliberately. Variant already provides the hasValue() method, which can serve as a null indicator. But in using it as a parameter in database modules, it would be useful to be able to give a Variant instance a type, as in v = "", but also to set it explicitly as NULL with setNull() or whatever. Could this fly without breaking existing code? Steve
Oct 27 2011
On 27.10.2011 17:12, Steve Teale wrote:How big a deal would it be to add a NULL indicator to the VariantN struct. I use the term NULL as opposed to null deliberately. Variant already provides the hasValue() method, which can serve as a null indicator. But in using it as a parameter in database modules, it would be useful to be able to give a Variant instance a type, as in v = "", but also to set it explicitly as NULL with setNull() or whatever. Could this fly without breaking existing code? SteveSurely Variant.init should do the trick? -- Dmitry Olshansky
Oct 27 2011
Surely Variant.init should do the trick?Dmitry, Are you talking about the new std.variant - I don't see 'init' currently. Steve
Oct 27 2011
On 27-10-2011 15:50, Steve Teale wrote:He is probably referring to the 'init' property on the *type*, i.e. int.init and so on. - AlexSurely Variant.init should do the trick?Dmitry, Are you talking about the new std.variant - I don't see 'init' currently. Steve
Oct 27 2011
On Thu, 27 Oct 2011 10:16:26 -0400, Alex Rønne Petersen <xtzgzorex gmail.com> wrote:On 27-10-2011 15:50, Steve Teale wrote:Init is a built-in property of all types and for Variant (both new and old) setting a variant to its init will cause it to have no value.He is probably referring to the 'init' property on the *type*, i.e. int.init and so on. - AlexSurely Variant.init should do the trick?Dmitry, Are you talking about the new std.variant - I don't see 'init' currently. Steve
Oct 27 2011
On Thu, 27 Oct 2011 16:16:26 +0200, Alex Rønne Petersen wrote:On 27-10-2011 15:50, Steve Teale wrote:Same catch 22. In order to have an init property, the Variant would have to have been set to some type, at which point hasValue() would say yes. SteveHe is probably referring to the 'init' property on the *type*, i.e. int.init and so on. - AlexSurely Variant.init should do the trick?Dmitry, Are you talking about the new std.variant - I don't see 'init' currently. Steve
Oct 27 2011
On Thu, 27 Oct 2011 12:58:57 -0400, Steve Teale = <steve.teale britseyeview.com> wrote:On Thu, 27 Oct 2011 16:16:26 +0200, Alex R=C3=B8nne Petersen wrote:veOn 27-10-2011 15:50, Steve Teale wrote:Same catch 22. In order to have an init property, the Variant would ha=He is probably referring to the 'init' property on the *type*, i.e. int.init and so on. - AlexSurely Variant.init should do the trick?Dmitry, Are you talking about the new std.variant - I don't see 'init' currently. Steveto have been set to some type, at which point hasValue() would say yes=.Steveimport std.variant; void main() { Variant v =3D 1; assert(v.hasValue()); v =3D v.init; assert(!v.hasValue()); } -Steve
Oct 27 2011
On Thu, 27 Oct 2011 13:09:43 -0400, Steven Schveighoffer wrote:On Thu, 27 Oct 2011 12:58:57 -0400, Steve Teale <steve.teale britseyeview.com> wrote:Exactly, and v has reverted to being typeless: import std.variant; import std.stdio; void main() { Variant v = 1; assert(v.hasValue()); v = v.init; assert(!v.hasValue()); writeln(v.type.toString()); } SteveOn Thu, 27 Oct 2011 16:16:26 +0200, Alex Rønne Petersen wrote:import std.variant; void main() { Variant v = 1; assert(v.hasValue()); v = v.init; assert(!v.hasValue()); } -SteveOn 27-10-2011 15:50, Steve Teale wrote:Same catch 22. In order to have an init property, the Variant would have to have been set to some type, at which point hasValue() would say yes. SteveHe is probably referring to the 'init' property on the *type*, i.e. int.init and so on. - AlexSurely Variant.init should do the trick?Dmitry, Are you talking about the new std.variant - I don't see 'init' currently. Steve
Oct 27 2011
On Thu, 27 Oct 2011 13:53:02 -0400, Steve Teale = <steve.teale britseyeview.com> wrote:On Thu, 27 Oct 2011 13:09:43 -0400, Steven Schveighoffer wrote:On Thu, 27 Oct 2011 12:58:57 -0400, Steve Teale <steve.teale britseyeview.com> wrote:On Thu, 27 Oct 2011 16:16:26 +0200, Alex R=C3=B8nne Petersen wrote:On 27-10-2011 15:50, Steve Teale wrote:He is probably referring to the 'init' property on the *type*, i.e.=Surely Variant.init should do the trick?Dmitry, Are you talking about the new std.variant - I don't see 'init' currently. Stevesayint.init and so on. - AlexSame catch 22. In order to have an init property, the Variant would have to have been set to some type, at which point hasValue() would =Sorry to jump in mid-stream, but you seemed to be suggesting Variant = didn't have an init without an assigned type. Why wouldn't you just wrap variant if you want to introduce a nullable = variant type? Why does Variant have to be muddied with requirements for= = database API? Database null is an entirely different animal from D's nu= ll. -SteveExactly, and v has reverted to being typeless:yes. Steveimport std.variant; void main() { Variant v =3D 1; assert(v.hasValue()); v =3D v.init; assert(!v.hasValue()); } -Steve
Oct 27 2011
On Thu, 27 Oct 2011 13:58:54 -0400, Steven Schveighoffer wrote:On Thu, 27 Oct 2011 13:53:02 -0400, Steve Teale <steve.teale britseyeview.com> wrote:No, I was just saying it didn't help.On Thu, 27 Oct 2011 13:09:43 -0400, Steven Schveighoffer wrote:Sorry to jump in mid-stream, but you seemed to be suggesting Variant didn't have an init without an assigned type.On Thu, 27 Oct 2011 12:58:57 -0400, Steve Teale <steve.teale britseyeview.com> wrote:Exactly, and v has reverted to being typeless:On Thu, 27 Oct 2011 16:16:26 +0200, Alex Rønne Petersen wrote:import std.variant; void main() { Variant v = 1; assert(v.hasValue()); v = v.init; assert(!v.hasValue()); } -SteveOn 27-10-2011 15:50, Steve Teale wrote:Same catch 22. In order to have an init property, the Variant would have to have been set to some type, at which point hasValue() would say yes. SteveHe is probably referring to the 'init' property on the *type*, i.e. int.init and so on. - AlexSurely Variant.init should do the trick?Dmitry, Are you talking about the new std.variant - I don't see 'init' currently. SteveWhy wouldn't you just wrap variant if you want to introduce a nullable variant type? Why does Variant have to be muddied with requirements for database API? Database null is an entirely different animal from D's null.Well, yes, that was my first reaction, but I thought I'd ask - if there was a spare bit somewhere in Variant, would it do much harm, and Variant is getting a makeover. Maybe there are circumstances other than database interactions where it could be useful. Steve
Oct 27 2011
On Thu, 27 Oct 2011 14:06:47 -0400, Steve Teale <steve.teale britseyeview.com> wrote:On Thu, 27 Oct 2011 13:58:54 -0400, Steven Schveighoffer wrote:[snip]On Thu, 27 Oct 2011 13:53:02 -0400, Steve Teale <steve.teale britseyeview.com> wrote:On Thu, 27 Oct 2011 13:09:43 -0400, Steven Schveighoffer wrote:On Thu, 27 Oct 2011 12:58:57 -0400, Steve Teale <steve.teale britseyeview.com> wrote:On Thu, 27 Oct 2011 16:16:26 +0200, Alex Rønne Petersen wrote:On 27-10-2011 15:50, Steve Teale wrote:Well, yes, that was my first reaction, but I thought I'd ask - if there was a spare bit somewhere in Variant, would it do much harm, and Variant is getting a makeover. Maybe there are circumstances other than database interactions where it could be useful. SteveSpeaking as the one making over variant, let me see if I understand your use case. Similar to typecons.Nullable, you want to be able to test any type for isNull and be to 'nullify' any type. Correct? Does nullifying a value wipe it clean? i.e. can you ever un-nullify something? If you assign to a nulled variant, should there be some sort of special behavior? Should 'hasValue' return false or true? If true, what should 'get' & company return? 'type' should return the TypeInfo of the type that was nullified, correct? What should 'toString' return? One thing that concerns me is the API. The new Variant supports reflection via opDispatch, so adding 'isNull' and 'nullify' members would, for example, block Nullable!int's 'isNull' and 'nullify' members. Would '__isNull' '__nullify' be acceptable? Alternatively, I could special case opAssign and opEquals: 'var = Variant.NULL' and 'var == Variant.NULL'. Thoughts? Sorry for all the questions, but I want to make sure what I build is what you need. That said, I'm petty sure I can incorporate what you want.
Oct 27 2011
On Fri, 28 Oct 2011 00:35:45 -0400, Robert Jacques wrote:On Thu, 27 Oct 2011 14:06:47 -0400, Steve Teale <steve.teale britseyeview.com> wrote:I want to be able to mark a Variant which is otherwise functional and representing a type. It might have the .init value for the type, or it could have any other value. The mark in my context would signify that it should be treated as a NULL for database purposes. But it could be used to add any other subtlety to a variant. It's just a mark I think.On Thu, 27 Oct 2011 13:58:54 -0400, Steven Schveighoffer wrote:[snip]On Thu, 27 Oct 2011 13:53:02 -0400, Steve Teale <steve.teale britseyeview.com> wrote:On Thu, 27 Oct 2011 13:09:43 -0400, Steven Schveighoffer wrote:On Thu, 27 Oct 2011 12:58:57 -0400, Steve Teale <steve.teale britseyeview.com> wrote:On Thu, 27 Oct 2011 16:16:26 +0200, Alex Rønne Petersen wrote:On 27-10-2011 15:50, Steve Teale wrote:Well, yes, that was my first reaction, but I thought I'd ask - if there was a spare bit somewhere in Variant, would it do much harm, and Variant is getting a makeover. Maybe there are circumstances other than database interactions where it could be useful. SteveSpeaking as the one making over variant, let me see if I understand your use case. Similar to typecons.Nullable, you want to be able to test any type for isNull and be to 'nullify' any type. Correct?Does nullifying a value wipe it clean? i.e. can you ever un-nullify something?No, it's just a mark, you can wipe it off and it then reverts to being a perfectly normal variantIf you assign to a nulled variant, should there be some sort of special behavior?I think maybe it should wipe the mark. If I've chosen a particular variant in a particular state to mark, then I'd say the mark would lose its significance if the thing was radically changed.Should 'hasValue' return false or true? If true, what should 'get' & company return?I think hasValue() et al should behave as usual - after all, it's just a mark. It's what I choose to do with the value from get or whatever that should be influenced.'type' should return the TypeInfo of the type that was nullified, correctAbsolutely - that's the primary requirement for me. That the variant should carry its type information, but not necessarily have a useful value.What should 'toString' return?Following my current path, it should return what it would normally return.One thing that concerns me is the API. The new Variant supports reflection via opDispatch, so adding 'isNull' and 'nullify' members would, for example, block Nullable!int's 'isNull' and 'nullify' members. Would '__isNull' '__nullify' be acceptable? Alternatively, I could special case opAssign and opEquals: 'var = Variant.NULL' and 'var == Variant.NULL'. Thoughts?Avoid the word null - use mark or whatever. If adding it means earmarking more than a single bit, then make it 'flags'. That way the facility is quite general-purpose. I think that in a 'type' that is supposed to stand for almost anything, this is not out of place.Sorry for all the questions, but I want to make sure what I build is what you need. That said, I'm pretty sure I can incorporate what you want.Questions are good. Do my answers make any sense? Steve
Oct 28 2011
On Fri, 28 Oct 2011 10:22:37 -0400, Steve Teale <steve.teale britseyeview.com> wrote:On Fri, 28 Oct 2011 00:35:45 -0400, Robert Jacques wrote:[snip]Okay, I think there was a bit of mis-communication here. What I'm asking is if the following represents required functionality: Variant var = 1; assert(var == 1); var.nullify; assert(var.isNull); var.unnullify; assert(var == 1); That is, do you need to be able to recover the previous value of the variant once it has been nulled?Speaking as the one making over variant, let me see if I understand your use case. Similar to typecons.Nullable, you want to be able to test any type for isNull and be to 'nullify' any type. Correct?I want to be able to mark a Variant which is otherwise functional and representing a type. It might have the .init value for the type, or it could have any other value. The mark in my context would signify that it should be treated as a NULL for database purposes. But it could be used to add any other subtlety to a variant. It's just a mark I think.Does nullifying a value wipe it clean? i.e. can you ever un-nullify something?No, it's just a mark, you can wipe it off and it then reverts to being a perfectly normal variantSo would the following be correct behavior? Variant var = 1; assert(var == 1); var.nullify; assert(var.isNull); var = "Hello"; assert(var == "Hello"); assert(var.isNull == false);If you assign to a nulled variant, should there be some sort of special behavior?I think maybe it should wipe the mark. If I've chosen a particular variant in a particular state to mark, then I'd say the mark would lose its significance if the thing was radically changed.As far as I understand it, a database null means that the field has no value. If a nulled variant has no value what does 'get' return? And whatever it does return, how can that be logically correct?Should 'hasValue' return false or true? If true, what should 'get' & company return?I think hasValue() et al should behave as usual - after all, it's just a mark. It's what I choose to do with the value from get or whatever that should be influenced.If variant does 'not necessarily have a useful value', why should 'hasValue' et al. function as if there were a value?'type' should return the TypeInfo of the type that was nullified, correctAbsolutely - that's the primary requirement for me. That the variant should carry its type information, but not necessarily have a useful value.So Variant var = 5; var.nullify; assert(var.toString == "5"); and not assert(var.toString == "Nulled int"; ?What should 'toString' return?Following my current path, it should return what it would normally return.Yes, but your answers weren't for the questions I was asking. Each of your answers appears to be predicated on a particular solution you wish to used to solve your problem. I've tried to ask clarifying questions to help define your actual use cases and functional needs. What I'm trying to define is the minimal feature set you need to make databases work well, not the behavior of the implementation you envision.One thing that concerns me is the API. The new Variant supports reflection via opDispatch, so adding 'isNull' and 'nullify' members would, for example, block Nullable!int's 'isNull' and 'nullify' members. Would '__isNull' '__nullify' be acceptable? Alternatively, I could special case opAssign and opEquals: 'var = Variant.NULL' and 'var == Variant.NULL'. Thoughts?Avoid the word null - use mark or whatever. If adding it means earmarking more than a single bit, then make it 'flags'. That way the facility is quite general-purpose. I think that in a 'type' that is supposed to stand for almost anything, this is not out of place.Sorry for all the questions, but I want to make sure what I build is what you need. That said, I'm pretty sure I can incorporate what you want.Questions are good. Do my answers make any sense?
Oct 28 2011
On Fri, 28 Oct 2011 23:50:37 -0400, Robert Jacques wrote:On Fri, 28 Oct 2011 10:22:37 -0400, Steve Teale <steve.teale britseyeview.com> wrote:Robert, I read through my answers again, and they seem to me to be perfectly valid responses to your questions. It's just that you are insisting on the use of terms like nullify and isNull that have different semantics than what is actually needed to deal with the database situation. Yes, I know I used NULL in my original question, but I was at pains to back of from that in my responses to your questions. I believe all that's needed to make variants play well with databases is a mark or flag. This could be used in other contexts for quite unrelated purposes. For the database case it would essentially serve as an ignore- this-value-just-note-the-type flag. It is not essential, but it would make a database interface using variants easier to code and to use. Probably we should just forget the idea. SteveOn Fri, 28 Oct 2011 00:35:45 -0400, Robert Jacques wrote:[snip]Okay, I think there was a bit of mis-communication here. What I'm asking is if the following represents required functionality: Variant var = 1; assert(var == 1); var.nullify; assert(var.isNull); var.unnullify; assert(var == 1); That is, do you need to be able to recover the previous value of the variant once it has been nulled?Speaking as the one making over variant, let me see if I understand your use case. Similar to typecons.Nullable, you want to be able to test any type for isNull and be to 'nullify' any type. Correct?I want to be able to mark a Variant which is otherwise functional and representing a type. It might have the .init value for the type, or it could have any other value. The mark in my context would signify that it should be treated as a NULL for database purposes. But it could be used to add any other subtlety to a variant. It's just a mark I think.Does nullifying a value wipe it clean? i.e. can you ever un-nullify something?No, it's just a mark, you can wipe it off and it then reverts to being a perfectly normal variantSo would the following be correct behavior? Variant var = 1; assert(var == 1); var.nullify; assert(var.isNull); var = "Hello"; assert(var == "Hello"); assert(var.isNull == false);If you assign to a nulled variant, should there be some sort of special behavior?I think maybe it should wipe the mark. If I've chosen a particular variant in a particular state to mark, then I'd say the mark would lose its significance if the thing was radically changed.As far as I understand it, a database null means that the field has no value. If a nulled variant has no value what does 'get' return? And whatever it does return, how can that be logically correct?Should 'hasValue' return false or true? If true, what should 'get' & company return?I think hasValue() et al should behave as usual - after all, it's just a mark. It's what I choose to do with the value from get or whatever that should be influenced.If variant does 'not necessarily have a useful value', why should 'hasValue' et al. function as if there were a value?'type' should return the TypeInfo of the type that was nullified, correctAbsolutely - that's the primary requirement for me. That the variant should carry its type information, but not necessarily have a useful value.So Variant var = 5; var.nullify; assert(var.toString == "5"); and not assert(var.toString == "Nulled int"; ?What should 'toString' return?Following my current path, it should return what it would normally return.Yes, but your answers weren't for the questions I was asking. Each of your answers appears to be predicated on a particular solution you wish to used to solve your problem. I've tried to ask clarifying questions to help define your actual use cases and functional needs. What I'm trying to define is the minimal feature set you need to make databases work well, not the behavior of the implementation you envision.One thing that concerns me is the API. The new Variant supports reflection via opDispatch, so adding 'isNull' and 'nullify' members would, for example, block Nullable!int's 'isNull' and 'nullify' members. Would '__isNull' '__nullify' be acceptable? Alternatively, I could special case opAssign and opEquals: 'var = Variant.NULL' and 'var == Variant.NULL'. Thoughts?Avoid the word null - use mark or whatever. If adding it means earmarking more than a single bit, then make it 'flags'. That way the facility is quite general-purpose. I think that in a 'type' that is supposed to stand for almost anything, this is not out of place.Sorry for all the questions, but I want to make sure what I build is what you need. That said, I'm pretty sure I can incorporate what you want.Questions are good. Do my answers make any sense?
Oct 29 2011
On Sat, 29 Oct 2011 16:23:11 -0400, Steve Teale <steve.teale britseyeview.com> wrote:On Fri, 28 Oct 2011 23:50:37 -0400, Robert Jacques wrote:[snip]I read through my answers again, and they seem to me to be perfectly valid responses to your questions. It's just that you are insisting on the use of terms like nullify and isNull that have different semantics than what is actually needed to deal with the database situation. Yes, I know I used NULL in my original question, but I was at pains to back of from that in my responses to your questions. I believe all that's needed to make variants play well with databases is a mark or flag. This could be used in other contexts for quite unrelated purposes. For the database case it would essentially serve as an ignore- this-value-just-note-the-type flag.Steve, when you state: "For the database case it would essentially serve as an ignore-this-value-just-note-the-type flag", you are no longer describing your concept or use case, you are describing how you would implement that use case using functionality X. From what I can tell, you're thinking of an implementation like this: Variant var = 1; var.mark = true; if(var.mark) { // Do DB NULL stuff } else { // Do DB value stuff } But how is that different from this: Variant var = 1; var.nullify; if(var.isNull) { // Do DB NULL stuff } else { // Do DB value stuff } or this: auto var = Variant.NULL!int; if(var.hasValue) { // Do DB NULL stuff } else { // Do DB value stuff } or this: auto var = typeid(int); if(auto type = var.peek!TypeInfo) { // Do DB NULL stuff } else { // Do DB value stuff } ? I don't care about adding functionality X; you can already build a null-able DB type on top of Variant (see above, or use Nullable!Vairant, etc). I care about making variant (or Algebraic) _into_ a null-able DB type. So that it composes integrates well with the rest of our code-bases.It is not essential, but it would make a database interface using variants easier to code and to use. Probably we should just forget the idea. SteveDatabases and their ilk are a pretty big and important use case. So I think cleanly supporting them is necessary. That said, there are lots of alternatives available.
Oct 29 2011
On Sat, 29 Oct 2011 17:42:54 -0400, Robert Jacques wrote:Variant var = 1; var.mark = true; if(var.mark) { // Do DB NULL stuff } else { // Do DB value stuff } But how is that different from this: Variant var = 1; var.nullify; if(var.isNull) { // Do DB NULL stuff } else { // Do DB value stuff } or this: auto var = Variant.NULL!int; if(var.hasValue) { // Do DB NULL stuff } else { // Do DB value stuff } or this: auto var = typeid(int); if(auto type = var.peek!TypeInfo) { // Do DB NULL stuff } else { // Do DB value stuff } ? I don't care about adding functionality X; you can already build a null-able DB type on top of Variant (see above, or use Nullable!Vairant, etc). I care about making variant (or Algebraic) _into_ a null-able DB type. So that it composes integrates well with the rest of our code-bases.Robert, I guess I was reacting to your worry about the std.typecons Nullable!T, and Steve S's objection to 'muddying' Variant by including specifically database oriented stuff. A simple mark seemed more general purpose and possibly more acceptable. From your examples, I like Variant var = 1; var.nullify; if(var.isNull) { // Do DB NULL stuff } else { // Do DB value stuff } As long as when it is nullified I can still use var.type and get int. I take it that in the case of this example hasValue() would signify that the Variant was 'raw' - we don't really have uninitialized in D. SteveIt is not essential, but it would make a database interface using variants easier to code and to use. Probably we should just forget the idea. SteveDatabases and their ilk are a pretty big and important use case. So I think cleanly supporting them is necessary. That said, there are lots of alternatives available.
Oct 29 2011
On Thu, 27 Oct 2011 19:06:47 +0100, Steve Teale <steve.teale britseyeview.com> wrote:On Thu, 27 Oct 2011 13:58:54 -0400, Steven Schveighoffer wrote:Could you wrap std.typecons.Nullable around it? It's currently disabled, but a quick copy/paste into my own src, plus templating the opAssign e.g. /** Assigns $(D value) to the internally-held state. */ void opAssign(T value) { enforce(_value); *_value = value; } and this works: import std.exception; //nullable import std.variant; import std.stdio; void main() { Nullable!Variant a; assert(a.isNull); a = 5; assert(!a.isNull); assert(a == 5); } I believe Nullable is going to be re-enabled soon? One argument in the nullable pull request: https://github.com/D-Programming-Language/phobos/pull/153 which also applies, is; why not just use Variant*'s in your database cases? R -- Using Opera's revolutionary email client: http://www.opera.com/mail/Why wouldn't you just wrap variant if you want to introduce a nullable variant type? Why does Variant have to be muddied with requirements for database API? Database null is an entirely different animal from D's null.Well, yes, that was my first reaction, but I thought I'd ask - if there was a spare bit somewhere in Variant, would it do much harm, and Variant is getting a makeover. Maybe there are circumstances other than database interactions where it could be useful.
Oct 28 2011
On Fri, 28 Oct 2011 10:23:03 +0100, Regan Heath <regan netmail.co.nz> wrote:On Thu, 27 Oct 2011 19:06:47 +0100, Steve Teale <steve.teale britseyeview.com> wrote:err.. sorry, I meant: /** Assigns $(D value) to the internally-held state. If the assignment succeeds, $(D this) becomes non-null. */ void opAssign(T)(T value) { _value = value; _isNull = false; } :p ROn Thu, 27 Oct 2011 13:58:54 -0400, Steven Schveighoffer wrote:Could you wrap std.typecons.Nullable around it? It's currently disabled, but a quick copy/paste into my own src, plus templating the opAssign e.g. /** Assigns $(D value) to the internally-held state. */ void opAssign(T value) { enforce(_value); *_value = value; }Why wouldn't you just wrap variant if you want to introduce a nullable variant type? Why does Variant have to be muddied with requirements for database API? Database null is an entirely different animal from D's null.Well, yes, that was my first reaction, but I thought I'd ask - if there was a spare bit somewhere in Variant, would it do much harm, and Variant is getting a makeover. Maybe there are circumstances other than database interactions where it could be useful.
Oct 28 2011
On Thu, 27 Oct 2011 14:06:47 -0400, Steve Teale = <steve.teale britseyeview.com> wrote:On Thu, 27 Oct 2011 13:58:54 -0400, Steven Schveighoffer wrote::On Thu, 27 Oct 2011 13:53:02 -0400, Steve Teale <steve.teale britseyeview.com> wrote:On Thu, 27 Oct 2011 13:09:43 -0400, Steven Schveighoffer wrote:On Thu, 27 Oct 2011 12:58:57 -0400, Steve Teale <steve.teale britseyeview.com> wrote:On Thu, 27 Oct 2011 16:16:26 +0200, Alex R=C3=B8nne Petersen wrote=e.On 27-10-2011 15:50, Steve Teale wrote:He is probably referring to the 'init' property on the *type*, i.=Surely Variant.init should do the trick?Dmitry, Are you talking about the new std.variant - I don't see 'init' currently. Stevedint.init and so on. - AlexSame catch 22. In order to have an init property, the Variant woul=dhave to have been set to some type, at which point hasValue() woul=eNo, I was just saying it didn't help.Sorry to jump in mid-stream, but you seemed to be suggesting Variant didn't have an init without an assigned type.Exactly, and v has reverted to being typeless:say yes. Steveimport std.variant; void main() { Variant v =3D 1; assert(v.hasValue()); v =3D v.init; assert(!v.hasValue()); } -SteveWhy wouldn't you just wrap variant if you want to introduce a nullabl=forvariant type? Why does Variant have to be muddied with requirements =database API? Database null is an entirely different animal from D's=enull.Well, yes, that was my first reaction, but I thought I'd ask - if ther=was a spare bit somewhere in Variant, would it do much harm, and Varia=ntis getting a makeover. Maybe there are circumstances other than databa=seinteractions where it could be useful.I don't like Variant having this behavior when it's only of specific use= . = Variant is not a database-only type. Here's another idea: struct DBNull(T) { } Where T is the type for the column. i.e.: row.column =3D DBNull!int; Now, you have your flag indicating it's null (you should be able to writ= e = a function that returns whether the column is null or not), it doesn't = consume any more space (value is already part of a union that's bigger = than DBNull!int), and the type of field is still valid. -Steve
Oct 28 2011
On Friday, October 28, 2011 19:04 Steven Schveighoffer wrote:I don't like Variant having this behavior when it's only of specific use. Variant is not a database-only type.Agreed. Unless such a change has a real use case beyond databases, I do not think that it should be built into Variant. - Jonathan M Davis
Oct 28 2011
On 29.10.2011 04:04, Steven Schveighoffer wrote:I don't like Variant having this behavior when it's only of specific use. Variant is not a database-only type. Here's another idea: struct DBNull(T) { } Where T is the type for the column. i.e.: row.column = DBNull!int; Now, you have your flag indicating it's null (you should be able to write a function that returns whether the column is null or not), it doesn't consume any more space (value is already part of a union that's bigger than DBNull!int), and the type of field is still valid.This is basically what ADO.Net does: http://msdn.microsoft.com/en-us/library/system.dbnull.aspx
Oct 29 2011
On 27-10-2011 15:12, Steve Teale wrote:How big a deal would it be to add a NULL indicator to the VariantN struct. I use the term NULL as opposed to null deliberately. Variant already provides the hasValue() method, which can serve as a null indicator. But in using it as a parameter in database modules, it would be useful to be able to give a Variant instance a type, as in v = "", but also to set it explicitly as NULL with setNull() or whatever. Could this fly without breaking existing code? SteveI'm not sure having three possible states in Variant is a good idea, but maybe I'm not quite following. Doesn't it already carry type information when not set to a value? - Alex
Oct 27 2011
I'm not sure having three possible states in Variant is a good idea, but maybe I'm not quite following. Doesn't it already carry type information when not set to a value? - AlexDon't believe so. If you haven't set any value, hasValue() will return false, so it is kind of null, and it is not associated with a type - how would it know? Steve
Oct 27 2011
On 27-10-2011 15:54, Steve Teale wrote:You're completely right; brain failed me for a moment there. OK, so I think introducing a constructor (or something like that) taking a TypeInfo object is a reasonable approach to setting it to no value, but still carrying a type. - AlexI'm not sure having three possible states in Variant is a good idea, but maybe I'm not quite following. Doesn't it already carry type information when not set to a value? - AlexDon't believe so. If you haven't set any value, hasValue() will return false, so it is kind of null, and it is not associated with a type - how would it know? Steve
Oct 27 2011
On Thu, 27 Oct 2011 09:12:26 -0400, Steve Teale <steve.teale britseyeview.com> wrote:How big a deal would it be to add a NULL indicator to the VariantN struct. I use the term NULL as opposed to null deliberately. Variant already provides the hasValue() method, which can serve as a null indicator. But in using it as a parameter in database modules, it would be useful to be able to give a Variant instance a type, as in v = "", but also to set it explicitly as NULL with setNull() or whatever. Could this fly without breaking existing code? SteveAny reason making a custom NULL type wouldn't work? i.e: struct NULL {} Variant var = NULL; assert(var.type == typeof(NULL));
Oct 27 2011
Any reason making a custom NULL type wouldn't work? i.e: struct NULL {} Variant var = NULL; assert(var.type == typeof(NULL));I don't think that is any improvement on hasValue(). It would tell you the particular value was null, but would not tell you what type it was. In a typical situation you need to tell the database server the type of the parameter, even if it is null. Steve
Oct 27 2011
Steve Teale Wrote:SQL uses `NULL` for all types. Did you try Algebraic - type-restricted version of Variant?Any reason making a custom NULL type wouldn't work? i.e: struct NULL {} Variant var = NULL; assert(var.type == typeof(NULL));I don't think that is any improvement on hasValue(). It would tell you the particular value was null, but would not tell you what type it was. In a typical situation you need to tell the database server the type of the parameter, even if it is null.
Oct 27 2011
On Fri, 28 Oct 2011 01:00:28 -0400, Kagamin wrote:SQL uses `NULL` for all types.Yes, but if you set a particular column value to NULL, it does not wipe away the column's meta-data.Did you try Algebraic - type-restricted version of Variant?SQL implementations tend to use structure types for time and date and such. Steve
Oct 28 2011
Steve Teale <steve.teale britseyeview.com> wrote:How big a deal would it be to add a NULL indicator to the VariantN struct. I use the term NULL as opposed to null deliberately. Variant already provides the hasValue() method, which can serve as a null indicator. But in using it as a parameter in database modules, it would be useful to be able to give a Variant instance a type, as in v = "", but also to set it explicitly as NULL with setNull() or whatever. Could this fly without breaking existing code? SteveJust store a std.typecons.Nullable!T in the Variant.
Oct 27 2011
On Thu, 27 Oct 2011 18:35:19 +0000, kennytm wrote:Just store a std.typecons.Nullable!T in the Variant.Mmm - works to some extent, but by the time you'd wrapped it to make the semantics half comprehensible I think it would have been better to simply wrap VariantN to add an extra bool. Steve
Oct 27 2011