Pascal Programming/Records

After you have learned to use an, this chapter introduces you to another data type structure concept called. Like an, the use of  s primarily serves the purposes of allowing you to write clean, structured programs. It is otherwise optional.

Concept
You briefly saw a  in the first chapter. While an  is a homogenous aggregation of data, that means all members have to have the same base data type, a   is potentially, but not necessarily an aggregation of data having various different data types.

Declaration
A  data type declaration looks pretty much like a collection of variable declarations: The declaration begins with the word  and ends with. Inbetween you declare fields, or members, member elements of the entire.

All  members have to bear distinct names within the   declaration itself. For instance in the example above, declaring two “variables”, member elements of the name  will be rejected.

There is no requirement on how many fields you have to declare. An “empty”  is also possible:

Many fields of the same data type
Similar to the declaration of variables you can define multiple fields of the same data type at once by separating identifiers with a comma. The previous declaration of  could also be written as: Most Pascal veterans and style guides, however, discourage the use of this shorthand notation (both for variable as well as  declarations, but also in formal parameter lists). It is only reasonable if all declared identifiers absolutely always have same data type; it is virtually guaranteed you will never want to change the data type of just one field in the comma-separated list. If in doubt, use the longhand. In programming, convenience plays a tangential role.

Use
By declaring a  variable you immediately have the entire set of “sub”‑variables at your hand. Accessing them is done by specifying the  variable’s name, plus a dot, followed by the   field’s name: You already saw the dot notation in the previous chapter on strings, where appending  on a name of a   variable refers to the respective variable’s character capacity. This is not a coincidence. However, especially beginners occasionally confuse the data type name with the variable’s name. The following code highlights the difference. Remember that a data type declaration does not reserve any memory and is mainly informative for the compiler, whereas a variable declaration actually sets some chunk of memory aside.

Advantages
But why and when do we want to use a ? At first glance and in the given examples so far it may seem like a troublesome way to declare and use multiple variables. Yet the fact that a  is handled as one unit entails one big advantage: Evidently you want to group data together that always appear together. It does not make sense to group unrelated data, just because we can. Another quite useful advantage is presented below in the section on variant records.
 * You can copy entire  values via a simple assignment.
 * This means you can pass much data at once: A  can be a parameter of routines, and in EP functions can return them as well.

Routing override
As you saw earlier, referring to members of a  can get a little tedious, because we are repeating the variable name over and over again. Fortunately, Pascal allows us abbreviate things a bit.

-clause
The -clause allows us to eliminate repeating a common prefix, specifically the name of a   variable. All identifiers that identify values are first looked for in the  scope of. If there is no match, all variable identifiers outside of the given  are considered too.

Of course it is still possible to denote a  member by its full name. E.&#8239;g. in the source code above it would be perfectly legal to still write  within the  -clause. Concededly, this would defeat the purpose of the -clause, but sometimes it may still be beneficial to emphasize the specific   variable just for documentation. It is nevertheless important to understand that the FQI, the fully-qualified identifier, the one with a dot in it, does not lose its “validity”.

In principle, all components of structured values “containing dots” can be abbreviated with. This is also true for the data type  you have learned in the previous chapter. Here, within the -clause , and for that matter  , refer to.

Multiple levels
If multiple -clauses ought to be nested, there is the short notation: which is equivalent to: It is important to bear in mind, first identifiers in  are searched, and if there is no match, secondly, identifiers in   are considered.

Variant records
In Pascal a  is the only data type structure concept that allows you to, so to speak, alter its structure during run-time, while a   is running. This super practical property of  permits us to write versatile code covering many cases.

Declaration
Let’s take a look at an example: The variant part of a  starts with the keyword , which you already know from selections. After that follows a  member declaration, the variant selector, but instead of a semicolon you put the keyword   thereafter. Below that follow all possible variants. Each variant is marked by a value out of the variant selector’s domain, here  and. Separated by a colon follows a variant denoter surrounded by parentheses. Here you can list additional  members that are only available if a certain variant is “active”. Note that all identifiers across all alternatives must be unique. The individual variants are separated by a semicolons, and there can be at most one variant part which has to appear at the end. Because you will need to be able to list all possible variants, the variant selector has to be an ordinal data type.

Use
Using variant records requires you to first select a variant. Variants are “activated” by assigning a value to the variant selector. Note, variants are not “created”; they all already exist at  startup. You merely need to make a choice. Only after assigning a value to the variant selector and as long as this value remains unchanged, you are allowed to access any fields of the respective variant. It is illegal to reverse the previous two lines of code and attempt accessing the  field even though   is not defined yet and, more importantly, does not bear the value.

It is certainly permissible to change the variant selector later in your  and then use a different variant, but all previously stored values in the variant part relinquish their validity and you cannot restore them. If you switch back the variant to a previous, original value, you will need to assign all values in that variant anew.

Application
This concept opens up new horizons: You can design your programs more interactively in a neat fashion. You can now choose a variant based on run-time data (data that is read while the  is running). Because at any time (after the first assignment of a value to the variant selector) only one variant is “active”, your  will crash if it attempts reading/writing values of an “inactive” variant. This is a desirable behavior, because that is the whole idea of having distinct variants. It guarantees your programs overall integrity.

