Menu

scScript Comparing & Counting

The C programming language has familiar == and != operators to compare scalar values as well as pointers. But scScript does not expose pointers, so provides special === and !== operators to compare storage locations instead. Given: Var A = "Yes", B = "Yes";
All the following will be true: (A == B) (A == "Yes") (B == "Yes")
because A and B will have the exact same value, "Yes" (an immutable string).

But all the following will be false: (A === B) (A === "Yes") (B === "Yes")
because A and B are different variables with different storage locations. Even more, while the value of A is "Yes", the variable A has its very own storage location, which is not the same as the literal string "Yes". In that sense, X === Y really tests that X is Y. (Recall that X =& Y makes X become Y.)

While === generally tests if both sides have the same storage location, it is smart enough to do a value comparison if one (or both) sides are just constant numbers without a storage location. So K === 12 returns 1 if the value of K is 12. Importantly, this test also works for NaN, since it does a bit-image comparison and not a numerical one. Therefore K === Math.#Nan is a good test to see if the value of K has left the realm of numbers. (Some languages require an obscure K != K test for this!)

Arrays, unless created with a [] constructor, are created with missing (unpopulated) cells. Dicts, by definition, only have a few pairs and are missing a whole infinity of possible key-value pairs. When comparing or using values, scScript will automatically populate any missing elts or pairs. It initializes these empty storage cells to contain the value Int 0, so == and other operations get proper values to compare and use. This auto-populate may also involve expanding the array or dict as necessary.

So a simple test, such as: (MyDict.George == 0) or (MyArr[12] == 0)
will in fact add a pair to MyDict and an elt to MyArr if they did not have them before. Therefore an equality test for MyArr[240000] will cost an immense amount of memory as MyArr is expanded!

But things are different for === as it only cares about storage locations, not values. To that end, === does not populate missing elts or pairs; it just treats them as missing (null) locations. But to get the proper semantics, === returns 0 if they are missing! So A[x] === A[y] is always 0 when one or both are missing. Interestingly a statement of the form A[x] == A[y] will automatically create both missing elts (and succeed as both will be 0), but these will still have different storage locations, so the === test, if subsequently applied, will once again return 0.

scScript provides two predicates to ascertain the size of an array or dict:

Importantly, the special dyadic function CountOf(TheArr, Index) or CountOf(TheDict, Key) will return 0 if the indexed elt is not populated or the indicated pair is not in the dict. But it is imperative to use this 2-arg format, otherwise CountOf(TheArr[Index]) will automatically populate TheArr[Index] when the argument for CountOf is being processed!

// Size and Count test!  (SCTest.sc)

Var A = Array();
Var D = Dict();

A[5] = 0;
D[5] = 12, D["Yes"] = 144, D["No"] = "Yes";

Writeln("A Size ", SizeOf(A));
Writeln("A Count ", CountOf(A));
Writeln("A[5] Count --> ", CountOf(A, 5));
Writeln("A[4] Count --> ", CountOf(A, 4));
Writeln("-----------");

Writeln("D Size ", SizeOf(D));
Writeln("D Count ", CountOf(D));
Writeln("D.Yes Count --> ", CountOf(D, "Yes"));
Writeln("D[4] Count --> ", CountOf(D, 4));
Writeln("-----------");

Writeln("A[5] == A[4] --> ", A[5] == A[4]);
Writeln("A[5] === A[4] --> ", A[5] === A[4]);
Writeln("A[5] === A[5] --> ", A[5] === A[5]);
Writeln("A[5] === A[6] --> ", A[5] === A[6]);
Writeln("A[3] === D[3] --> ", A[3] === D[3]);
Writeln('D["No"] == "Yes" --> ', D["No"] == "Yes");
Writeln('D["No"] === "Yes" --> ', D["No"] === "Yes");
Writeln('"Yes" === "Yes" --> ', "Yes" === "Yes");
Writeln("-----------");

Function Test()(OutA, OutD)
{
    Var   LocA =& OutA;
    Var   LocB = LocA;

    Writeln("OutA === A --> ", OutA === A);
    Writeln("OutA === LocA --> ", OutA === LocA);
    Writeln("LocA === A --> ", LocA === A);
    Writeln("LocB === A --> ", LocB === A);
    Writeln("-----------");

    LocA[9] =& OutD["Yes"];
    Writeln("LocA[9] --> ", LocA[9]);
}

Test()(A, D);
Writeln("A[9] --> ", A[9]);

Writeln("-----------");
Show.Vars(Show.#MAX)(A, D);

The sample code above, and its output below, illustrates many of the points made in this section. The Test() function above demonstrates the implicit alias mechanism of the out arg list as well as the explicit storage assignment of the =& operator itself. In both cases, variables are assigned pre-existing storage locations belonging to another, a relationship that can be verified using ===.

A Size 8
A Count 1
A[5] Count --> 1
A[4] Count --> 0
-----------
D Size 16
D Count 3
D.Yes Count --> 1
D[4] Count --> 0
-----------
A[5] == A[4] --> 1
A[5] === A[4] --> 0
A[5] === A[5] --> 1
A[5] === A[6] --> 0
A[3] === D[3] --> 0
D["No"] == "Yes" --> 1
D["No"] === "Yes" --> 0
"Yes" === "Yes" --> 1
-----------
OutA === A --> 1
OutA === LocA --> 1
LocA === A --> 1
LocB === A --> 0
-----------
LocA[9] --> 144
A[9] --> 144
-----------
    Var (Ref:1) [Entry 000032 (16 Bytes) on Mem:1 (VEnt) Slab:1]
        --> Array (Ref:1) [Entry 000064 (16 Bytes) on Mem:1 (VEnt) Slab:1]
            --> 10 Entries [Entry 009536 (96 Bytes) on Mem:4 (ADat) Slab:1]
                000 ---
                001 ---
                002 ---
                003 ---
                004 ---
                005 Var (Ref:1) [Entry 000000 (16 Bytes) on Mem:1 (VEnt) Slab:1]
                    Int 0
                006 ---
                007 ---
                008 ---
                009 Pair (Ref:2) [Entry 016608 (32 Bytes) on Mem:2 (BEnt) Slab:1]
                    Int 144

    Var (Ref:1) [Entry 000016 (16 Bytes) on Mem:1 (VEnt) Slab:1]
        --> Dict (Ref:1) [Entry 017184 (32 Bytes) on Mem:2 (BEnt) Slab:1]
            --> 16 Entries [Entry 009392 (144 Bytes) on Mem:4 (ADat) Slab:1]
                Filled Dictionary:  3 of 16
                Total Probes:3 (Avg:1.000000)
                - * - - - - - - * - - - - * 
                Pair (Ref:1) 0001 Key:"No" Val:"Yes"
                Pair (Ref:2) 0002 Key:"Yes" Val:144
                Pair (Ref:1) 0003 Key:5 Val:12