Manual: Difference between revisions

From NEOSYS Dev Wiki
Jump to navigationJump to search
No edit summary
 
(17 intermediate revisions by 2 users not shown)
Line 1: Line 1:
=== Programmer's Guides ===
Only for C++ at the moment. For all others, see some examples:
http://code.google.com/p/exodusdb/source/browse/#svn%2Ftrunk%2Fswig%2Fshare
==== [[Python]] ====
==== [[Perl]] ====
==== [[PHP]] ====
==== [[Java]] ====
==== [[C#]] ====
==== [[C++]] ====
=== ICONV/OCONV PATTERNS ===
=== ICONV/OCONV PATTERNS ===


==== Decimal (MD/MC) ====
==== Decimal (MD/MC) ====


{|border="1" cellpadding="10" cellspacing="0"
{|class="wikitable"  
!input!!conversion (string)!!output
!input!!conversion (string)!!output
|-
|-
Line 44: Line 31:
==== Date (D) ====
==== Date (D) ====


{|border="1" cellpadding="10" cellspacing="0"
{|class="wikitable"  
!input!!conversion (string)!!output
!input!!conversion (string)!!output
|-
|-
Line 84: Line 71:
==== Time (MT) ====
==== Time (MT) ====


{|border="1" cellpadding="10" cellspacing="0"
{|class="wikitable"  
!input!!conversion!!output
!input!!conversion (string)!!output
|-
|-
|234800||MT||17:13
|234800||MT||17:13
Line 106: Line 93:
==== Hex (HEX/MX) ====
==== Hex (HEX/MX) ====


{|border="1" cellpadding="10" cellspacing="0"
{|class="wikitable"  
!input!!conversion (string)!!output
!input!!conversion (string)!!output
|-
|-
Line 130: Line 117:
==== Text (L/R/T) ====
==== Text (L/R/T) ====


{|border="1" cellpadding="10" cellspacing="0"
{|class="wikitable"  
!input!!conversion!!output
!input!!conversion!! (string)output
|-
|-
|abcd||L#3||abc
|abcd||L#3||abc
Line 227: Line 214:
</pre>
</pre>


=== Traditional Multivalue Functions and Statements (non-OO) ===
=== Functions and Commands ===
 
Exodus clones traditional multivalue function and statement behaviour and retains their syntax as far as possible.
 
* Traditional functions are rendered as Exodus functions.
* Traditional statements are rendered as Exodus subroutines.
 
PRINT OCONV(DATE(),'D')
 
in Exodus becomes:
 
printl(oconv(date(),"D"));


==== String Commands ====
==== String Commands ====


The use of most of Exodus's functions will be fairly obvious to traditional multivalue programmers.
Most string functions like trim() that return a new modified string have a corresponding modify in place command like function like trimmer() that is is usually much faster.
 
So we have convert and converter, replace and replacer, insert and inserter and so on.  
Ηοwever it is not so obvious that all the functions ending in "-er" correspond to the old string commands.


For example, the classic multivalue "modify in-place" character conversion command:
Therefore by preference use


  CONVERT 'ab' TO 'cd' IN ZZ
  trimmer(v1);
// or
v1.trimmer()


is now represented in Exodus by:
instead of


  converter(zz,"ab","cd");
  v1 = trim(v1);
 
  // or
Exodus provides a complete set of string modification commands even where there was no specific command in classic mv basic.
  v1 = v1.trim();
 
To guarantee fast performance (regardless of compiler optimisation) you should always use the command instead of the old "self assign" idiom.
 
For example:
 
ZZ=TRIM(ZZ)
 
should appear in Exodus as:
 
  trimmer(zz);
 
and not:
 
  zz=trim(zz);


==== Function Types ====
==== Function Types ====


{|border="1" cellpadding="10" cellspacing="0"
{|class="wikitable"  
!TYPE !!FUNCTION TYPE||
!TYPE !!FUNCTION TYPE||
|-
|-
Line 281: Line 244:
|cmd ||traditional commands with no outputs||
|cmd ||traditional commands with no outputs||
|-
|-
|cmd2 ||traditional commands that now have outputs and can be used in expressions||
|expr ||traditional commands that now have outputs and can be used in expressions||
|}
|}


==== Parameters/Argument Types ====
==== Parameters/Argument Types ====


{|border="1" cellpadding="10" cellspacing="0"
{|class="wikitable"  
|in|| Parameters that provide data to the function. Can be variables or raw data like 1 or "X"||
|in|| Parameters that provide data to the function. Can be variables or raw data like 1 or "X"||
|-
|-
Line 299: Line 262:
Optional Parameters
Optional Parameters


{|border="1" cellpadding="10" cellspacing="0"
{|class="wikitable"  
!Key !!Default||
!Key !!Default||
|-
|-
|="" ||""||
|= "" ||""||
|-
|-
|=" " ||" "||
|= " " ||" "||
|-
|-
|="." ||"."||
|= "." ||"."||
|-
|-
|=1 ||1 ||
|= 1 ||1 ||
|-
|-
|=0 ||0||
|= 0 ||0||
|-
|-
|=true ||true||
|= true ||true||
|-
|-
|=false ||false||
|= false ||false||
|}
|}


==== Complete List of Functions ====
==== Field mark characters ====


Exodus implements a PICK OS data structure called a "dynamic array". This is simply any string which uses six specific unprintable ASCII delimiter characters (\x1A to \x1F) to separate its various parts. The parts are referred to as records, fields, values, subvalues, text, and subtext and fall within each other.


===== Environment =====
Dynamic arrays therefore implement sparse six dimensional arrays.


{|border="1" cellpadding="10" cellspacing="0"
Typical CPU caching architecture favours similar values being adjacent in memory therefore implementing them as strings of values separated by delimiter characters can have performance advantages over more complex structures.
|-
|var= ||osgetenv(envname)||
|-
|if ||osgetenv(envname, out value)||
|-
|if ||ossetenv(envname, newvalue)||
|}


===== Time/Date/Sleep =====
In practice the vast majority of dynamic arrays consist of "fields" separated by the FM character (\x1E) but it is very common for fields to have values separated by the VM character (\x1D) and values to have subvalues using SM (\x1D).


{|border="1" cellpadding="10" cellspacing="0"
Since the six delimiter characters fall in the unprintable character range certain other characters have been designated as usable for coding and printing. For example the FM character is represented as ^ and can be entered in source code appended with _var to indicate that the string must be converted to internal format.
|var= ||date()||
|-
|var= ||time()||
|-
|var= ||timedate()||
|-
|cmd ||ossleep(milliseconds)||
|-
|var= ||ostime()||
|}


===== System File =====
var v1 = "f1^f2^f3"_var; // Three fields


{|border="1" cellpadding="10" cellspacing="0"
var v2 = "f1^v1]v2]v3^f3"_var; // Three fields, 2nd field has 3 values. It is "multivalued".
|if ||osopen(filename, out filehandle, in locale="")||
|-
|cmd ||osclose(filehandle)||
|-
|var= ||osbread(filehandle, startoffset, length)||
|-
|cmd ||osbread(out data, filehandle, startoffset, length)||
|-
|cmd ||osbwrite(data, filehandle, startoffset)||
|-
|if ||osread(out data, osfilename, in locale="")||
|-
|var= ||osread(osfilename, in locale="")||
|-
|if ||oswrite(data, osfilename, in locale="")||
|-
|if ||osdelete(osfilename)||
|-
|if ||osrename(oldosdir_or_filename, newosdir_or_filename)||
|-
|if ||oscopy(fromosdir_or_filename, newosdir_or_filename)||
|-
|cmd ||osflush()||
|}


===== System Directory =====
Anything which contains a collection of fields can be considered as a "record" and records can be stored in files with a unique primary key. The fields might represent different columns of a traditional database table. So anonymous field number 1 might be a contact name, field 2 the contact address, field 3 a multivalued list of contact points. etc.


{|border="1" cellpadding="10" cellspacing="0"
{|class="wikitable"  
|var= ||oslist(path=".", wildcard="", mode=0)||
!Delimiter<br>name!!var||Hex!!Display!!cstr " "||char ' '
|-
|var= ||oslistf(path=".", wildcard="")||
|-
|var= ||oslistd(path=".", wildcard="")||
|-
|-
|var= ||osfile(filename)||
|Record Mark  ||RM||\x1F|| ` || _RM || RM_
|-
|-
|var= ||osdir(filename)||
|Field Mark    ||FM||\x1E|| ^ || _FM || FM_
|-
|-
|if ||osmkdir(newdirname)||
|Value Mark    ||VM||\x1D|| ] || _VM || VM_
|-
|-
|if ||osrmdir(dirname, evenifnotempty=false)||
|Subvalue Mark ||SM||\x1C|| } || _SM || SM_
|-
|-
|var= ||oscwd()||
|Text Mark||TM ||\x1B|| &#124; || _TM || TM_
|-
|-
|var= ||oscwd(newdirname)||
|Subtext Mark  ||STM||\x1A|| ~ || _STM || STM_
|}
|}


===== Program Control =====
{|class="wikitable" style="text-align: center;"
 
{|border="1" cellpadding="10" cellspacing="0"
|var= ||suspend(command)||
|-
|var= ||osshell(command)||
|-
|var=    ||osshellread(command)||
|-
|-
|cmd    ||osshellread(out commandoutput, command)||
|align=right|<b> Delimiter Name :</b>  ||Record Mark||Field Mark||Value Mark||Subvalue Mark||Text Mark||Subtext Mark
|-
|-
|cmd   ||osshellwrite(commandinput, command)||
|align=right|<b>var :</b>   || RM ||FM  ||VM  ||SM  ||TM  ||STM
|-
|-
|cmd ||stop(text="")||
|align=right|<b>Display :</b>||`  ||^  || ]  || }  || &#124; || ~
|-
|-
|cmd ||abort(text)||
|align=right|<b>Hex :</b>    ||\x1F||\x1E||\x1D||\x1C||\x1B||\x1A
|-
|-
|var= ||perform(command)||
|align=right|<b>cstr " " :</b>  ||_RM ||_FM ||_VM ||_SM ||_TM ||_STM
|-
|-
|var= ||execute(command)||
|align=right|<b>char ' ' :</b>  ||RM_ ||FM_ ||VM_ ||SM_ ||TM_ ||STM_
|-
|var= ||chain(command)||
|-
|var= ||logoff()||
|-
|cmd ||debug()||
|}
|}


==== Complete List of Functions ====


===== Variable Control =====
[[Functions|Complete List of Functions]]
 
{|border="1" cellpadding="10" cellspacing="0"
|if    ||assigned(anyvar)||
|-
|if    ||unassigned(anyvar)||
|-
|cmd2    ||exchange(var1,var2)||
|-
|cmd2    ||transfer(fromvar,tovar)||
|}
 
===== Console Output =====
 
{|border="1" cellpadding="10" cellspacing="0"
|cmd ||print(instring)||
|-
|cmd ||printl(instring="")||
|-
|cmd ||printt(instring="")||
|}
 
===== Cursor =====
 
{|border="1" cellpadding="10" cellspacing="0"
|var= ||at(column0orcode)||
|-
|var= ||at(column0, row0)||
|-
|var= ||getcursor()||
|-
|cmd ||setcursor(cursorstr)||
|-
|var= ||getprompt()||
|-
|cmd ||setprompt(promptchar)||
|}
 
===== Console Input =====
 
{|border="1" cellpadding="10" cellspacing="0"
|-
|var= ||input()||
|-
|var= ||input(out inputstr)||
|-
|var= ||input(prompt, out inputstr)||
|-
|var= ||inputn(n)||
|}
 
===== Math =====
 
{|border="1" cellpadding="10" cellspacing="0"
|var=    ||rnd(number)||
|-
|cmd    ||initrnd(seednumber)||
|-
|var=    ||mod(dividend, divisor)||
|-
|var=    ||abs(number)||
|-
|var=    ||pwr(base, exponent)||
|-
|var=    ||exp(power)||
|-
|var=    ||sqrt(number)||
|-
|var=    ||sin(degrees)||
|-
|var=    ||cos(degrees)||
|-
|var=    ||tan(degrees)||
|-
|var=    ||atan(number)||
|-
|var=    ||loge(number)||
|-
|var=    ||integer(number)||
|-
|var=    ||floor(number)||
|-
|var=    ||round(number, ndecimals=0)||
|}
 
===== String Creation =====
 
{|border="1" cellpadding="10" cellspacing="0"
|var=  ||chr(integer)||
|-
|var=    ||str(instring, number)||
|-
|var=    ||space(number)||
|}
 
 
===== String Info/Search =====
 
{|border="1" cellpadding="10" cellspacing="0"
|-
|var=  ||count(instring, substr)||
|-
|var=  ||dcount(instring, substr)||
|-
|var=  ||index(instring, substr, occurrenceno=1)||
|-
|var=  ||index2(instring, substr, startcharno=1)||
|-
|var=  ||len(instring)||
|-
|var=  ||length(instring)||
|-
|if    ||match(instring, matchstr, options="")||
|-
|var=  ||seq(inchar)||
|}
 
===== String Functions =====
 
Return new and doesnt change original.
 
{|border="1" cellpadding="10" cellspacing="0"
|var= ||convert(instring, oldchars, newchars)||
|-
|var=  ||crop(instring)||
|-
|var=  ||field(instring, sepchar, fieldno, nfields=1)||
|-
|var=  ||field2(instring, sepchar, fieldno, nfields=1)||
|-
|var=  ||fieldstore(instring, sepchar, fieldno, nfields, replacementstr)||
|-
|var= ||lcase(instring)||
|-
|var=    ||ucase(instring)||
|-
|var= ||lower(instring)||
|-
|var=  ||raise(instring)||
|-
|cmd2  ||quote(instring)||
|-
|cmd2  ||squote(instring)||
|-
|cmd2  ||unquote(instring)||
|-
|var=  ||splice(instring, fromcharno, nchars, insertionstr)||
|-
|var= ||substr(instring, fromcharno)||
|-
|var= ||substr(instring, fromcharno, nchars)||
|-
|var= ||swap(instring, oldstr, newstr, options="")||
|-
|var=  ||trim(instring, trimchars=" ")||
|-
|var=  ||trimb(instring, trimchars=" ")||
|-
|var=  ||trimf(instring, trimchars=" ")||
|}
 
===== String Commands =====
 
Modify original in place
 
{|border="1" cellpadding="10" cellspacing="0"
|-
|cmd2  ||converter(io instring, oldchars, newchars)||
|-
|var=  ||cropper(io instring)||
|-
|cmd2  ||fieldstorer(io instring, sepchar, fieldno, nfields, replacementstr)||
|-
|cmd2  ||lcaser(io instring)||
|-
|var=  ||ucaser(io instring)||
|-
|cmd2  ||lowerer(io instring)||
|-
|cmd2  ||raiser(io instring)||
|-
|cmd2  ||quoter(io instring)||
|-
|cmd2  ||squoter(io instring)||
|-
|cmd2  ||unquoter(io instring)||
|-
|cmd2  ||splicer(io instring, fromcharno, nchars, insertion)||
|-
|var=  ||substrer(io instring, fromcharno)||
|-
|var=  ||substrer(io instring, fromcharno, nchars)||
|-
|cmd2  ||swapper(io instring, oldstr, newstr, options="")||
|-
|cmd2  ||trimmer(io instring, trimchars=" ")||
|-
|cmd2  ||trimmerb(io instring, trimchars=" ")||
|-
|cmd2  ||trimmerf(io instring, trimchars=" ")||
|}
 
===== iconv/oconv =====
 
{|border="1" cellpadding="10" cellspacing="0"
|var= ||oconv(instring, conversionstring)||
|-
|var= ||iconv(instring, conversionstring)||
|}
 
===== Database =====
 
{|border="1" cellpadding="10" cellspacing="0"
|if ||connect(connectionstring="")||
|-
|if ||disconnect()||
|-
|if    ||createdb(dbname, out errmsg)||
|-
|if    ||deletedb(dbname, out errmsg)||
|-
|if ||createfile(filename, options="")||
|-
|if ||deletefile(filename)||
|-
|if ||clearfile(filename)||
|-
|var= ||listfiles()||
|-
|if ||createindex(filename, fieldname, usingdictfilename="")||
|-
|if ||deleteindex(filename, fieldname)||
|-
|var= ||listindexes(filename="")||
|-
|if    ||begintrans()||
|-
|if    ||rollbacktrans()||
|-
|if    ||committrans()||
|}
 
===== Database Files and Records =====
 
{|border="1" cellpadding="10" cellspacing="0"
|if ||open(filename, out filehandle)||
|-
|if ||read(out record, filehandle, key)||
|-
|if ||matread(out dimrecord, filehandle, key)||
|-
|if ||readv(out record, filehandle, key, fieldnumber)||
|-
|if ||write(record, filehandle, key)||
|-
|if ||matwrite(in dimrecord, filehandle, key)||
|-
|if ||writev(record, filehandle, key, fieldn)||
|-
|if ||deleterecord(filehandle, key)||
|-
|if ||updaterecord(record, filehandle, key)||the record key must already exist
|-
|if ||insertrecord(record, filehandle, key)||the record key must not already exist
|-
|if    ||lock(filehandle, key)||
|-
|cmd    ||unlock(filehandle, key)||
|-
|cmd    ||unlockall()||
|}
 
===== Record Selection =====
 
{|border="1" cellpadding="10" cellspacing="0"
|if ||select(sortselectclause="")||
|-
|cmd ||clearselect()||
|-
|if ||readnext(out key)||
|-
|if ||readnext(out key, out valueno)||valueno returns multivalue numbers if your sortselectclause sorted BY-EXP on a multivalued field. Not implemented yet.
|-
|if ||selectrecord(sortselectclause="")||
|-
|if ||readnextrecord(out record, out id)||must be preceded by a selectrecord() not select()
|}
 
===== Dictionary =====
 
{|border="1" cellpadding="10" cellspacing="0"
|var= ||calculate(fieldname)||
|-
|var= ||xlate(filename, key, fieldno, mode)||
|}
 
 
===== Dynamic Array Functions =====
 
Return modified, dont change original
 
{|border="1" cellpadding="10" cellspacing="0"
|var=    ||replace(instring, fieldno, replacement)||
|-
|var= ||replace(instring, fieldno, valueno, replacement)||
|-
|var=    ||replace(instring, fieldno, valueno, subvalueno, replacement)||
|-
|var= ||extract(instring, fieldno, valueno=0, subvalueno=0)||
|-
|var= ||erase(instring, fieldno, valueno=0, subvalueno=0)||
|-
|var=  ||insert(instring, fieldno, insertion)||
|-
|var=  ||insert(instring, fieldno, valueno, insertion)||
|-
|var=  ||insert(instring, fieldno, valueno, subvalueno, insertion)||
|-
|if ||locate(instring, target, out setting, fieldn=0, valuen=0)||
|-
|if ||locateby(instring, target, ordercode, out setting, fieldn=0, valuen=0)||
|-
|if ||locateusing(instring, target, usingchar, out setting, fieldn=0, valuen=0, subvaluen=0)||
|-
|if ||locateusing(instring, target, usingchar)||
|-
|var=  ||remove(fromstr, io startx, out delimiterno)||
|-
|var= ||sum(instring, sepchar=VM_)||
|}
 
===== Dynamic Array Commands =====
 
Modify original in place
 
{|border="1" cellpadding="10" cellspacing="0"
|cmd2 ||replacer(io instring, fieldno, replacement)||
|-
|cmd2  ||replacer(io instring, fieldno, valueno, replacement)||
|-
|cmd2 ||replacer(io instring, fieldno, valueno, subvalueno, replacement)||
|-
|cmd2 ||inserter(io instring, fieldno, insertion)||
|-
|cmd2 ||inserter(io instring, fieldno, valueno, insertion)||
|-
|cmd2 ||inserter(io instring, fieldno, valueno, subvalueno, insertion)||
|-
|cmd2 ||eraser(io instring, fieldno, valueno=0, subvalueno=0)||
|}

Latest revision as of 09:13, 30 January 2025

ICONV/OCONV PATTERNS

Decimal (MD/MC)

input conversion (string) output
1234 MD2 12.34
1234 MD20 1234.00
1234 MD20, 1,234.00
1234.5678 MD2 12.35
1234.5678 MD20 1234.57
1234.5678 MD20, 1,234.57
1234 MC2 12,34
1234 MC20 1234,00
1234 MC20, 1.234,00
1234 MD20- 1234.00

Date (D)

input conversion (string) output
12345 D 18 OCT 2001
12345 D/ 10/18/2001
12345 D- 10-18-2001
12345 D2 18 OCT 01
12345 D/E 18/10/2001
12345 DS 2001 OCT 18
12345 DS/ 2001/10/18
12345 DM 10
12345 DMA OCTOBER
12345 DY 2001
12345 DY2 01
12345 DD 18
12345 DW 4
12345 DWA THURSDAY
12345 DQ 4
12345 DJ 291
12345 DL 31

Time (MT)

input conversion (string) output
234800 MT 17:13
234800 MTH 05:13PM
234800 MTS 17:13:20
234800 MTHS 05:13:20PM
0 MT 00:00
0 MTH 12:00AM
0 MTS 00:00:00
0 MTHS 12:00:00AM

Hex (HEX/MX)

input conversion (string) output
ab HEX (same as HEX8 or HEX4 depending on platform)
ab HEX8 0000006100000062
ab HEX4 00610062
ab HEX2 6162
15 MX F
254 MX FE
255 MX FF
256 MX 100
27354234 MX 1A1647A

Text (L/R/T)

input conversion (string)output
abcd L#3 abc
ab L#3 ab␣
abcd R#3 bcd
ab R#3 ␣ab
ab T#3 ab␣
abcd T#3 abc™d␣␣
42 L(0)#5 42000
42 R(0)#5 00042
42 T(0)#5 42000

Dictionaries

Exodus dictionaries enable classic multivalue database data definition. Dictionaries are just normal Exodus multivalue files that contain one record for each data column definition. You can use Exodus's edir program to manually edit dictionaries.

Dictionary file names must start with the word "dict_". For example, if you have a "books" file, then you will probably have a "dict_books" file.

You can list the contents of a dictionary by typing "list dict_filename".

Exodus Dictionary Format

0 DICTID Field/Column Code
1 DICTTYPE "F" or "S" : "F" means use Field No (i.e. raw data) and "S" means use Source Code (i.e. a function).
2 FIELDNO Field number (0=key, 1=field 1 etc for "Fields"
3 TITLE Title on reports
4 SM S or M or Mnn : "Single Value" or "Multivalue" or "Multivalue Group nn"
5 KEYPARTNO Multipart keys are separated by * characters.
6
7 CONVERSION Conversion (MD/MT/D etc.)
8 SOURCE Source Code of a subroutine to calculate the field. Multivalues are lines and the result must be placed in a variable "ANS".
9 JUST "L" or "R" or "T" requesting left, right or text justification
10 WIDTH Column Width on fixed width reports

Sort/Select Command

Exodus provides the classic multivalue sort/select command within any Exodus program followed by readnext().

Classic multivalue select/readnext functions only provide the keys of the selected records. Exodus provides the classic select/readnext and also selectrecords/readnextrecord which provides complete records instead of just keys.

The format of the select/sselect command is as follows:

 SELECT|SSELECT

 {max_number_of_records}

 {using filename}

 filename

 {datakeyvalue} ...

 {BY|BY-DSND fieldname} ...
 
 {

  WITH

  {NO|ALL|ANY}

  dict_field_id

  {
   CONTAINING|STARTING|ENDING|LIKE|EQ|NE|NOT|GT|LT|GE|LE=|<>|>|<|>=|<= value(s)
   |
   BETWEEN value AND value
  }

  {AND|OR}

 } ...

Functions and Commands

String Commands

Most string functions like trim() that return a new modified string have a corresponding modify in place command like function like trimmer() that is is usually much faster. So we have convert and converter, replace and replacer, insert and inserter and so on.

Therefore by preference use

trimmer(v1);
// or
v1.trimmer()

instead of

v1 = trim(v1);
// or
v1 = v1.trim();

Function Types

TYPE FUNCTION TYPE
var= traditional functions that return values and can be used in expressions and be on the right hand side of assignments
if traditional conditional statements that started with "if" or ended with "then/else" (or could have)
cmd traditional commands with no outputs
expr traditional commands that now have outputs and can be used in expressions

Parameters/Argument Types

in Parameters that provide data to the function. Can be variables or raw data like 1 or "X"
unspecified Same as "in". Omission of the most common type de-clutters the documentation. NB When defining your own subroutines and functions "in" cannot be omitted from the source code.
io Parameters that may provide and/or return data. Must be variables. Cannot be raw data like 1 or "X"
out Parameters that return data. Must be variables. Cannot be raw data like 1 or "X"

Optional Parameters

Key Default
= "" ""
= " " " "
= "." "."
= 1 1
= 0 0
= true true
= false false

Field mark characters

Exodus implements a PICK OS data structure called a "dynamic array". This is simply any string which uses six specific unprintable ASCII delimiter characters (\x1A to \x1F) to separate its various parts. The parts are referred to as records, fields, values, subvalues, text, and subtext and fall within each other.

Dynamic arrays therefore implement sparse six dimensional arrays.

Typical CPU caching architecture favours similar values being adjacent in memory therefore implementing them as strings of values separated by delimiter characters can have performance advantages over more complex structures.

In practice the vast majority of dynamic arrays consist of "fields" separated by the FM character (\x1E) but it is very common for fields to have values separated by the VM character (\x1D) and values to have subvalues using SM (\x1D).

Since the six delimiter characters fall in the unprintable character range certain other characters have been designated as usable for coding and printing. For example the FM character is represented as ^ and can be entered in source code appended with _var to indicate that the string must be converted to internal format.

var v1 = "f1^f2^f3"_var; // Three fields
var v2 = "f1^v1]v2]v3^f3"_var; // Three fields, 2nd field has 3 values. It is "multivalued".

Anything which contains a collection of fields can be considered as a "record" and records can be stored in files with a unique primary key. The fields might represent different columns of a traditional database table. So anonymous field number 1 might be a contact name, field 2 the contact address, field 3 a multivalued list of contact points. etc.

Delimiter
name
var Hex Display cstr " " char ' '
Record Mark RM \x1F ` _RM RM_
Field Mark FM \x1E ^ _FM FM_
Value Mark VM \x1D ] _VM VM_
Subvalue Mark SM \x1C } _SM SM_
Text Mark TM \x1B | _TM TM_
Subtext Mark STM \x1A ~ _STM STM_
Delimiter Name : Record Mark Field Mark Value Mark Subvalue Mark Text Mark Subtext Mark
var : RM FM VM SM TM STM
Display : ` ^ ] } | ~
Hex : \x1F \x1E \x1D \x1C \x1B \x1A
cstr " " : _RM _FM _VM _SM _TM _STM
char ' ' : RM_ FM_ VM_ SM_ TM_ STM_

Complete List of Functions

Complete List of Functions