Anonymous variants
Pascal also permits having anonymous variant selectors, that is selectors not bearing any name. The implications are “But wasn’t this the object of the exercise?” you might ask. Yes, indeed, since there is no named selector your  cannot keep track which variant is supposed to work and which one is “defective”. You are responsible to determine which variant you can sensibly read/write at present.
 * you cannot explicitly select (nor query) any variant, so
 * in turn all variants are considered “active” at the same time.

Anonymous variants are/were frequently abused to implement “typecasts”. If you have an anonymous variant part, you can declare members bearing different data types which in turn determine the underlying data’s interpretation method. You can then exploit the fact that many (but not necessarily all) compilers put all variants in the same memory block.

This concept exists in many other programming languages too. In the programming language C, for instance, it is called a union.

Conditional loops
So far we have been exclusively using counting loops. This is great if you can predict in advance the number of iterations, how many times the loop’s body needs to be executed. Yet every so often it is not possible to formulate a proper expression determining the number of iterations in advance.

Conditional loops allow you to make the execution of the next iteration dependent on a  expression. They come in two flavors: The difference is, the loop’s body of a tail-controlled loop is executed at least once in any case, whereas a head-controlled loop might never execute the loop body at all. In either case, a condition is evaluated over and over again and must uphold for the loop to continue.
 * Head-controlled loop, and
 * tail-controlled loop.

Head-controlled loop
A head-controlled loop is frequently called -loop because of its syntax. The “control” condition appears above the loop body, i.&#8239;e. at the head. is shorthand for. This standard  returns   if there is no further data available to read, commonly called end of file. It is illegal, and will horribly fail, to  from a file if the respective   function call returns.

Unlike a counting loop, you are allowed to modify data the conditional loop’s condition depends on. The  the loop’s condition depends on will be repeatedly divided by two. Because the division operator is an integer division, at some point the value  will be divided by two and the arithmetically correct result   is truncated  toward zero. Yet the value  does not satisfy the loop’s condition anymore, thus there will not be any subsequent iterations.

Tail-controlled loop
In a tail-controlled loop the condition appears below the loop’s body, at the foot. The loop’s body is always run once before even the condition is evaluated at all. The loop’s body is encapsulated by the keywords  and. After  follows a   expression. In contrast to a  loop, the tail-controlled loop always continues, always keeps going,   the specified condition becomes. A  condition marks the end. In the above example the user will be prompted again and again until he eventually complies and enters a positive number.

Date and time
This section introduces you to features of Extended Pascal as defined in the ISO standard 10206. You will need an EP‑compliant compiler to use those features.

Time stamp
In EP there is a standard data type called. It is declared as follows: As you can see from the declaration,  also contains data fields for a calendar date, not just the time as indicated by a standard clock.

Getting a time stamp
EP also defines a unary  that populates a   variable with values. assigns values to all members of a  passed in the first (and only) parameter. These values represent the “current date” and “current time” as at the invocation of this procedure. However, in the 1980’s not all (personal/home) computers did have a built-in “real time” clock. Therefore, the ISO standard 10206 devised prior 21st century stated that the word “current” was “implementation-defined”. The  and   fields were specifically inserted to address the issue that some computers simply do not know the current date and/or time. When reading values from a  variable, it is still advisable to check their validity first after having   fill them out.

If  was unable to obtain a “valid” value, it will set Both are independent from each other, so it may certainly be the case that just the time could be determined, but the date is invalid.
 * ,  and   to a value representing January 1, 1 CE, but also   to.
 * In the case of time,,   and   become all  , a value representing midnight. The   field becomes.

Note that the Gregorian calendar was introduced during the year 1582 CE, so the  data type is generally useless for any dates before 1583 CE.

Printable dates and times
Having obtained a, EP furthermore supplies two unary functions: Both functions will fail and terminate the  if   or   indicate an invalid datum respectively. Note, the exact format of  representation is not defined by the ISO standard 10206. Putting things together, consider the following :
 * returns a human-readable  representation of ,   and  , and
 * returns a human-readable  representation of ,   and.

Summary on loops
This is a good time to take inventory and reiterate all kinds of loops.

Conditional loops
Conditional loops are the tools of choice if you cannot predict the total number of iterations. It is possible to formulate either loop as the other one, but usually one of them is more suitable. A tail-controlled loop is particularly suitable if you do not have any data yet to make a judgment, to evaluate a proper  prior the first iteration.

Counting loops
Counting loops are good if you can predict the total number of iterations before entering the loop.

Inside counting loops’ bodies you cannot modify the counting variable, only read it. This prevents you from any accidental manipulations and ensures the calculated predicted total number of iterations will indeed occur.

Loops on aggregations
If you are using an EP-compliant compiler, you furthermore have the option to use a loop on sets.

Tasks
You have made it this far, and it is quite impressive how much you already know. Since this chapter’s concept of a  should not be too difficult to grasp, the following exercises mainly focus on training. A professional computer programmer spends most of his time on thinking what kind of implementation, using which tools (e.&#8239;g.  “vs.”  ), is the most useful/reasonable. You are encouraged to think first, before you even start typing anything. Nonetheless, sometimes (esp. due to your lack of experience) you need to just try things out, which is fine if it is intentional. Aimlessly finding a solution does not discern an actual programmer.

Sources: Type […] }} Notes:
 * quote        = […] records have two unique aspects: First, the stored values can have different types. This makes records potentially heterogeneous—composed of values of different kinds. Arrays, in contrast, hold values of just one type, so they’re said to be homogeneous.