Clipper Tutorial: a Guide to Open Source Clipper(s)/Basic Language Tutorial

xBase/Clipper Tutorial
Please note: if anybody will contribute, the Clipper tutorial should contain only 'standard' code that would work on every Clipper compatible compiler. Compiler-specific code should be placed somewhere else, or clearly indicated in a box.

The code here should be of simple console-mode applications using only the simplest forms of input/output and focused only on algorithms, since the methods for creating and managing user interfaces will be described in Chapter 5, Making Up a User Interface.

The helloworld application line by line
Let's try to highlight the parts of helloworld:

(in GeoCities this and all other sources were highlighted by the on-line service CodeColorizer at http://www.chami.com/colorizer/, or, alternatively by the service at http://tohtml.com/Clipper/ - they tend to look a bit better than the Wikibook highlighting).

We will comment on each line of the helloworld program.

function MAIN

The first line defines a function named MAIN. Defining such a function is not compulsory with Harbour, as if it is missed errors would occur during compilation, but I will keep it to make sure the examples work with all compilers. A function cannot be defined when typing in commands at the dot prompt (hbrun/xbscript).

Every xBase language is case insensitive, which means that all the following lines are the same:

function MAIN FUNCTION main FuNcTiOn mAiN

Of course, this feature is beneficial only if you use it to improve the code readability.

We will learn later how to define and use functions and procedures.

* This is an example

The second line is a comment. Commenting your programs will help you when you are to modify them later. If they aren't commenting, modifying them will be a very hard task. It will be much more difficult if you are to modify programs written by others if they didn't comment them: figuring out what a program does using only its code is very difficult and even the cleanest programming language may prove to be write-only if not properly commented.

You can write comments in many different styles: using an asterisk (*), two sweeps (//), a double ampersand (&&) or a couple sweep-asterisk (/*) and asterisk-sweep (*/), as shown below:

* This is a comment... // ...and so is this... && ...and this. /* This is an example of the fourth commenting style, which may span over several lines.*/

The second and the fourth commenting styles are derived from the C programming language, the first and the third are peculiar of the Clipper/xBase standard. None of these comments are accepted by xbscript, but hbrun (Harbour) accepts the last three.

clear

No, the purpose of this command is not to make the source code clear (that would be too easy! It is up to us to write clear source code, and to do so we must comment it well), but instead to clean the screen. :-) You could also use clear screen or cls, although these two commands are not exactly the same of this clear (the difference will be clear later when we can GET the point - then, you could also appreciate the pun in this paragraph - but will more likely not).

What are commands?

Harbour commands are defined via the #command macro directive (http://harbour.edu.pl/clipper/en/ng122d3c.html). The first commands we encountered are defined in the file std.ch by these lines:
 * 1) command CLS                       => Scroll ; SetPos(0,0)
 * 2) command ? []         => QOut

? "Hello, the weather is fine today"

The ? is a command which means print. In the BASIC programming language, it is also an abbreviation for its print command (the syntax of xBase is quite similar to that of the BASIC programming language).

In this case ? print the string "Hello, the weather is fine today". Please note that a string can be enclosed in single quotes (or apostrophes), double quotes or square brackets: all of the following are the same:

? "Hello, the weather is fine today" ? 'Hello, the weather is fine today' ? [Hello, the weather is fine today]

The last line:

return nil

Return is used to mark the end of the function. We will explain later what the return exactly does.

Today Harbour needs not an explicitly defined main function/procedure. The following version of helloworld will compile and is exactly the same as the previous one:

The Harbour Interpreter and Virtual Machine

The program above, stored in a text file named hello.prg, can be run with the command hbrun hello.prg

hbrun is an interpreter for Harbour. This means that if we run it, we get to a screen with a "Dot prompt" on its last line, where we can enter and run instructions. For example, entering ? "Hello world"

will get Hello world printed on the screen, but only after the interpreter hbrun itself is closed. To quit the interpreter and get the greeting printed type QUIT

All in all, hbrun permits to feel how handling databases was done in the old dBase "Dot prompt" mode - that is, like this: http://manmrk.net/tutorials/database/dbase/IntrodBASEIIIPlus.htm

Running the compiler harbour (harbour.exe on Windows) on a printA.prg containing the line ? "A"

will output a printA.c file. The bottom of this file reads:

