Results 1 to 23 of 23

Thread: Ultimate Type Tutorial

  1. #1
    Join Date
    Dec 2006
    Location
    Sydney, New South Wales, Australia
    Posts
    4,097
    Mentioned
    15 Post(s)
    Quoted
    42 Post(s)

    Lightbulb Ultimate Type Tutorial

    Ultimate Type Tutorial
    By Daniel

    Introduction:
    In this tutorial, i'll be showing you as to what should be common knowledge, plus a little more Everything in here will take you from (if you're a complete beginner scripter) nothing to an intermediate scripter right away (well, that's what i think anyway). I tried to make it quite simple to grasp If you need any help, please reply to this thread with your question and it'll happily be answered. Also, adding to my reputation (by pressing the blue tick at the top right of this, or any other, post of mine) let's me know that you enjoy my tutorials and i'll keep writing more

    Contents:

    About Types:
    A type is essentially a name for a kind of data. When you declare a variable you must specify it's type, which determines the set of values the variable can hold and the operations that can be performed in it. Every expression returns data of a particular type, as does every function. Some (if not most) functions and procedures require parameters of specific types.

    There are several ways to categorized types:
    • Some types are predefined (or built-in); the compiler recognizes these automatically, without the need for a declaration. Almost all of the types documented in this language reference are predefined. Other types are created by declaration; these include user-defined types.
    • Types can be classified as either fundamental or generic. The range and format of a fundamental type is the same in all implementations of the Delphi/Pascal (SCAR-like) language, regardless of the CPU and operating system. The range and format of a generic type is platform-specific and could vary across different systems. Most predefined types are fundamental, but a handful of integer, character, string, and pointer types are generic.
    • Types can be classified as simple, string, structured, pointer, procedural, or variant. In addition, type identifiers themselves can be regarded as belonging to a special 'type' because they can be passed as parameters to certain functions (such as High, Low, Length and SizeOf).
    Last edited by Daniel; 02-27-2011 at 07:19 AM.

  2. #2
    Join Date
    Dec 2006
    Location
    Sydney, New South Wales, Australia
    Posts
    4,097
    Mentioned
    15 Post(s)
    Quoted
    42 Post(s)

    Default

    Simple Types:
    Ordinal Types:
    Ordinal types include integer, character, Boolean, enumerated, and subrange types. An ordinal type defines an ordered set of values in which each value except the first has a unique predecessor and each value except the last has a unique successor. Further, each value has an ordinality which determines the ordering of the type. In most cases, if a value has ordinality n, its predecessor has ordinality n-1 and its successor has ordinality n+1.

    • For integer types, the ordinality of a value is the value itself.
    • Subrange types maintain the ordinalities of their base types.
    • For other ordinal types, by default the first value has ordinality 0, the next value has ordinality 1, and so forth. The declaration of an enumerated type can explicitly override this default.


    Several predefined functions operate on ordinal values and type identifiers. The most important of them are summarized below.



    The standard procedures Inc and Dec increment and decrement the value of an ordinal variable. For example, Inc(I) is equivalent to SetLength(i, Length(i) + 1) and, if I is an integer variable, to I := I + 1.

    Integer Types:
    An integer type represents a subset of the whole numbers. The generic integer types are Integer and Cardinal; use these whenever possible, since they result in the best performance for the CPU and operating system. The table below gives their ranges and storage formats for the SCAR compiler.

    Generic Integer Types:


    Fundemental Integer Types:
    Fundamental integer types include Shortint, Smallint, Longint, Int64, Byte, Word and LongWord.



    Note: Some standard routines that take integer arguments truncate Int64
    values to 32 bits. However, the High, Low, Inc, Dec and IntToStr routines fully support Int64 arguments. Also, the Round, Trunc and StrToInt64functions return Int64 values. A few routines cannot take Int64 values at all.

    Character Types:
    The fundamental character types are Char and WideChar. Char values are byte-sized (8-bit) characters ordered according to the locale character set which is possibly multibyte.

    WideChar characters use more than one byte to represent every character. In the current implementations, WideChar is word-sized (16-bit) characters ordered according to the Unicode character set.

    Boolean Types:
    The four predefined Boolean types are Boolean, ByteBool, WordBool, and LongBool. Boolean is the preferred type. The others exist to provide compatibility with other languages and operating system libraries.

    A Boolean variable occupies one byte of memory, a ByteBool variable also occupies one byte, a WordBool variable occupies two bytes (one word), and a LongBool variable occupies four bytes (two words).

    Boolean values are denoted by the predefined constants True and False. The following relationships hold:



    A value of type ByteBool, LongBool, or WordBool is considered True when its ordinality is not 0. If such a value appears in a context where a Boolean is expected, the compiler automatically converts any value of a non-0 ordinality to True.

    The previous remarks refer to the ordinality of Boolean values, not to the values themselves. In SCAR, Boolean expressions cannot be equated with integers or reals. Hence, if X is an integer variable, the statement:
    scar Code:
    if(X) then
    generates a compilation error. Changing the variable to a Boolean type is unreliable, but each of the following alternatives will work:
    scar Code:
    if X <> 0 then ...; { use longer expression that returns Boolean value }
             
    var OK: Boolean;
     ...
    OK := X <> 0;
    if OK then ...;

    Enumerated Types:
    An enumerated type defines an ordered set of values by simply listing identifiers that denote these values. The values have no inherent meaning. To declare an enumerated type, use the syntax:
    type
    TypeName = (Value1, Value2...)

    where TypeName and each Value (Value1 and Value2, etc) are valid identifiers. For example, the declaration:
    type
    CardSuit = (Club, Diamond, Heart, Spade);

    defines an enumerated type called CardSuit whose possible values are Club, Diamond, Heart, and Spade, where Ord(Club) returns 0, Ord(Diamond) returns 1, and so forth. An example of this can be:
    scar Code:
    type
      CardSuit = (Club, Diamond, Heart, Spade);
    var
      s: CardSuit;
    begin
      s := Spade;
      Writeln(Ord(s));
    end.
    When you declare an enumerated type, you are declaring each Value to be a constant of type TypeName. If the Value identifiers are used for another purpose within the same scope, naming conflicts occur. For example, suppose you declare the type:type TypeName= (High, Low);
    Unfortunately, High and Low are also the names of predefined functions. So, if you do something similar to:
    scar Code:
    type
      TypeName = (High, Low);
    var
      TN: TypeName;
    begin
      TN := High;
    end.
    you'll get a compilation error.

    A better solution, however, is to choose constant names that are not likely to conflict with other identifiers. Examples:
    type
    TypeName = (tnHigh, tnLow);


    You can use the (Value1, Value2, etc) construction directly in variable declarations, as if it were a type name, examples:
    var
    MyCardSuits: (Club, Diamond, Heart, Spade);

    var
    MyCards1: (Club, Diamond, Heart, Spade);
    MyCards2: (Club, Diamond, Heart, Spade);

    var
    MyCards1, MyCards2: (Club, Diamond, Heart, Spade);


    Real Types:
    A real type defines a set of numbers that can be represented with floating-point notation. The table below gives the ranges and storage formats for the fundamental real types on the Windows operating systems:



    NOTE: Currency is a fixed-point data type that minimizes rounding errors in monetary calculations. On the Win32 platform, it is stored as a scaled 64-bit integer with the four least significant digits implicitly representing decimal places. When mixed with other real types in assignments and expressions, Currency values are automatically divided or multiplied by 10000.
    Last edited by Daniel; 07-17-2009 at 09:58 AM.

  3. #3
    Join Date
    Dec 2006
    Location
    Sydney, New South Wales, Australia
    Posts
    4,097
    Mentioned
    15 Post(s)
    Quoted
    42 Post(s)

    Default

    String Types:
    A string represents a sequence of characters. SCAR supports the following predefined string types:



    String types can be mixed in assignments and expressions; the compiler automatically performs required conversions. But strings passed by reference to a function or procedure (as var and out parameters) must be of the appropriate type. Strings can be explicitly cast to a different string type. However, casting a multi-byte string to a single byte string may result in data loss.

    The reserved word string functions like a general string type identifier. For example:
    var s: String;
    creates a variable S that holds a string. On the Windows operating system, the compiler interprets string (when it appears without a bracketed number after it) as UnicodeString.

    Note that the keyword string is also used when declaring ShortString types of specific lengths (see Short Strings, below).

    The standard function Length returns the number of characters in a string. The SetLength procedure adjusts the length of a string. Note that the SizeOf function returns the number of bytes in a string, so SizeOf may return a different result than Length.

    Comparison of strings is defined by the ordering of the characters in corresponding positions. Between strings of unequal length, each character in the longer string without a corresponding character in the shorter string takes on a greater-than value. For example, 'AB' is greater than 'A'; that is, 'AB' > 'A' returns True. Zero-length strings represent the lowest values.

    You can index a string variable just as you would an array. If S is a non-UnicodeString string variable and i an integer expression, S[i] represents the ith byte in S, which may not be the ith character or an entire character at all. However, indexing a UnicodeString variable does result in a character. For a ShortString or AnsiString, S[i] is of type AnsiChar; for a WideString, S[i] is of type WideChar. For single-byte (Western) locales, MyString[2] := 'A'; assigns the value A to the second character of MyString.

    You can assign the value of a string constant - or any other expression that returns a string - to a variable. The length of the string changes dynamically when the assignment is made. Examples:
    scar Code:
    MyString := 'Hello world!';
    MyString := 'Hello' + 'world';
    MyString := MyString + '!';
    MyString := ' '; //Space
    MyString := ''//Empty String
     

    Short Strings:
    A ShortString is 0 to 255 single-byte characters long. While the length of a ShortString can change dynamically, its memory is a statically allocated 256 bytes; the first byte stores the length of the string, and the remaining 255 bytes are available for characters. If S is a ShortString variable, Ord(S[0]), like Length(S), returns the length of S; assigning a value to S[0], like calling SetLength, changes the length of S.

    When you assign a value to a short-string variable, the string is truncated if it exceeds the maximum length for the type.

    The standard functions High and Low operate on short-string type identifiers and variables. High returns the maximum length of the short-string type, while Low returns zero.

    Long Strings:
    AnsiString, also called a long string, represents a dynamically allocated string whose maximum length is limited only by available memory.

    A long-string variable is a structure containing string information. When the variable is empty - that is, when it contains a zero-length string, the pointer is nil and the string uses no additional storage. When the variable is nonempty, it points to a dynamically allocated block of memory that contains the string value. This memory is allocated on the heap, but its management is entirely automatic and requires no user code. The AnsiString structure contains a 32-bit length indicator, a 32-bit reference count, a 16 bit data length indicating the number of bytes per character, and a 16 bit code page.

    Although it prefers single byte data, an AnsiString variable can also contain Unicode data.

    Because long-string variables have pointers, two or more of them can reference the same value without consuming additional memory. The compiler exploits this to conserve resources and execute assignments faster. Whenever a long-string variable is destroyed or assigned a new value, the reference count of the old string (the variable's previous value) is decremented and the reference count of the new value (if there is one) is incremented; if the reference count of a string reaches zero, its memory is deallocated. This process is called reference-counting. When indexing is used to change the value of a single character in a string, a copy of the string is made if - but only if - its reference count is greater than one. This is called copy-on-write semantics.

    UnicodeString:
    The UnicodeString type represents a dynamically allocated Unicode string whose maximum length is limited only by available memory.

    With a single-byte character set (SBCS), each byte in a string represents one character. In a multibyte character set (MBCS), some characters are represented by one byte and others by more than one byte. Multibyte character sets - especially double-byte character sets (DBCS) - are widely used for Asian languages.

    Unicode is a set of multibyte character encodings. Unicode characters and strings are also called wide characters and wide character strings.

    The Windows operating system supports single-byte and multibyte character sets as well as Unicode. The Windows operating system supports Unicode UCS-2.

    In a Unicode character set, each character is represented by one or more bytes. Thus a Unicode string is a sequence not of individual bytes but of multi-byte words. The character size depends on the type of Unicode encoding.

    In UTF-8. for instance, characters may be one to 4 bytes. In UTF-8, the first 128 Unicode characters map to the US-ASCII characters.

    The UnicodeString type has exactly the same structure as the AnsiString type. UnicodeString data is encoded in UTF-16.

    Although it prefers Unicode data, a UnicodeString variable can also contain ANSI string data.

    Since UnicodeString and AnsiString have the same structure, they function very similarly. When a UnicodeString variable is empty, it uses no additional memory. When it is not empty, it points to a dynamically allocated block of memory that contains the string value, and the memory handling for this is transparent to the user. UnicodeString variables are reference counted, and two or more of them can reference the same value without consuming additional memory.

    Instances of UnicodeString can index characters. Indexing is 1-based, just as for AnsiString.

    UnicodeString is assignment compatible with all other string types. However, assignments between AnsiString and UnicodeString do the appropriate up or down conversions. Note that assigning a UnicodeString type to an AnsiString type is not recommended and can result in data loss.
    Last edited by Daniel; 07-15-2009 at 05:05 PM.

  4. #4
    Join Date
    Dec 2006
    Location
    Sydney, New South Wales, Australia
    Posts
    4,097
    Mentioned
    15 Post(s)
    Quoted
    42 Post(s)

    Default

    Pointer Types:
    A pointer is a variable that denotes a memory address. When a pointer holds the address of another variable, we say that it points to the location of that variable in memory or to the data stored there. In the case of an array or other structured type, a pointer holds the address of the first element in the structure. If that address is already taken, then the pointer holds the address to the first element.

    Pointers are typed to indicate the kind of data stored at the addresses they hold. The general-purpose Pointer type can represent a pointer to any data, while more specialized pointer types reference only specific types of data. Pointers occupy four bytes of memory.

    To see how pointer work, look at the following example:
    scar Code:
    var
      D, A, N: Integer;
     
    begin
      D := 10;
      A := ___Pointer(D);
      N := A;
      Writeln(IntToStr(N));
    end.

    Line 2 declares D, A and N as integer variables. Line 5 assigns the value to D, then line 6 points A to the value of D then line 7 equals the value of A which equals the value of D. After this executes, D, A and N have the same value as one another.

    My example may seem like a roundabout way of copying the value of one variable to another - something that we could have accomplished with a simple assignment statement. But pointers are useful for several reasons:
    • Any data type that requires large, dynamically allocated blocks of memory use pointers.
    • Long-string variables, for instance, are implicitly pointers, as are class instance variables. Moreover, some advanced programming techniques require the use of pointers.
    Last edited by Daniel; 07-15-2009 at 05:45 PM.

  5. #5
    Join Date
    Dec 2006
    Location
    Sydney, New South Wales, Australia
    Posts
    4,097
    Mentioned
    15 Post(s)
    Quoted
    42 Post(s)

    Default

    Procedural Types:
    Procedural types allow you to treat procedures and functions as values that can be assigned to variables or passed to other procedures and functions. For example, suppose you define a function called Calc that takes two integer parameters and returns an integer:
    function Calc(X, Y: Integer): Integer;
    You can assign the Calc function to the variable F:
    var F: function(X, Y: Integer): Integer;
    If you take any procedure or function heading and remove the identifier after the word procedure or function, what's left is the name of a procedural type. You can use such type names directly in variable declarations (as in the previous example) or to declare new types:
    scar Code:
    type
      TIntegerFunction = function: Integer;
      TProcedure = procedure;
      TStrProc = procedure(const S: string);
      TMathFunc = function(X: Double): Double;
    var
      F: TIntegerFunction;
      Proc: TProcedure;
      SP: TStrProc;
      M: TMathFunc;
    procedure FuncProc(P: TIntegerFunction);

    Two procedural types are compatible if they have:
    • the same calling convention
    • the same return value (or no return value)
    • the same number of parameters, with identically typed parameters in corresponding positions. (Parameter names do not matter.)


    Procedural Types in Statements and Expressions:
    When a procedural variable is on the left side of an assignment statement, the compiler expects a procedural value on the right. The assignment makes the variable on the left a pointer to the function or procedure indicated on the right. In other contexts, however, using a procedural variable results in a call to the referenced procedure or function. You can even use a procedural variable to pass parameters:
    scar Code:
    var
      F: function(X: Integer): Integer;
      I: Integer;
      function SomeFunction(X: Integer): Integer;
        ...
      F := @SomeFunction;    // assign SomeFunction to F
      I := F(4);            // call function; assign result to I
     

    In assignment statements, the type of the variable on the left determines the interpretation of procedure or method pointers on the right. For example:
    scar Code:
    var
      F, G: function: Integer;
      I: Integer;
      function SomeFunction: Integer;
        ...
      F := @SomeFunction;      // assign SomeFunction to F
      G := F();                 // copy F to G
      I := G;                 // call function; assign result to I
     

    The first statement assigns a procedural value to F. The second statement copies that value to another variable. The third statement makes a call to the referenced function and assigns the result to I. Because I is an integer variable, not a procedural one, the last assignment actually calls the function (which returns an integer).

    In some situations it is less clear how a procedural variable should be interpreted. Consider the statement:
    scar Code:
    if(F() = MyFunction) then
    In this case, the occurrence of F results in a function call; the compiler calls the function pointed to by F, then calls the function MyFunction, then compares the results. The rule is that whenever a procedural variable occurs within an expression, it represents a call to the referenced procedure or function. In a case where F references a procedure (which doesn't return a value), or where F references a function that requires parameters, the previous statement causes a compilation error.

    Any procedural variable can hold the value nil, which means that it points to nothing. But attempting to call a nil-valued procedural variable is an error.

    NOTE: When pointing to an expression, always include the @ symbol before the identifier. When calling the procedural expression, disclude the @ symbol and add parenthesis'.
    Last edited by Daniel; 07-15-2009 at 06:24 PM.

  6. #6
    Join Date
    Dec 2006
    Location
    Sydney, New South Wales, Australia
    Posts
    4,097
    Mentioned
    15 Post(s)
    Quoted
    42 Post(s)

    Default

    Working With Variants:
    Sometimes it is necessary to manipulate data whose type varies or cannot be determined at compile time. In these cases, one option is to use variables and parameters of type Variant, which represent values that can change type at runtime. Variants offer greater flexibility but consume more memory than regular variables, and operations on them are slower than on statically bound types. Moreover, illicit operations on variants often result in runtime errors, where similar mistakes with regular variables would have been caught at compile time.

    By default, Variants can hold values of any type except records, sets, static arrays, files, classes, class references, and pointers. In other words, variants can hold anything but structured types and pointers. They can hold interfaces, whose methods and properties can be accessed through them. They can hold dynamic arrays, and they can hold a special kind of static array called a variant array. Variants can mix with other variants and with integer, real (extended), string, and Boolean values in expressions and assignments; the compiler automatically performs type conversions.

    Variants that contain strings cannot be indexed. That is, if V is a variant that holds a string value, the construction V[1] causes a runtime error.

    A variant occupies 16 bytes of memory and consists of a type code and a value, or pointer to a value, of the type specified by the code. All variants are initialized on creation to the special value Unassigned. The special value Null indicates unknown or missing data.

    The standard function VarType returns a variant's type code. The varTypeMask constant is a bit mask used to extract the code from VarType's return value, so that, for example:
    VarType(V) and varTypeMask = varDouble

    ...returns True if V contains a Double or an array of Double. (The mask simply hides the first bit, which indicates whether the variant holds an array.)

    Variant Type Conversions:
    All integer, real, string, character, and Boolean types are assignment-compatible with Variant. The following code demonstrates the use of variants and some of the automatic conversions performed when variants are mixed with other types:
    scar Code:
    var
       V1, V2, V3, V4, V5: Variant;
       I: Integer;
       D: Double;
       S: string;
       begin
          V1 := 1;         //Integer value
          V2 := 1234.5678; //Real Value
          V3 := 'Hello world!'; //String Value
          V4 := '1000';         //String Value
          V5 := V1 + V2 + V4;   //Real value 2235.5678
          I  := V1;             //I = 1 (integer value)
          D  := V2;            //D = 1234.5678 (real value)
          S  := V3;            //S = 'Hello world!' (string value)
          I  := V4;             //I = 1000 (integer value)
          S  := V5;            //S = '2235.5678' (string value)
       end;

    The compiler performs type conversions according to the following rules:


    Special conversion rules apply to the TDateTime type. When a TDateTime is converted to any other type, it treated as a normal Double. When an integer, real, or Boolean is converted to a TDateTime, it is first converted to a Double, then read as a date-time value. When a string is converted to a TDateTime, it is interpreted as a date-time value using the regional settings. When an Unassigned value is converted to TDateTime, it is treated like the real or integer value 0. Converting a Null value to TDateTime raises an error.

    Variants in Expressions:
    Except for comparisons, which always return a Boolean result, any operation on a variant value returns a variant result. If an expression combines variants with statically-typed values, the statically-typed values are automatically converted to variants.

    This is not true for comparisons, where any operation on a Null variant produces a Null variant. For example:
    V := Null + 3;
    ...assigns a Null variant to V. By default, comparisons treat the Null variant as a unique value that is less than any other value. For example:
    if Null > -3 then ... else ...;
    In this example, the else part of the if statement will be executed.

    Variant Arrays:
    You cannot assign an ordinary static/dynamic array to a variant. Instead, create a variant array by declaring the variable as a TVariantArray instead. For example:
    var
    V: TVariantArray;

    ...declares a new array of Variants

    TVariantArrays are exactly the same as a normal Variant, except can store more than one value (hence, being an array). For more information on arrays, check out the array section in Structured Types (below).
    Last edited by Daniel; 07-16-2009 at 03:55 PM.

  7. #7
    Join Date
    Dec 2006
    Location
    Sydney, New South Wales, Australia
    Posts
    4,097
    Mentioned
    15 Post(s)
    Quoted
    42 Post(s)

    Default

    Declaring Types:
    A type declaration specifies an identifier that denotes a type. The syntax for a type declaration is:
    type TMyString = String;
    ...you can make the variable decleration:
    var s: TMyString;
    A type identifier's scope doesn't include the type declaration itself. So you cannot, for example, define a record type that uses itself recursively.

    When you declare a type that is identical to an existing type, the compiler treats the new type identifier as an alias for the old one. Thus, given the declarations:
    scar Code:
    type TValue = Double;
    var
      X: Single;
      Y: TValue;
    X and Y are of the same type; at runtime, there is no way to distinguish TValue from a real type (in this case, Single). This is usually of little consequence, but if your purpose in defining a new type is to utilize runtime type information, for example, to associate a property editor with properties of a particular type - the distinction between 'different name' and 'different type' becomes important.
    Last edited by Daniel; 07-20-2009 at 08:48 PM.

  8. #8
    Join Date
    Dec 2006
    Location
    Sydney, New South Wales, Australia
    Posts
    4,097
    Mentioned
    15 Post(s)
    Quoted
    42 Post(s)

    Default

    Structured Types:
    Instances of a structured type hold more than one value. Structured types include arrays and records.. A type can have unlimited levels of structuring.

    Arrays:
    An array represents an indexed collection of elements of the same type (called the base type). Because each element has a unique index, arrays, unlike sets, can meaningfully contain the same value more than once. Arrays can be allocated statically or dynamically.

    Static Arrays:
    Static arrays have a fixed size or length:
    array[indexType1..indexType2] of baseType;
    ...where each indexType is an ordinal type whose range does not exceed 2GB. Since the indexTypes index the array, the number of elements an array can hold is limited by the product of the sizes of the indexTypes. indexTypes are Integers.

    In the simplest case of a one-dimensional array, there is only a single indexType. For example:
    var MyArray: array [1..100] of Char;
    declares a variable called MyArray that holds an array of 100 character values. Given this declaration, MyArray[3] denotes the third character in MyArray. If you create a static array but don't assign values to all its elements, the unused elements are still allocated and contain random data; they are like uninitialized variables.

    A multidimensional array is an array of arrays. For example:
    type TMatrix = array[1..10] of array[1..50] of Single;

    TMatrix represents an array of 500 real (in this case, Single) values. A variable MyMatrix of type TMatrix can be indexed like this: MyMatrix[2][45].

    The standard functions Low and High operate on array type identifiers and variables. They return the low and high bounds of the array's first index type. The standard function Length returns the number of elements in the array's first dimension.

    Dynamic Arrays:
    Dynamic arrays do not have a fixed size or length. Instead, memory for a dynamic array is reallocated when you assign a value to the array or pass it to the SetLength or SetArrayLength procedure. For example:
    var MyFlexibleArray: array of Single;
    ...declares a one-dimensional dynamic array of singles. The declaration does not allocate memory for MyFlexibleArray. To create the array in memory, call SetLength. For example, given the previous declaration:
    SetLength(MyFlexibleArray, 20);

    or
    SetArrayLength(MyFlexibleArray, 20);

    ...allocates an array of 20 reals, indexed 0 to 19. Dynamic arrays are always integer-indexed, always starting from 0.

    If X and Y are variables of the same dynamic-array type, X := Y points X to the same array as Y (There is no need to allocate memory for X before performing this operation). For example, after this code executes:
    scar Code:
    var
      A, B: array of Integer;
      begin
        SetLength(A, 1);
        A[0] := 1;
        B := A;
        B[0] := 2;
      end;
    the value of A[0] is 2 (If A and B were static arrays, A[0] would still be 1).

    Assigning to a dynamic-array index (for example, MyFlexibleArray[2] := 7) does not reallocate the array. Out-of-range indexes are not reported at compile time.

    When dynamic-array variables are compared, their references are compared, not their array values. Thus, after execution of the code:
    scar Code:
    var
      A, B: array of Integer;
      begin
         SetLength(A, 1);
         SetLength(B, 1);
         A[0] := 2;
         B[0] := 2;
      end;
    A = B returns False but A[0] = B[0] returns True.

    Once a dynamic array has been allocated, you can pass it to the standard functions Length, High, and Low. Length returns the number of elements in the array, High returns the array's highest index (that is, Length - 1), and Low returns 0. In the case of a zero-length array, High returns -1 (with the anomalous consequence that High < Low).

    Note: In some function and procedure declarations, array parameters are represented as array of baseType, without any index types specified. For example, function CheckStrings(A: array of String): Boolean;
    This indicates that the function operates on all arrays of the specified base type, regardless of their size, how they are indexed, or whether they are allocated statically or dynamically.

    Multidimensional Dynamic Arrays:
    To declare multidimensional dynamic arrays, use iterated array of ... constructions. For example:
    type TMessageGrid = array of array of string;
    var Msgs: TMessageGrid;

    ...declares a two-dimensional array of strings.

    You can create multidimensional dynamic arrays that are not rectangular. The first step is to call SetLength, passing it parameters for the first n dimensions of the array. For example:
    var Ints: array of array of Integer;
    SetLength(Ints,10);

    allocates ten rows for Ints but no columns. Later, you can allocate the columns one at a time (giving them different lengths); For example:
    SetLength(Ints[2], 5);
    makes the third column of Ints five integers long. At this point (even if the other columns haven't been allocated) you can assign values to the third column - for example, Ints[2][4] := 6.

    Records:
    A record represents a heterogeneous set of elements. Each element is called a field; the declaration of a record type specifies a name and type for each field. The syntax of a record type declaration is:
    scar Code:
    type
      recordTypeName = record
        fieldList1: Integer;
            ...
        fieldListn: String;
      end;
    where recordTypeName is a valid identifier, each type denotes a type, and each fieldList is a valid identifier or a comma-delimited list of identifiers. The final semicolon is optional.

    For example, the following declaration creates a record type called TDateRec:
    scar Code:
    type
      TDateRec = record
        Year: Integer;
        Month: (Jan, Feb, Mar, Apr, May, Jun,
                Jul, Aug, Sep, Oct, Nov, Dec);
        Day: String;
      end;

    Each TDateRec contains three fields: an integer value called Year, a value of an enumerated type called Month, and another integer between 1 and 31 called Day. The identifiers Year, Month, and Day are the field designators for TDateRec, and they behave like variables. The TDateRec type declaration, however, does not allocate any memory for the Year, Month, and Day fields; memory is allocated when you instantiate the record, like this:
    var Record1, Record2: TDateRec;

    This variable declaration creates two instances of TDateRec, called Record1 and Record2.

    You can access the fields of a record by qualifying the field designators with the record's name:
    scar Code:
    Record1.Year := 1904;
    Record1.Month := Jun;
    Record1.Day := 16;
    Or use a with statement:
    scar Code:
    with Record1 do
     begin
        Year := 1904;
        Month := Jun;
        Day := 16;
     end;

    You can now copy the values of Record1's fields to Record2:
    Record2 := Record1;

    Instead of defining record types, you can use the record construction directly in variable declarations:
    scar Code:
    var S: record
          Name: string;
          Age: Integer;
        end;

    However, a declaration like this largely defeats the purpose of records, which is to avoid repetitive coding of similar groups of variables. Moreover, separately declared records of this kind will not be assignment-compatible, even if their structures are identical.
    Last edited by Daniel; 07-16-2009 at 07:56 AM.

  9. #9
    Join Date
    Dec 2006
    Location
    Sydney, New South Wales, Australia
    Posts
    4,097
    Mentioned
    15 Post(s)
    Quoted
    42 Post(s)

    Default

    Variables:
    A variable is an identifier whose value can change at runtime. Put differently, a variable is a name for a location in memory; you can use the name to read or write to the memory location. Variables are like containers for data, and, because they are typed, they tell the compiler how to interpret the data they hold.

    The basic syntax for a variable declaration is
    var identifierList:type;

    ...where identifierList is a comma-delimited list of valid identifiers and type is any valid type. For example:
    var I: Integer;

    ...declares a variable I of type Integer, while:
    var X, Y: Double;


    declares two variables - X and Y - of type Real.

    Consecutive variable declarations do not have to repeat the reserved word var:
    scar Code:
    var
       X, Y, Z: Double;
       I, J, K: Integer;
       Okay: Boolean;

    Variables declared within a procedure or function are sometimes called local, while other variables are called global. Global variables can be initialized at the same time they are declared.

    If you don't explicitly initialize a local or global variable, the compiler initializes it to 0.

    When you declare a variable, you are allocating memory which is freed automatically when the variable is no longer used. In particular, local variables exist only until the program exits from the function or procedure in which they are declared.
    Last edited by Daniel; 07-16-2009 at 07:57 AM.

  10. #10
    Join Date
    Dec 2006
    Location
    Sydney, New South Wales, Australia
    Posts
    4,097
    Mentioned
    15 Post(s)
    Quoted
    42 Post(s)

    Default

    Putting It All Together:
    scar Code:
    type
      Box = record
        X1, Y1, X2, Y2: Integer;
      end;

      BoxArray = array of Box;
      UpDown = (Up, Down);
      UDArray = array[1..2] of UpDown;
     
    var
      v: Variant;
      i: function(X, Y: Integer): Integer;
      b: array[0..1] of BoxArray;
      bI: Integer;
     
    function New(a, b: Integer): Integer;
    begin
      Result := Round(Int(a - b));
    end;

    begin
      ClearDebug;

      v := '1500';
      i := @New;
     
      SetArrayLength(b[0], 1);
      SetArrayLength(b[1], 2);
     
      repeat
     
        b[0][0].X1 := Random(1501);
        b[1][0].X2 := Random(3000);
        b[1][1].Y1 := Random(2000);

        if(i(b[0][0].X1, b[1][1].Y1) <> v) then
          Writeln('Not 1500') else
            Writeln('Is 1500 :-(');
           
        IncEx(bI, High(b) + Random(3));
       
      Until(bI >= 5);
    end.

    Post a script, which applies almost everything that you learned from this tutorial, and let others see what l33t (awesome) SCAR scripting skills you can do
    Last edited by Daniel; 07-15-2009 at 08:13 PM.

  11. #11
    Join Date
    Jun 2007
    Location
    Wednesday
    Posts
    2,460
    Mentioned
    1 Post(s)
    Quoted
    0 Post(s)

    Default

    I reserve 11!

    In the Enumerated type bit, you failed with your tags

    [font="Courier New"]type TypeName= (High, Low);[FONT]

    needs a / for the closing tag silly

    Also, none of the areas look like type casting would fit - I hope you don't forget it since it's not really the ultimate type tutorial if it doesn't have it

    Edit:Structured types section, High returns -1 when a dynamic arrays length is 0 silly, not 1
    Last edited by mixster; 07-15-2009 at 09:05 PM.
    By reading this signature you agree that mixster is superior to you in each and every way except the bad ways but including the really bad ways.

  12. #12
    Join Date
    Dec 2006
    Location
    Sydney, New South Wales, Australia
    Posts
    4,097
    Mentioned
    15 Post(s)
    Quoted
    42 Post(s)

    Default

    Quote Originally Posted by mixster View Post
    I reserve 11!

    In the Enumerated type bit, you failed with your tags

    [font="Courier New"]type TypeName= (High, Low);[FONT]

    needs a / for the closing tag silly

    Also, none of the areas look like type casting would fit - I hope you don't forget it since it's not really the ultimate type tutorial if it doesn't have it
    Sorry, i'm trying to write it out as quick and as best as i can and i can screw up the tags sometimes

    I might add Type Casting later or at the end of the tutorial, who knows.

    And thanks, <3

  13. #13
    Join Date
    Jan 2008
    Location
    NC, USA.
    Posts
    4,435
    Mentioned
    0 Post(s)
    Quoted
    2 Post(s)

    Default

    Wonderfull tutorial
    Rep'd
    Quote Originally Posted by irc
    [00:55:29] < Guest3097> I lol at how BenLand100 has become noidea
    [01:07:40] <@BenLand100> i'm not noidea i'm
    [01:07:44] -!- BenLand100 is now known as BenLand42-
    [01:07:46] <@BenLand42-> shit
    [01:07:49] -!- BenLand42- is now known as BenLand420
    [01:07:50] <@BenLand420> YEA

  14. #14
    Join Date
    Mar 2007
    Posts
    4,813
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

  15. #15
    Join Date
    Oct 2007
    Location
    #srl
    Posts
    5,991
    Mentioned
    15 Post(s)
    Quoted
    10 Post(s)

    Default

    Quote Originally Posted by NaumanAkhlaQ View Post
    Good tutorial, but should be in intermediate as a beginner won't understand
    Hard to say for sure. Some of it belongs in Beginner but alot in Intermediate as well.

    Great tut though!
    ~
    SRL6| Git |SRL5
    ~



  16. #16
    Join Date
    Dec 2006
    Location
    Sydney, New South Wales, Australia
    Posts
    4,097
    Mentioned
    15 Post(s)
    Quoted
    42 Post(s)

    Default

    Quote Originally Posted by noidea View Post
    Wonderfull tutorial
    Rep'd
    Thanks

    Quote Originally Posted by NCDS View Post
    Hard to say for sure. Some of it belongs in Beginner but alot in Intermediate as well.

    Great tut though!
    Quote Originally Posted by NaumanAkhlaQ View Post
    Good tutorial, but should be in intermediate as a beginner won't understand
    Was it getting a bit intermediate near the end? Like after the Variant area? If that's the case, it's because i was getting a bit tired near the end, but wanting to complete it as quick as possible. Also, some of the words i got from the Thesaurus synonym dictionary to make me sound more pro



    Glad you guys liked it.

  17. #17
    Join Date
    Jul 2007
    Location
    Norway.
    Posts
    1,957
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

  18. #18
    Join Date
    May 2007
    Location
    UK
    Posts
    4,008
    Mentioned
    1 Post(s)
    Quoted
    11 Post(s)

    Default

    Great tut,
    Rep +

    T~M

  19. #19
    Join Date
    May 2007
    Location
    Sydney, Australia (Faggot Region)
    Posts
    1,446
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    You asked me to look at a tutorial you wrote not an ULTIMATE TUTORIAL!
    Good Work!


  20. #20
    Join Date
    Jul 2008
    Location
    Canada
    Posts
    1,617
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    GAH, never finished the whole thing.

    Great tutorial, but massive!


    ^^BookMarked^^

  21. #21
    Join Date
    Dec 2006
    Location
    Sydney, New South Wales, Australia
    Posts
    4,097
    Mentioned
    15 Post(s)
    Quoted
    42 Post(s)

    Default

    Quote Originally Posted by Smarter Child View Post
    GAH, never finished the whole thing.

    Great tutorial, but massive!


    ^^BookMarked^^
    Thanks for that

    Glad you decided to actually read it xD

  22. #22
    Join Date
    Aug 2009
    Location
    Inside the Matrix...yes it has me, and it has you too.
    Posts
    1,901
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    dan, u da man. i already know all this stuff, but rep++ for you for pure awesomeness
    NYAN NYAN NYAN NYAN NYAN NYAN NYAN NYAN NYAN NYAN NYAN NYAN NYAN

  23. #23
    Join Date
    Dec 2006
    Location
    Sydney, New South Wales, Australia
    Posts
    4,097
    Mentioned
    15 Post(s)
    Quoted
    42 Post(s)

    Default

    Quote Originally Posted by bionicle1800 View Post
    dan, u da man. i already know all this stuff, but rep++ for you for pure awesomeness
    He-he thanks

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •