Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Articles
Recherche: 

Reducing your code
Hilmar Zonneveld, December 1, 2002
Introduction This article presents an introduction to coding shortcuts in Visual FoxPro - when to use them, and when not to. Notes on coding in general This article is about coding shortcuts; however, I should first emphasize that making the code as small as possible is usually not the number...

Introduction

This article presents an introduction to coding shortcuts in Visual FoxPro - when to use them, and when not to.

Notes on coding in general

This article is about coding shortcuts; however, I should first emphasize that making the code as small as possible is usually not the number one priority when writing computer code. I would say the priorities are - usually in this order:

  • First of all, the code should work as expected.
  • The code should be maintainable (for instance, with inheritance, or an adequate use of functions, you can often make key changes in one single place).
  • The code should be readable. This also helps making the code maintainable.
  • The code should be fast. (I am sure many programmers would place "fast" higher up in the list, and in some cases, speed is of primary importance. However, I believe that quite often VFP does an adequate job without much tweaking, and that usually there is no need to sacrifice readability for speed.)
  • The code should not be longer than necessary (considering all of the above).

For instance, you should never omit a reasonable amount of notes in your code, just to make your code shorter, and you should never use variable names that are so short that the reader can't recognize what sort of value the variable is supposed to hold.

On the other hand, less lines to maintain may very well make the entire program more maintainable.

I haven't tried it, but I imagine there could be quite heated discussions whether a command like

a = b = c

should be avoided, in favor of a longer version. You can get accustomed to reading it and interpreting it correctly, and perhaps any good VFP programmer should be able to find out rather quickly what VFP will do if it sees this command.

Be this as it may, in the remainder of this article I will present some interesting ways to make long code short. In some cases, this is done at the cost of readability; the programmer should consider carefully whether it is worthwhile to use a certain shortcut.

Logical expressions

A great amount of coding "mistakes" (in the sense of using too much code) is done in the use of logical expressions. For some people it may be easy to understand code like

if a = b
   * Do something here
endif

but it might cause some difficulty to understand that in most places where you can use the values .T. and .F., any logical expression can be used. This includes saving a logical value to a variable or a field.

Let's see some examples involving logical expressions.

if MyField = .T.

MyField already is a logical expression! Comparing it to .T. is completely superfluous - this will result in exactly the same value as MyField. So, this expression can be simplified to

if MyField

A comparison like "if MyField = .F.", on the other hand, can be changed to "if Not MyField".

Another example:

if MyField
  MyVar = .T.
else
  MyVar = .F.
endif

This can be reduced to a single line:

MyVar = MyField

Remember the general rule: you can assign any logical expression to a logical variable.

And yet another example:

if b = c
  a = .T.
else
  a = .F.
endif

Once again, you can assign the logical expression (in this case, the result of the comparison) directly to the variable:

a = b = c

You may want to use parentheses:

a = (b = c)

but this is not required, since the comparison on the right is done before the assignment, anyway. That is, the parentheses are not required according to the compiler - for the human, the code with parentheses may be more readable, since it is now quite clear what is done first by the compiler.

IF, and shortcut Boolean evaluation

An expression like

if a
  if b
    (Do Something)
  endif
endif

can be simplified, combining the two Ifs (this only works here because of the lack of ELSE clauses):

if a and b
  (Do Something)
endif

In this case, the two statements are exactly equivalent, even if you replace "a" and "b" with more complicated expressions.

To fully understand the fact that the statements are equivalent, you should have a basic understanding of shortcut Boolean evaluation. Lets take a statement like

if a and b

It may help to review the truth table of the AND operator: if both parts are true, the result is true. If any of the two parts (or both) are false, the result is false.

That means that if the first part, "a", is false, the result will always be false, whether the second part is true or false. Therefore, there is no need to look at (evaluate) the second part. And this is exactly what the compiler does: ignore the second part.

This may not be very relevant with simple variables, but it can be very helpful with more complicated expressions.

For example, in the following code:

if type("x") = "L" and x