that is, as an intermediate step the Harbour compiler compiles pcode, or bytecode for a virtual machine.

If the compilation is done with the /gh option hbmk2 /gh printA.prg harbour /gh printA.prg

the result will be a file named printA.hrb, a "Harbour Portable Object" file which can be executed by hbrun printA.hrb

In this way, hbmk2 and hbrun work in couple as a perfectly equivalent tools to the Java compiler javac and java interpreter java.

As a parenthesis, virtual machines are not a new concept. If we look into the retrocomputing field, we'll see that in the late 1970s and early 1980s the University of California San Diego has a portable operating system based on pcode, the UCSD P-System which was written in UCSD Pascal and could be run on 6502, 8080, Z-80, and on PDP-11 http://www.threedee.com/jcm/psystem/index.html (it actually was a competitor of MS-DOS, PC DOS and CP/M - http://www.digitalresearch.biz/CPM.HTM and http://www.seasip.info/Cpm/index.html).

Also, in 1979 Joel Berez and Marc Blank developed the Z-machine as a virtual machine to run Infocom's text adventure games, the name not hiding they were mainly thinking about Zork. The programming language for the Z-machine was called ZIL (Zork Implementation Language). A modern compiler for ZIL to Microsoft .NET is ZILF https://bitbucket.org/jmcgrew/zilf/wiki/Home and a Z-machine.NET is available https://zmachine.codeplex.com/. More information at http://inform-fiction.org/zmachine/index.html.

Apart from the JVM (Java Virtual Machine), the Microsoft .NET CLR (Common Language Runtime), is another modern virtual machine.



hbmk2 was created to support all shells, all compilers on all platforms, also to replace old 'bld.bat' solution, while staying compatible with existing hbmk script features and options.

Pieces of information on how to get an executable without using hbmk2 can be found at http://www.kresin.ru/en/hrbfaq.html.

Remember that the PATH Environment Variable (in Windows) must be updated to include the directory containing the compiler: use the command SET PATH=C:\hb32\bin;%PATH% locally in a Prompt Window or update it globally: "Start" → "Control Panel" → "System" → "Advanced system settings" → "Environment Variables..." → select "Path", then click "Edit..."

Data Types in General (and Their Operators)
The list of types supported by Clipper is as follows:
 * A        Array
 * B        (Code) Block
 * C        Character
 * D        Date
 * L        Logical
 * M        Memo
 * N        Numeric
 * O        Object
 * U        NIL

These letters can be used as a prefix to a variable name, to indicate "at first sight" what kind of item it is. This way  o Box would be the name of an object,  a Names an array,  d Birthday a date and so on. An alternative for logical variables is to add an is prefix as in is Ok or is Existing (somewhat more readable than lOk and lExisting). This naming convention is called the Hungarian notation and applies to functions as well, and to their synopsis:  A COPY( , , [], [], [] ) is the function to copy elements from an array to another, which takes two arrays a Source and a Target, and optionally three numeric parameters n Start, n Count, n TargetPos;  C To D ( c Date) takes a character argument and converts it to a date,  DB Create is a function to create a database.

The type Memo can only be used in a database (it is a link to a subsidiary file to a DBF table, as described in the Wikipedia DBF entry).

This is the list of results returned by the function VALTYPE. The function TYPE returns also:
 * U        NIL, local, or static
 * UE       Error syntactical
 * UI       Error indeterminate

