## Δευτέρα 22 Νοεμβρίου 2021

### Revision 41, Version 10

1. Fix the sort algorithm for Lists (Inventory type), when we choose Descending traiting keys as numbers (or have number fields inside).

// list is an inventory class object
s=list:=2,3,4,5,30,40, 200
sort descending s as number
print s
// using s=list:=2,3,4,5,30,40, 200 we don't have to clear s.
// because we get new pointer.
// now we have an s as list so we have to clear if we use Inventory statement.
Clear s
Inventory s= 2,3,4,5,30,40, 200
//Append s, 2,3,4,5,30,40, 200  // or using Append because s type is  Inventory
Print Type\$(s)="Inventory"
Print "s is a Queue:", @IsQueue(s), "???"
sort ascending s as number
print s
// Queue may have same keys - it is also an Inventory Class object
// stable sort
s=queue:=2,3:="first 3",3:="Second 3",4,5,30,40, 200
Print Type\$(s)="Inventory"

Print "s is a Queue:", @IsQueue(s)
sort descending s as number
print s
sort ascending s as number
print s

Function IsQueue(k as inventory)
With k, "IsQueue" as ok
=Val(ok -> boolean)
End Function

Sorting methods/statements exist for:

1. Document object. We set a position for starting the "key", plus starting and ending paragraph.
2. Array 1D
3. Array 2D
4. Inventories (list & queue subtype)

About (4) Keys on inventories are Strings always but we can use numbers (which converted to string before the key finding function took place). We can use either text or number type sort. Number type is not only if the key is a number but also if it has number fields (so a 1.2.3.5 can used for number sort, because all numbers inside key are treated as numbers.

Test some sortings:

s=list
profiler
for i=1 to 1000
append s, i
next i
m=timecount
print "Press A key", "- Time to insert 1000 items:", m
Push Key\$: Drop
print "sort start"
profiler
sort descending s as number
m=timecount
print "ok"
print s
print m
print "Press A key"
Push Key\$: Drop
print "sort start"
profiler
sort ascending s as number
m=timecount
print "ok"
print s
print m

// Using an array (pointer to a) which we append one item array for 1000 times. It's very fast, 3300 times from previous sort. (on a list). A sorting in a list, copy item structures and rehash all items. A sort in an array just use 16 bytes for each value (it's type of Variant, internal).

a=(,)
profiler
for i=1 to 1000
append a, (i,)
next i
m=timecount
Print "Press A key", "- Time to insert 1000 items:", m
Push Key\$: Drop
print "sort start"
profiler
sort descending a
m=timecount
print "ok"
print a
print m
Print "Press A key"
Push Key\$: Drop
print "sort start"
profiler
sort ascending a
m=timecount
print "ok"
print a
print m

We can mix strings and numbers in 1D array. Always string treated as Higher from any numeric value.

a=(,)
profiler
for i=1 to 10
append a, (str\$(i,"")+"*",)
next i
for i=i to 20
append a, (i,)
next i
for i=i to 30
append a, (str\$(i,"")+"*",)
next i
for i=i to 40
append a, (i,)
next i
m=timecount
print "Press A key", "- Time to insert 40 items:", m
Push Key\$: Drop
print "sort start"
profiler
sort descending a
m=timecount
print "ok"
print a
print m
print "Press A key"
Push Key\$: Drop
print "sort start"
profiler
sort ascending a
m=timecount
print "ok"
print a
print m

// 2D arrays have multiple keys (each column can be another key). In the example below we use a\$() to put strings and numbers. So we make a reference to a\$() as a() and we use it for passing/reading numbers. The sort statement expect a range (start-end), and a series of  two VALUES, the column number and the sort type. Here we have column 2 as first Key and column 3 as second Key. The same happen like 1D if we have strings and numbers in one column.

dim a\$(1 to 10, 1 to 3)

for i=1 to 10
a\$(i, 1)="Title"+str\$(i)
a(i, 2)=Random(1, 3)
a(i, 3)=Random(1, 5)*500
next i
sort a(), 1, 10, 2, ascending, 3, descending
for i=1 to 10
Print a\$(i, 1), a(i, 2), a(i, 3)
next i

2. Static Functions now return Boolean type, like ordinary functions and lambda functions.

k=true=true
def m as boolean=False, z as Currency=12.4555
print k, type\$(k)="Boolean", type\$(m)="Boolean"
print  val(z->Boolean) ' cast to Boolean
function TrueM {
=1=1
}
TrueM0=lambda ->1=1
print TrueM()
print TrueM0()
print @TrueM1()

function TrueM1()
=1=1
end function

A static Function is like a Sub, their definitions are in the bottom of module's code. We can't change code for static function by code, only from editor. Ordinary functions (or we say Functions, with any adjective before) are catalog in a list of functions, and before we use them we have to register to that catalog using a line (or more) like Function Alfa(x, y) { code here } or Function Alfa {Read x, y: code here} which is the actual code which M2000 made in the catalog (the x and y parameters are going to a statement Read). Also a Function can be called in an expression Print Alfa(1,2) , or using Call, like Call Alfa(1,2)  (a non zero value raise error, unless we say Call Void Alfa(1,2) which drop the value before the error part examine the return value.  Static functions can be used only in expressions and need a @ before the name.  Also a Static function can't passed by reference (until current version and revision, later maybe change this).

All functions in M2000 have one of two major types, numeric or alphanumeric (string). Its important for M2000 Interpreter to know in advance which major type a function have by using the \$ character as the last symbol attached to function name. So alfa\$(1, 2) is a (string OR object which return string), and alfa(1,2) is a (numeric Or object ).

A lambda function is a function and a variable, which have two parts, a list of closures and code to execute. Putting another lambda in a lambda we through the old lambda. We can take a snapshot of a lambda using another variable, uninitialized or type of lambda. Closures are copies, and that means that a pointer to an object may change locally, but if not changed the object be like a common access resource for all snapshots.

Finally, we can make objects of type Group to behave like Functions, using private members are own "closures".

Array Alfa() can exist with Alfa() function. We can call Alfa() like static function using @Alfa(), but normally there isn't clever to use same names, as local names. But what happen if one of them are global?

Global alfa(1 to 10,1 to 2)=1
Module z {
Print alfa(2, 2)=1
Function alfa(x, y) {
=x**y
}
Print alfa(2, 2)=4
}
z

We can write in another module this:

Function Global alfa(x, y) {
=x**y
}
Module z {
Print alfa(2, 2)=4
Dim alfa(1 to 10,1 to 2)=1
Print alfa(2, 2)=1
}
z

A local name shadow a global one.