the first part of the condition is meant to avoid error messages. If the first part evaluates to false, the second part will not be evaluated, and there will be no error message ("variable not found" if the variable doesn't exist, or "type mismatch" if the variable happens to have the wrong type).

By the way, with OR, shortcut Boolean evaluation works the other way: if the first part is true, the second part will be ignored by the compiler.

Ignoring return values

VFP functions have a return value. If you don't need the return value, you can just discard it. Some examples follow:

InsMode(.T.)

will turn insert on. The return value (the previous value of insmode) is ignored in this case.

iif(llCondition, Function1(), Function2())

will execute Function1 if the condition is true, Function2 otherwise. Once again, the return value is ignored.

= Function1() and Function2() and Function3()

will execute the three specified functions, one after the other. If any of the functions returns false, the following functions will not be evaluated.

By the way, a more extensible way to obtain the same result, and one that simplifies debugging, is a DO CASE with no statements, only conditions:

do case
case not Function1()
case not Function2()
case not Function3()
endcase

Why will this work? Because, if one of the CASEs evaluates to false, VFP will try the next one.

XOR

I have seen the following workaround for the apparent lack of a XOR (exclusive OR) operator in Visual FoxPro:

if (a and not b) or (b and not a)

Of course, this will work, since XOR can be defined this way. However, there is a much simpler way:

if a # b

"#" is the inequality, which you may replace with "<>" or with "!=". You may prefer to make the code more readable, as follows:

#DEFINE XOR #
if a XOR b

For more complex expressions, remember that the thusly #defined operator is not a "real" boolean operator. This affects the order-of-precedence. In other words, in an expression like

#DEFINE XOR #
if (field1 = 0) XOR (field2 = 0)

the parentheses may not be omitted, since otherwise the equality on the right will be evaluated after the XOR (equality and inequality have the same order-of-precedence).

Know the relevant commands

It helps to know the VFP commands, and use the most appropriate for each case. This may help you avoid long workarounds. This general statement might be expanded to hundreds of examples; let me just give two.

go top
do while not eof()
  ? AnyField
  skip
enddo

Knowing the existence of the SCAN loop - which is specifically designed to skip through a number of records - simplifies this loop quite a bit:

scan
  ? AnyField
endscan

GO TOP, the condition, and the SKIP are all taken care of by the SCAN loop.

The second example shows that in some cases, knowing the commands is not enough - it may require a stroke of creative genius to apply existing functions in innovative ways. For most of us, this means participating in a newsgroup like the Universal Thread, to benefit from other people's genius. (I don't know who first discovered this particular shortcut.)

The problem is to include, in a SELECT - SQL statement, a clause to sort on a certain field. The sort order, however, is not alphabetic, but (sort of) arbitrary, since the field contains specially coded information. For instance, "Q" should come first, next "W", then "E", then "R".

Two obvious solutions are nested iif's, as follows:

SELECT ...,;
  iif(Code = "Q", 1, iif(Code = "W", 2, iif(Code = "E", 3, 4))) as OrderField;
  ...

and invoking a UDF which includes a DO CASE and returns the numbers in the desired sort order.

The shortcut - which in my opinion required a stroke of genius to be found - is as follows:

SELECT ..., at(Code, "QWER") as OrderField;
  ...

AT() simply does a search of the first string within the second, and returns the position, if found.

Summary

You can use a lot of different tricks to make your programs shorter. In some cases, this may make your program code easier to maintain. In others, it may make your code unreadable.