Harbour has a longer list (http://www.fivetechsoft.com/harbour-docs/harbour.html):
 * HB_ISARRAY
 * HB_ISBLOCK
 * HB_ISCHAR
 * HB_ISDATE
 * HB_ISDATETIME
 * HB_ISHASH
 * HB_ISLOGICAL
 * HB_ISMEMO
 * HB_ISNIL
 * HB_ISNULL
 * HB_ISNUMERIC
 * HB_ISOBJECT
 * HB_ISPOINTER
 * HB_ISPRINTER
 * HB_ISREGEX
 * HB_ISSTRING
 * HB_ISSYMBOL
 * HB_ISTIMESTAMP

ISPOINTER (http://www.marinas-gui.org/projects/harbour_manual/ispointer.htm) for example is marked: Not available in CA-Cl*pper. Together with HB_IT_POINTER and HB_ISPOINTER it is used in Harbour's internals (the C-level API: http://www.fivetechsoft.com/harbour-docs/clevelapi.html#ispointer).

Let us see a little program that shows the use of the most common data types.

I wanted to show, in this example, a computation of π instead of that of √2, but xBase misses the ArcTan function. We may solve this problem by importing it from an external library, or by supplying it ourselves. (Both ways should be pursued in this tutorial).

The last two data types are a bit different from the preceding: "Memo" is not very useful when used outside of a database, and the arrays cannot be used in databases.

The function SQR has been eliminated from Harbour and replaced by SQRT. Trying to use it will result in a linker error "undefined reference to 'HB_FUN_SQR'".

From the following example (which runs) we see that Harbour is a weakly typed programming language: a variable, such as a in our example can be a number, and then become a string of text.

There is a problem: if the variable type changed and the programmer did not get aware of it he may issue some instruction that will cause an error at run time. If we had another line of code

in the program above, Harbour will attempt to add the number 1 to the string "abc", and the result will be the error

Error BASE/1081 Argument error: +.

Strings
Strings are essentially a list of characters. They are written between double quotes (eg. "Hello"). Note the difference: 123      => a number "123"    => a string

Let's see how to use the function Stuff to change a character within a string:

Here is a list of the most commonly used functions for handling strings:

Lower  Convert uppercase characters to lowercase Upper  Converts a character expression to uppercase format Chr    Convert an ASCII code to a character value Asc    Convert a character to its ASCII value Len    Return the length of a character string or the number of elements in an array At     Return the position of a substring within a character string

Nevertheless in Clipper and Clipper Tools library can also be found very curious functions such as these:

AsciiSum  Finds the sum of the ASCII values of all the characters of a string Soundex   is a character function that indexes and searches for sound-alike or phonetic matches CHARONE   Search and remove repeating characters CHARONLY  Remove non-standard characters CHAROR    "OR" bytes in a string

Let's see what we can do with these functions.

We show the ASCII codes (http://www.asciitable.com/) corresponding to the keys pressed by the user, concluding the program when ESC is pressed.

inkey.ch is the eader file for Inkey function, which serves to obtain the following key code from the keyboard buffer.

Other Considerations about the Classification of Data Types
A first classification of data types divides them into simple (or scalar) types and structured (or composite, or aggregate or compound) types.

In xBase the simple data types are numbers, logical values, strings and dates, that is, the types which can be field types in a database table. Memos are not, since they are a pointer to an external file.

Scalar data types can be composed to build up structured data types: arrays, associative arrays (hash tables), tables or databases (which are a "data type" which is stored on a disk). Primitive_data_type

Code blocks and objects are special data types.

Operators and Precedence
We see in this example that the exponentiation operator ** is left-associative (as opposed to mathematics where exponentiation is a right-associative operation).

The fact that 3**3**3 and 3**(3**3) give two different results means that parenthesis alter the operator precedence: whatever is enclosed in parenthesis is evaluated first.

Even when the operation is left-associative, the result of 9**9**9 is quite a "large" number (196627050475552913618075908526912116283103450944214766927315415537966391196809 to be precise, as you can easily check - maybe using some arbitrary precision calculator program, such as GNU bc, which is available on every Linux distribution and as a download for Windows at http://gnuwin32.sourceforge.net/packages/calc.htm - or by hand spending only some weekend time) which exceeds the resources Harbour allocates for a number (which is called overflow) and it, therefore, prints 23 times a * to indicate this error. It also gives zero (0.00) if we try to compute its reciprocal (which is called underflow). Overflow and underflow errors happen when the result of a computation is, respectively, too big or too small to be represented with the number of bits a compiler has allocated for the variable in which we're trying to store it in.

The same happens with dates. What it the result of date-1000000 (subtracting 1 million of days from the current date)? Let us see:

Here, the last two outputs ("00/00/00") indicate invalid dates, just as the rows of 23 asterisks seen above indicate invalid numeric results. Acceptable dates are those that can be stored in a dBase table (ie a .dbf file) and in these files a date is a string of 8 characters in the "YYYYDDMM" format (4 characters for the year, 2 for the month and 2 for the day). Consequently, negative years (before Christ) or with more than 5 digits are not accepted.

Harbour displays the year with only two digits unless we change its behavior with a SET command and gives wrong results with these large number of years. The reason is simple: in a database application (inventory management, reservation systems) we won't have to deal with intervals of centuries and Harbour's routines for handling dates don't work correctly if we try to do that. In other fields, such as Archaeoastronomy this is the case and those who do deal with those problems (e.g. checking the precision of the alignment of the Winter solstice sunrise at Karnak in 2000 B.C. or the megalithic alignments) use their special routines for the computation of the dates.

There is another quandary when doing computation with computers. Look:

Now, if we extract the square root twice from a number and then square the result twice we should have the starting number. In fact, computers are not so precise and checking for the equality of two floating-point numbers can give unexpected results.

If you want to learn more you could have a look at What Every Computer Scientist Should Know About Floating-Point Arithmetic at https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html (which is part of a Sun Microsystems book entitled Numerical Computation Guide), and the Decimal Arithmetic FAQ at http://speleotrove.com/decimal/decifaq.html.

Fortunately, the precision of the variables used in xBase languages ​​and the fact that in common business applications square roots, logarithms and other mathematical operations that cause loss of precision are rather rare, are circumstances that mitigate the problem.

SET OPTIONS

We've seen SET DECIMALS TO n and SET CENTURY ON/OFF commands. But in fact there are many options which can be set. The SETMODE(, ) function is particularly useful when using hbrun or xbscript: its purpose is to determine the size of the window.

Boolean Algebra & Flow Control
We can print the result of a comparison, which is a Boolean value (represented as .T. or .F.), but they are useful with special words in order to branch or repeat the execution of one or more instructions.

We have a Boolean expression when its result is true (whose xBase symbol is .T.) or false (.F.). The easiest way to get a Boolean result is to use a comparison (relational) operator: =, ==, !=, <>, #, >, <, >=, and <=. Always remember the difference between the comparison operators = (equal), == (exactly equal) and the assignment operator :=.

Actually, the "real" (mathematical) definition of a Boolean expression is different from what is stated in the last paragraph. A "real" Boolean expression would contain only the two Boolean values .T. and .F. and the Boolean operators (.AND., .OR., .NOT.).

Boolean Algebra is applied to electronic digital circuits since the work of Claude Shannon in 1937. See http://www.allaboutcircuits.com/textbook/digital/chpt-7/introduction-boolean-algebra/ (and the successive pages of that online textbook) to have an idea of what Boolean Algebra means when it's applied to bits within a circuit (including a microprocessor). Here we're using it at a much higher level.

Consider Hamlet, Act 3, Scene 1: «[…]To be, or not to be? That is the question— Whether ’tis nobler in the mind to suffer The slings and arrows of outrageous fortune…». If Prince Hamlet asked Boole (but he could not, as it is set in the 14th or 15th century whereas Boole was born in 1815), his reply would have certainly baffled him. Why?

As Harbour told us, in Boolean algebra, the answer is "true". Have a look at this page: https://vicgrout.net/2014/07/18/to-be-or-not-to-be-a-logical-perspective/.

Conditional execution
A number of graphical ways have been developed for seeing how a program's flow control is transferred: these include flowcharts (https://www.lucidchart.com/pages/what-is-a-flowchart-tutorial), data flow diagrams (https://www.lucidchart.com/pages/data-flow-diagram), Nassi-Shneiderman diagrams and the JSP and JSD diagrams by Michael A. Jackson (which is almost certainly not the first Michael Jackson you'll think of).

The following example gets a number from the keyboard and prints it. If the number is 0 it comments that value (I presented this example as a typical nihilist programming). The flowchart shows why conditional execution is sometimes called bifurcation.



This example prints two different comments, whether the condition of the remainder of the division of the number supplied by 2 is, or is not, 0.

This example shows that more than a command can be executed.

This example adds another keyword, ELSEIF, to show that the choices are not necessarily dichotomic. This is a chained conditional. Only one of the branches will be executed.

The following example checks whether the system time is earlier than 18 (6 p.m.) and prints a greeting appropriate to the time of day.

There are three logical operators: .AND., .OR., and .NOT.

Here is an example with a rather long condition, coordinating more comparisons with .OR. operators. The example is terribly stupid, but it shows how a semicolon allows you to continue an instruction on the following line.

This same thing is however achieved in a more concise way using the substring comparison operator $ (or regular expressions, an advanced topic that we will see later).

Looping
DO WHILE, EXIT, LOOP, ENDDO are keywords used To repeatedly execute a series of statements (loop body) while a condition is true (i.e. its result is .T.).

Loops come in several flavours: the pre-tested loop, the post-tested loop, and the definite iteration, which is done via a count-controlled loop (usually called a for loop). In practice, we may have a middle-tested loop as well, but no specific syntax for it... we need to put an EXIT statement within an already existing loop body to get this one. The next program we will key in is of some interest for the mathematicians (Real Programmers aren't afraid of maths, do you know this famous adage?)

Here is it: As you can see, this looping statement is similar to the IF statement: both of them are ended by a END-corresponding statement, both of them contains a logical espression.

This looping statement will continue until its condition remains true (will evaluate to .T.).

The two instructions it repeats are sum=sum+num and num=num+2. The second is fundamental: if it wasn't there or was wrong (for example if you keyed in num=num/2), the condition would not evaluate to .F. and the program would not stop its execution (this is called infinite looping). When this happens to you, press the keys Ctrl and C at the same time. This should convince the computer to give his attention to you instead of running the loop.

The programs above is a nice example of how an extremely methodical calculator without any creativity would attack the problem of summing up the first n odd numbers. Notes about the creative approach to it can be found at this address: http://betterexplained.com/articles/techniques-for-adding-the-numbers-1-to-100/ (along with the usual anedocte about Gauss' show off about it in elementary school).

The WHILE looping statement is said to have the control expression in its head, opposed to the Pascal REPEAT-UNTIL looping statement (a post-test loop) which has the control of the condition in its tail (these are the Italian computer science slang for pre- and post- tested loops, aren't they funny?). How does the xBase/Clipper say REPEAT-UNTIL? It doesn't. Here is how to emulate it (copied & pasted from the Norton Guide):

LOCAL lMore := .T.

DO WHILE lMore

loopbody

lMore := condition

ENDDO

As you see, we first set a variable to be true, enter the loop, and specify the condition at the end of the loop, to make sure its body is executed at least once.

Here is an example, equivalent to the one at the pascal_repeat_until_loop page in tutorialspoint.com.

But the code above changed the condition. If we didn't want this to happen, we can simply negate the condition we'd use in the Pascal code: repeat loopbody until condition becomes then:

Let us now see this kind of loop: This loop prints "I won't stop." as long as 'true' is... true. It is thus called an infinite loop because the ending condition will never be satisfied. It is the first example of control flaw studied in computer science classes. By definition, you incur in an infinite loop every time you specify a tautology as the condition to be checked. It is not always obvious to detect this and other control flaws and errors - it is indeed a process that involves the use of a specific piece of software called a debugger.

Counter-controlled Loops, and Nested Loops
In this section, we will see how to use FOR loops to print multiplication tables, how to nest loops, how to format output on the console screen and the importance of indenting code to improve readability.

The FOR...NEXT construct (counter-controlled loop) is useful when we know how many times we want the loop body be executed. We shall now use it to print out and revise multiplication tables.

(Please note in this example we have a loop inside the body of another loop: this is called a nested loop). Well, this works, but its output is not very nice... Moreover, it is customary to print the multiplication tables up to 10, since we're using a decimal numeration system... let us try it again!

this way we can print it much prettier... by the way, when nesting loops and branching statements, it becomes important to arrange the indentations in order to make the program easier to read... in The Oasis are available "source code beautifiers" such as dst314.zip. Harbour gives us the hbformat tool, https://vivaclipper.wordpress.com/tag/hbformat/.

PICTURE "999" is the instruction to specify we want the output format - as we specified three digits, the numbers in output will be printed as if they were three digits long, thus aligning them in our multiplication table.

As a second example of nested loops, the following is one of the most irritating programs I've ever written. It asks the user for an opinion and then always responds its contrary. It even quits when the user says he has more to tell him and keeps asking for input when the user says he has nothing else to add. Since it is particularly difficult for a program to answer the opposite of the user's assertions, this program simply prints the input string reversed, using the SubStr function (SubStr(, , []) --> cSubstring - extract a substring from a character string cString, at index nStart with length nCount).

User input is obtained through the ACCEPT command (a COBOL reminiscence), and the control flow uses a DO WHILE loop (from FORTRAN) and a FOR ... TO ... STEP loop (from BASIC).

How do we deal with such an awkward customer? Just try typing "remmargorp revelc yrev a era uoy" and the solution will be clear. In Italy there is an expression to call a person who always contradicts his interlocutors: he is called a "bastian contrario". They do work like this program.

& - the Macro Evaluation Operator
Consider this short piece of code:

The & is an operator that will evaluate (runtime compilation) an expressions and will permit text substitution within strings (see https://harbour.github.io/ng/c53g01c/ng110bc2.html). Let's make a simple calculator using it.

Here is an example of interaction with this program:

Please enter the first number: 12 Please enter the second number: 23.5 Enter operation: - 12-23.5=       -11.5

Arrays
An array is an ordered grouping of data, whose elements are identified by a number called an index. In many programming languages ​​the indices (or "indexes") start at 0, but in xBase they start from 1. Since in mathematics the indices are written next to the variable slightly below the line, sometimes they are called subscripts and, for this reason, arrays are sometimes called subscripted variables.

Consider this first example of arrays. We create two arrays, one with the names of the months of the year and one with their duration in days, and then we print them in an orderly manner. The same result can be obtained in a much more elegant way using associative arrays.

In the next example we show that xBase has high-level support for dynamic arrays (implementing them in a low level language like C requires pointer arithmetic and memory management functions).

Note: This example will reappear many times in these notes. Often when we will introduce a new feature of the language we will write a new program which does the same thing of this program in a different way. It is one of the best pedagogical advice I can give you. Since I don't provide you with exercises, think of different ways of redoing some program using new language features, i.e. just to give you an idea: how difficult is it to redo the program that shows the multiplication tables on the screen using code blocks?

Here is the list of functions in hbmisc: https://harbour.github.io/doc/hbmisc.html.

The program above is not very satisfactory: due to the use of the IsDec function it can treat only positive integer numbers. What if we'd like it to accept numbers like -8 and 2.78? Three solutions come to mind offhand: write ourselves function that checks if the string represents a number (an improved version of IsDec), test input using regular expressions, using xBase functions for error handling. We will use this last technique in the next section of the tutorial.

FOR EACH n in aNumbers       && FOR EACH is a more modern control flow statement Harbour syntax ?? AVERAGE - &n NEXT

In addition to a function to add elements to an array we have one to delete them:

Harbour provides a function, hb_ADel, which accepts a third Boolean element and (if it's .T.) shrinks the array.

Multidimensional arrays are made by nesting arrays within other arrays.

Error Handling (the Clipper Way)
All of the programs showed up to this point will fail and show a runtime error if the user entered an unexpected input (in simple words, they crash). Programs called "robust" don't. Checking the conditions in which errors can occur and take countermeasures to prevent crashes is a job that was normally done with if-then-else.

BEGIN SEQUENCE ... END[SEQUENCE] is a control structure that executes some code and optionally some statements if the code produced an error. In our example if the conversion of the user input into a number generates an error, we will call EXIT to leave the while loop and continue our program.

Clipper 5 (C5) provided four classes:

Error          Provides objects with information about runtime errors Get            Provides objects for editing variables and database fields TBrowse        Provides objects for browsing table-oriented data TBColumn       Provides the column objects TBrowse objects

The Clipper 5.3 Norton Guide lists these classes:

Error class      Provides objects with information about runtime errors CheckBox class   Provides objects for creating checkboxes Get class        Provides objects for editing variables and database fields ListBox class    Provides objects for creating list boxes MenuItem class   Provides objects for creating menu items PopUpMenu class  Provides objects for creating pop-up menus PushButton class Provides objects for creating push buttons RadioButto class Provides objects for creating radio buttons RadioGroup class Provides objects for creating radio button groups Scrollbar class  Provides objects for creating scroll bars TBColumn class   Provides objects for browsing table-oriented data TBrowse class    Provides the column objects TBrowse objects TopBarMenu class Provides objects for creating top menu bars

Functions and Procedures
A function is a piece of code that returns a result every time it is called. Let us consider a function to convert Celsius into Fahrenheit (the same function is provided by libct, but we redo it for educational purposes):

But have a look at the following:

Consider this example of use for the function HB_Random:

A good function would function as a "black box", that is you can use it without worrying about how it internally works. An example usually given at this point is that of driving a car: you can use it without worrying about how the engine works (do you know anybody which looked at the pistons of their new car before buying it?). Someone else designed the engine. But there may be problems: if we change our Celsius into Fahrenheit function as follows

we'll get a side effect. This program output is

212.0       32.0         2

That is, our new function did not only return a value, it also increased by 1 the variable number.

The Clipper Norton Guides read, "A procedure in CA-Clipper is the same as a user-defined function, with the exception that it always returns NIL" (http://www.oohg.org/cl53/ng10a778.html), thus a procedure is really just a type of function that relies on these side effects to get something done.

The utility of functions is that they improve program readability, maintainability. Splitting a program into functions is a good design approach, which lets breaking a complex problem into smaller, simpler problems (top-down).

Harbour has four different kinds of subroutines/subprograms:
 * the FUNCTION and
 * the PROCEDURE (which is a FUNCTION with no return value),
 * the method (which has no associated keyword, works like every object-oriented programming language) and
 * the code block.

Why the Main Function?
The main function is the designated start of a program written in C or C++ (Java uses a static main method). Since a procedure is a function that returns NIL, we can have a procedure main instead of a function main in our program. With Harbour it is not necessary anymore.

Another characteristic of variables: scope identifiers
Variables have a name, a type, a scope and a lifetime (http://www.dbase.com/Knowledgebase/dbulletin/bu05vari.htm) which may be explicitly declared as (list below copied verbatim from Harbour (software)):


 * LOCAL: Visible only within the routine which declared it. Value is lost upon exit of the routine.
 * STATIC: Visible only within the routine which declared it. Value is preserved for subsequent invocations of the routine. If a STATIC variable is declared before any Procedure/Function/Method is defined, it has a MODULE scope, and is visible within any routine defined within that same source file, it will maintain its life for the duration of the application lifetime.
 * PRIVATE: Visible within the routine which declared it, and all routines called by that routine.
 * PUBLIC: Visible by all routines in the same application.

They do not make sense before we work with functions and procedures.

On running this, we get a strange output:

9 x from A=        10 9 x from B=         5 9 x from C=         -1 9 x from D before updating value=         -1 x from D=        12 9 x from E=        12 9

This program sets a variable x and five different procedures, A, B, C, D, E. The first three procedures define a variable x within themselves, assign it a value and print it. The fourth function assigns a new value to some variable named x without declaring it. The fifth function shows the value of some x variable, which happens to be the value of the fourth x variable. The main fact to remember here is that two variables are not the same, even if hey have the same name, provided they have different scopes and this feature is called shadowing.

9 x from A=        10 9 x from B=         5 9 x from C=        -1 -1 x from D before updating value=        -1 x from D=        12 12 x from E=        12 12

As static variables seem to require further informations (they work like C static variables), here is an example:

See pascal_variable_scope in tutorialspoint.com and http://aelinik.free.fr/c/ch14.htm

Variable scope is a foretaste of object oriented programming, in the sense that it anticipates some encapsulation concepts.

Part 1: Using the Clipper Tools (CT) Library
If you checked the list of functions you will have noticed that the xBases have no trigonometric functions. Not that in general they miss them: these languages are targeted database applications such as "accounting systems and airline reservations systems" (see Database application. ) in which trigonometric functions are not really important. But we now ask ourselves how to compute an approximation to the Ludolphine number, π (more information on this "search" at http://www.mathpages.com/home/kmath457.htm), We can do it using the CT library (see http://vouch.info/harbour/index.html?hbct.htm), or importing the C standard library function atan.

Part 2: Mixing C and Harbour Code
We get the idea from Harbour for beginners by Alexander Kresin (http://www.kresin.ru/en/hrbfaq_3.html). It must be noted that the extend.h file (* Compatibility header file for CA-Cl*pper Extend System) contains this warning:

/* DON'T USE THIS FILE FOR NEW HARBOUR C CODE */ /* This file is provided to support some level of */ /* Harbour compatibility for old Clipper C extension code */

In fact this example is here only to consider how the open source cross-compilers (Harbour in this case) extend themselves with C library functions, which gives them a lot of flexibility. Not that computing π would be useful in itself for the average xBase programmer (by the way the CT library contains a function to directly compute π). We shall not concern ourselves with a method to do that, but move to something more conventional.

The FizzBuzz interview question: critical thinking and algorithms, with an introduction to table trace and the concept of flag
FizzBuzz is a little problem that is quite often asked in job interviews. A good discussion is found at the page https://micheleriva.medium.com/about-coding-the-fizzbuzz-interview-question-9bcd08d9dfe5. As always there are many ways of solving even a simple problem like this, that can be worded as follows,

Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.

The first thing one should do is to think as many ways as possible to solve the problem. Also, you may be asked to show that your solution works without having access to a computer: the way of doing so is also one of the best ways of reading a program written by someone else, and even of checking the program you yourself wrote. You take a piece of paper and a pencil and check how the program instructions change the variables and what input they produce by arranging the content of the variables in a table and behaving like the computer. I heard this being called called Trace table, tracing an algorithm, hand tracing, dry running. For the moment I point you to a tutorial on YouTube which should give you a taste of how the thing works: https://www.youtube.com/watch?v=UbANyxE7pGE (Trace tables tutorial GCSE Computer Science).

Take for example the following trivial solution of FizzBuzz:

This example introduces a flag variable, that is, a variable that is checked to know whether the program executed a particular instruction or set of instructions.

Sorting Algorithms
Sorting data is an important application in computer science. In fact, in the ancient times (which means in the 50s), an important component of a computer was a piece of hardware called a Card Sorter, which was used to sort punched cards, see one at http://www.columbia.edu/cu/computinghistory/sorter.html, but the Census Machine built by Hollerith in the 1880's already had its own sorter box, and the French word for computer, ordinateur, can even be literally translated to sorter.

Let's start with a piece of code

From the version above we can (and should) separate the sorting routine in a procedure, this way:

Usually the first sorting algorithm introduced (even in my high school textbook) is Bubble Sort, which is a bad choice. Here we use Exchange Sort, which is equally bad, but at least we vary a little.

Grasping Recursion
We have recursion when a function calls itself. The definition is really this simple.

Put like that, it doesn't seem like a good idea, because it seems that a recursive function will trap the program in an infinite loop. In reality a recursive function does not just call itself, but includes a criterion to stop doing it and provide some actual result.

A first example is the factorial function, of which we take a definition from a dictionary (https://www.dictionary.com/browse/factorial): « Mathematics. the product of a given positive integer multiplied by all lesser positive integers: The quantity four factorial (4!) = 4 ⋅ 3 ⋅ 2 ⋅ 1 = 24. Symbol: n!, where n is the given integer».

Code blocks
https://github.com/vszakats/harbour-core/blob/master/doc/codebloc.txt

Sites around the Net say that Clipper 5 documentation called them unnamed assignable functions.

Let us get back at our Celsius to Fahrenheit temperature converting function:

and redo it as a codeblock:

In the first line we assigned a code block to a variable named Cels2F. The code block is comprised in braces. The first thing is a variable that is to be passed to the block, between vertical bars (|). More variables should be separated by commas. Then we can write the instructions (more than one should be separated by commas).

Later we use two times the Eval function giving it two arguments: the name we assigned to our codeblock and the parameter to pass it. In addition to Eval, other functions can evaluate code block: AEval and dbEval. Ascan and Asort can be given code blocks to change their behavior.

As code blocks can't contain commands, we can't put a ? command in them, but have to use the corresponding QOut function.

Command Line Arguments
Suppose that we wish to write a clone of the Unix cat command, which means that we will have a program to which we'll pass a command line argument that is a file name and output the content of the file.

That's it! In fact, it is quite limited, and it is more likely a clone of the DOS type command (or even of the CP/M type command!). Procedure This file's procedure MAIN receives one argument, and gets it from the command line. Then passes it to the MEMOREAD function (description: Return the text file’s contents as a character string), and sends the result to the console output.

File Management
Accessing files can be done using low-level functions, which are: FOPEN, FCREATE, FWRITE, FREAD, FREASDSTR, FERASE, FERROR, FSEEK, FCLOSE and FRENAME.

How should we code an example using these functions? Here is an idea:


 * 1) We create a new file is created using FCREATE and text is written into it with FWRITE.
 * 2) The pointer is positioned at the end of the file using FSEEK.
 * 3) The contents of the file are read using FREAD.
 * 4) The file is closed with FCLOSE.
 * 5) The file is renamed using FRENAME.
 * 6) Finally, the renamed file using FERASE is deleted.

Harbour, however, provides functions that permit manipulating text files in a similar way to DBF files (https://vivaclipper.wordpress.com/tag/memoread/).