More info needed for xSharp on different Null(s), Nil, DotNet DBNull, None

This forum is meant for questions and discussions about the X# language and tools
User avatar
robert
Posts: 4310
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

More info needed for xSharp on different Null(s), Nil, DotNet DBNull, None

Post by robert »

Thomas, Antonio,
At this moment we plan the following (and this will not be included in the coming build by the way):
- we're not going to invent new type
- The literal .NULL. will be compiled to DbNull.Value. That is a DotNet standard for NULL database values.
- When .NULL. or DbNull.value is stored in a Usual we will assign it a new UsualType. We'll make its ValType and VarType "X" and its "ToString()" will be ".NULL."
- The IsNull() function will return TRUE for USUAL values with this type.
- The various operators in the Usual class will allow adding / subtracting USUAL values with .NULL. and will return .NULL., just like VFP does
- I did a check with VFP and if you assign .NULL. to a variable (let's say A) then the comparison A == .NULL. returns FALSE even when A has the value .NULL. That does not really make sense, but we'll implement that too. We'll also implement all the other operators on the USUAL type to work just like VFP, so when usual A has .NULL. and usual B has "A" the result of A + B will be .NULL..
- In VFP the expression (considering again that A has the value .NULL.) "IF A" will also not evaluate to TRUE so will go into the ELSE branch of the IF statement. We'll implement that too.
- And As long as you don't strongly type your code this should all be fine. When you start strong typing your code then assigning a value of .NULL. to a type variable, such as for example a STRING will generate an error. Assigning a literal .NULL. to a STRING will generate a compiler error (since the compiler knows that you cannot assign DBNull.value to a string).
If you assign an untyped variable containing .NULL. to a string will generate a runtime error, since there is no real conversion.

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
atlopes
Posts: 83
Joined: Sat Sep 07, 2019 11:43 am
Location: Portugal

More info needed for xSharp on different Null(s), Nil, DotNet DBNull, None

Post by atlopes »

Robert,

Ok. we'll see how this will work against actual code.

Just one more bit of information: assign a NULL to an object variable is common practice in VFP code to release the object (starting with the official documentation).

Code: Select all

LOCAL tn AS n

m.tn = CREATEOBJECT("n")

? "("

m.tn = .NULL.

? ")"

DEFINE CLASS n AS Custom

	PROCEDURE Destroy

		? "Being released..."

	ENDPROC

ENDDEFINE
prints

Code: Select all

(
Being released...
)
I don't know how this adjusts to your plans.

Now, </neutral>
I did a check with VFP and if you assign .NULL. to a variable (let's say A) then the comparison A == .NULL. returns FALSE even when A has the value .NULL. That does not really make sense, but we'll implement that too.
In fact, it makes a lot of sense and encapsulates perfectly well the place and purpose of NULL in VFP. NULL is not a value, it can't be compared to anything, including itself. And VFP is far from being alone in this approach. In standard SQL, these two statements

Code: Select all

SELECT COUNT(*) FROM someTable WHERE someNilableColumn = NULL;
SELECT COUNT(*) FROM someTable WHERE someNilableColumn IS NULL;
are not equivalent and the first will always return 0, no matter what.
mainhatten
Posts: 200
Joined: Wed Oct 09, 2019 6:51 pm

More info needed for xSharp on different Null(s), Nil, DotNet DBNull, None

Post by mainhatten »

Hi Robert,
robert wrote: ...
- I did a check with VFP and if you assign .NULL. to a variable (let's say A) then the comparison A == .NULL. returns FALSE even when A has the value .NULL. That does not really make sense, but we'll implement that too. We'll also implement all the other operators on the USUAL type to work just like VFP, so when usual A has .NULL. and usual B has "A" the result of A + B will be .NULL..
- In VFP the expression (considering again that A has the value .NULL.) "IF A" will also not evaluate to TRUE so will go into the ELSE branch of the IF statement. We'll implement that too.
Antonio beat me pointing to SQL as reason for .Null. # .Null. making sense - my example would have been an inner join, where including on "I don't know" probably is not wished for. Reads ok, including DBNull.Value as default for nulled Usuals.
- And As long as you don't strongly type your code this should all be fine. When you start strong typing your code then assigning a value of .NULL. to a type variable, such as for example a STRING will generate an error. Assigning a literal .NULL. to a STRING will generate a compiler error (since the compiler knows that you cannot assign DBNull.value to a string).
If you assign an untyped variable containing .NULL. to a string will generate a runtime error, since there is no real conversion.
Here I am uncertain,

Code: Select all

string s1 = "abcd";
string s2 = "";
string s3 = null;

Console.WriteLine("String s1 {0}.", Test(s1));
Console.WriteLine("String s2 {0}.", Test(s2));
Console.WriteLine("String s3 {0}.", Test(s3));

String Test(string s)
{
if (String.IsNullOrEmpty(s))
    return "is null or empty";
else
    return String.Format("("{0}") is neither null nor empty", s);
}
is valid C# of MS documentation. Does your text mean that in xSharp strings cannot be "null" any more or just that they cannot be assigned the DBNull.value used in RT? Problem here is probably that .Null. and null are synonymous in vfp code - I must think a bit on that.

Current way of thinking is that Core/stong typed xSharp should support the concept of "null" in POCOs by having nullable strings and other variables, so IMO the distinction C# makes between "null" and DBNull should be mirrored in xSharp. But that is first impression, not really thought through.

my 0.02€
thomas
User avatar
robert
Posts: 4310
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

More info needed for xSharp on different Null(s), Nil, DotNet DBNull, None

Post by robert »

Thomas,

From the Ms Docs on DbNull:

Do not confuse the notion of null in an object-oriented programming language with a DBNull object. In an object-oriented programming language, null means the absence of a reference to an object. DBNull represents an uninitialized variant or nonexistent database column.

So "null" for strings is allowed of course.

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
mainhatten
Posts: 200
Joined: Wed Oct 09, 2019 6:51 pm

More info needed for xSharp on different Null(s), Nil, DotNet DBNull, None

Post by mainhatten »

Hi Antonio,
atlopes wrote:That said, and starting to get a bit judgmental here, I don't think that VFP's NULL approach is consistent all the way in every corner, I'm fully agreeing with you. It won't be too hard to find some Wat moments.

Furthermore, in their specific area, VFP SQL commands (the great mountain ahead for the X# team to climb) follow the ANSI rules. For instance,

Code: Select all

CREATE CURSOR x (n Int NULL)
INSERT INTO x VALUES (1)
INSERT INTO x VALUES (.NULL.)
SELECT MAX(n) FROM x  && shows 1


The only reasonable scenario I anticipate where we would throw a NULL inside a built-in VFP function is when the value comes from an external source, like a query, or a result from a method call, or the value of a property. But this is me not being neutral anymore.
What I meant was that the Foxtools originating functions are less adapted to SQL. Enhancing your example a bit

Code: Select all

CREATE CURSOR x (n Int NULL, se CHR(20) Null, js CHR(20) Null)
INSERT INTO x VALUES (1, "< for extract >", "c:fil.txt")
INSERT INTO x VALUES (5, "< for ext >", "c:filname.txt")
INSERT INTO x VALUES (.NULL., .null., .null.)
SELECT MAX(n) ;
, MAX(LEN(STREXTRACT(Se, "<", ">"))) ;
, MAX(LEN(IIF(ISNULL(Js), .Null., JUSTSTEM(js)))) ;
 FROM x  
might not be totally construed examples. StrExtract() is easy to use over the table, if I want to find longest file name length I have to guard the function - here done with iif(), in real code probably with a wrapper function returning .Null. on IsNull(). Takes longer to write about it then to code, so let us drop the theme.
Nevertheless, I think that being able to distinguish between NULL and any other value, including empty values, should be a fairly expectable target for a VFP implementation, and I hope X# succeeds in this.
Agreed. If they ban IsBlank or Blank I would not protest much as long as null is fully supported.

regards
thomas
mainhatten
Posts: 200
Joined: Wed Oct 09, 2019 6:51 pm

More info needed for xSharp on different Null(s), Nil, DotNet DBNull, None

Post by mainhatten »

robert wrote: So "null" for strings is allowed of course.
Good.

regards
Thomas
mainhatten
Posts: 200
Joined: Wed Oct 09, 2019 6:51 pm

More info needed for xSharp on different Null(s), Nil, DotNet DBNull, None

Post by mainhatten »

Robert, one slight correction (had to verify some nagging vague memory first)
robert wrote: - I did a check with VFP and if you assign .NULL. to a variable (let's say A) then the comparison A == .NULL. returns FALSE even when A has the value .NULL. That does not really make sense, but we'll implement that too.
The reason being SQL already discussed, but I guess you checked with iif(null==null)
In effect if deciding outcome/program flow on boolean criterion the above is stlll true, but the underlying mechanism is slightly different, the comparison returns .null., which then works as .f. if checked as Boolean:

Code: Select all

ln1 = null
ln2 = null
lnErg = (ln1=ln2)
? lnErg
lnErg = (ln1==ln2)
? lnErg
? IIF(lnErg, "= true", "= false")
BTW: Having read up on Dotnet Nullable value and reference types I can understand you staying first with Usual and own nullable implementation - head is reeling, and if I understood Dotnet "thinks" your way in checking nullable value types for equality - I still think SQL is more important for a DB language, but perhaps creating NullSqlEqual and NullVarEqual extension methods might make sense if you want to enable nullable types in Core at some later time. Holler if you want Short code examples of vfp SQL joins with nulls

regards
thomas
Post Reply