Hilmar Zonneveld, Independent Consultant
Hilmar Zonneveld works in programming since 1986, using dBASE, FoxPro and Visual FoxPro. He is available as an independent consultant. He currently works as a programmer at Bata Shoe Organization; also as an instructor at Cisco Networking Academy. You can contact him through the Universal Thread, or, via e-mail, at hilmarz@yahoo.com. Personal Web page (mainly in Spanish): www.geocities.com/hilmarz.
More articles from this author
Hilmar Zonneveld, May 1, 2003
An audit-trail is a record of who did what changes, and when. In Visual FoxPro, this can easily be accomplished through triggers. I hinted at the possibility of doing an audit-trail, in my article on triggers - now, as a reaction to questions in the Universal Thread, I want to present a sample...
Hilmar Zonneveld, December 6, 2001
(The latest update contains minor edits only.) Five easy and fun ways to get yourself into trouble with inheritance. A frequent source of problems in OOP is called "breaking inheritance". This document briefly describes what inheritance is, how it applies to properties and methods, and how it ...
Hilmar Zonneveld, July 1, 2002
Introduction Buffering is a feature in Visual FoxPro that allows us to give the user "undo" and "save" capabilities. In the old FoxPro 2.x days, programmers either didn't provide this capability, or edited memory variables, and copied information between these variables and the table fiel...
Hilmar Zonneveld, October 6, 2005
Due to a recent Windows security fix, users can no longer access a CHM file on a server. The table of contents appears, but the individual pages are replaced by error messages. Access to CHM files in specific folders can be explicitly allowed through special registry settings.
Hilmar Zonneveld, July 20, 2001
(The last update contains minor edits only.) The idea is to have several controls on a form controlled with an array. Thus, you can quickly go through all the controls on the form, managing the array. The sample code included will help you get started quickly. You can easily adapt it to manage...
Hilmar Zonneveld, September 1, 2002
With Automation, you can control all aspects of Excel, Word, or other programs that provide this feature, from Visual FoxPro. In this article, I will concentrate on Excel. Its purpose is to provide a starting point, especially for people new to automation. Introduction With automation, you bas...
Hilmar Zonneveld, March 1, 2003
Introduction One common task in programming is to keep track of what problems are pending. For this purpose, I use a "hierarchical to-do list": a list of items, each of which can have sub-items. All you need is Microsoft Word. Alternatives are available as freeware or shareware, but in t...
Hilmar Zonneveld, October 7, 2005
This is a step-by-step tutorial to show inheritance, specifically in Visual FoxPro forms, as a guidance for people who are not familiar with inheritance in general, or who don’t know how to implement it in Visual FoxPro. The basic idea of inheritance is that all your forms, or several of your for...
Hilmar Zonneveld, May 30, 2004
The code shows how to quickly obtain the greatest common factor, and the least common multiple. Both functions are used when manipulating fractions, among others. Several methods are possible; the method usually taught in school involves prime numbers, but this code will execute much faster (and it ...
Hilmar Zonneveld, November 1, 2006
A standard requirement in a production system, or in systems for cost calculation, is to add up all the raw materials for a number of finished articles, to get the total cost, or simply to purchase the materials. In this article, Hilmar outlines how to do this with multiple levels of intermediate ar...
Hilmar Zonneveld, August 1, 2002
Overview The purpose of this article is to give an overview of normalization. Basically, normalization refers to having an efficient table structure. I will not discuss the famous "first to fifth normal forms" - if you want that information, enough texts exist about it in other places (search sit...
Hilmar Zonneveld, November 8, 2001
The following function will open any document, with its default association (the same application that will be called when you double-click on the file, in Windows Explorer). Use it to open a text-file, a Word or Excel document, an image, etc., with an external application.
Hilmar Zonneveld, May 1, 2002
Introduction This document explains the meaning of primary key, foreign key and candidate index in Visual FoxPro. A discussion of natural and surrogate keys (keys visible, or not visible, to the end-user) is included, including the advantages of each approach, as well as different methods for o...
Hilmar Zonneveld, January 1, 2003
Continuing my series of introductory articles, this article presents an introduction of a simple yet powerful programming concept: recursion. Introduction "To understand recursion, you must first understand recursion." "To make yogurt, you need milk and yogurt." If you are not accustomed...
Hilmar Zonneveld, July 20, 2001
Rushmore Optimization can help make queries much faster. However, "Full Rushmore Optimization" is not always a desirable goal. "Partial Optimization" is sometimes much faster. It is often believed that to speed things up, you need to have as many indices as possible. This article explains that so...
Hilmar Zonneveld, June 7, 2002
If you need to check elapsed time with seconds() or a datetime value, this function allows you to display the elapsed time in a human-readable format, that is, hours:minutes:seconds, instead of the total number of seconds. Just pass a number of seconds as a parameter.
Hilmar Zonneveld, April 1, 2002
SQL is a standard language used to manipulate databases. Several of the SQL commands are integrated into the Visual FoxPro language. Select This is a very flexible command, used to select data from a table, or from several tables. This command has options to get totals from several record...
Hilmar Zonneveld, August 1, 2003
In this article, I will show several ways to manipulate text-files. Knowledge of these methods is often important to import and export specific formats. Some of the techniques can also be used to work with files of any content; however, this article will concentrate on text-files. When ...
Hilmar Zonneveld, June 1, 2002
The purpose of this article is to show how to use some aspects provided by the Visual FoxPro database engine, to control our data. Indices Perhaps most readers already know indices; anyway, I find it convenient to include a brief summary of the topic, since this is a requisite to understan...
Hilmar Zonneveld, November 1, 2002
A help file can be used either for interactive help, or as an online manual. In this article, I will give an overview over creating help files in the new help format (CHM), for Visual FoxPro 6 and later. This article is introductory and assumes no prior knowledge of the Help Compiler, or of HTML cod...
Hilmar Zonneveld, February 1, 2003
Introduction Any real-world application will sooner or later misbehave. It is important to be able to find those problems. Visual FoxPro's built-in debugger can help a lot to find out why your program doesn't work as you thought it would. Most of the material in this article applies to Visual...
Hilmar Zonneveld, May 1, 2006
This article is an introduction to VisioModeler. This is a free CASE tool, that can help you design your database, in the process sharing the information with the client in a visual, easy-to-understand, format.