home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #1
/
monster.zip
/
monster
/
CLIPPER
/
CLIPTIPS.ZIP
/
CODEBLOC.ZIP
/
CBEASY.TXT
Wrap
Text File
|
1990-08-15
|
9KB
|
125 lines
*╔═══════════════════════════════════════════════════════════════════════════╗*
*║ System Name: CODE BLOCK DEMONSTRATION SUITE ║*
*║ Module Name: CBSTART.TXT ║*
*║ Description: Shows how easy code blocks are to understand. ║*
*║ Author.....: Micheal Todd Charron ║*
*║ Date.......: Oct. 23, 1990 ║*
*║ History....: Thought up, on a Train to Montreal ║*
*╚═══════════════════════════════════════════════════════════════════════════╝*
┌─────────────────────────────────────────────────────────────────────────────┐
│ bBlock := { | p1, p2 | DEVPOS( p1, 0 ), cOutString := ( p2 +; │
│ ' ' + LTRIM( STR( p1 ) ) ), DEVOUT( cOutString ),; │
│ DEVPOS( p1, 8 ), DEVOUT( REPLICATE( ' .', 35 ) ),; │
│ ( p1 % 3 == 0 ) } │
└─────────────────────────────────────────────────────────────────────────────┘
The code above is a Code Block. If you don't have trouble understanding it,
please read no further. If your like me, you looked at these things for maybe
three weeks not understanding them one bit. Then another two months was
spent with hesitation wondering if the one you just typed in was in the right
format.
Then one day on a train to Montreal I began to wonder what was the best way to
explain Code Blocks to a User Group. I figured that the best way to start was
to help them look at them in a way that was very familiar.
┌─────────────────────────────────────────────────────────────────────────────┐
│ bBlock := {; │
│ | p1, p2 |; │
│ DEVPOS( p1, 0 ),; │
│ cOutString := ( p2 + ' ' + LTRIM( STR( p1 ) ) ),; │
│ DEVOUT( cOutString ),; │
│ DEVPOS( p1, 8 ),; │
│ DEVOUT( REPLICATE( ' .', 35 ) ),; │
│ ( p1 % 3 == 0 ); │
│ } │
└─────────────────────────────────────────────────────────────────────────────┘
By the way, DEVPOS() and DEVOUT() are new functions in Clipper 5.0/5.01.
DEVPOS() positions the cursor on the screen. DEVOUT() will display the value
of its parameter at the current cursor position.
The Code Block above is a little easier to read and it also shows how similar
Code Blocks are to User Defined Functions. In fact, we could actually take this
one step further and transform this Code Block to:
┌─────────────────────────────────────────────────────────────────────────────┐
│ FUNCTION fName │
│ PARAMETER p1, p2 │
│ DEVPOS( p1, 0 ) │
│ cOutString := ( p2 + ' ' + LTRIM( STR( p1 ) ) ) │
│ DEVOUT( cOutString ) │
│ DEVPOS( p1, 8 ) │
│ DEVOUT( REPLICATE( ' .', 35 ) ) │
│ RETURN ( p1 % 3 == 0 ) │
└─────────────────────────────────────────────────────────────────────────────┘
As you can see there is little difference between a Code Block and a User
Defined function. In fact, they have been referred to as Unnamed Functions.
Even the simplest Code Blocks can be converted into this format:
┌─────────────────────────────────────────────────────────────────────────────┐
│ { || 'just a string' } // Code Block │
│ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - │
│ FUNCTION Userfunc // User defined function │
│ RETURN ( 'just a string' ) │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ { | p | p + 1 } // Code Block │
│ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - │
│ FUNCTION Userfunc( p ) // User defined function │
│ RETURN ( p + 1 ) │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ { | x, y | SQRT( x ) + SQRT( y ) } // Code Block │
│ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - │
│ FUNCTION Userfunc( x, y ) // User defined function │
│ RETURN ( SQRT( x ) + SQRT( y ) ) │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ { | a, b, c | Myfunc( a ), Myfunc( b ), Myfunc( c ) } // Code Block │
│ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - │
│ FUNCTION Userfunc( a, b, c ) // User defined function │
│ Myfunc( a ) │
│ Myfunc( b ) │
│ RETURN Myfunc( c ) │
└─────────────────────────────────────────────────────────────────────────────┘
Always remember that the variables between the vertical lines (||) are the
parameters for the Code Block and the last expression in the Code Block
determines the value returned from the Code Block. If you run into trouble
with Code Blocks, convert them into User Defined Functions and work them out.
The last paragraph presents a question that I get asked constantly, "Why use a
Code Block instead of a User Defined Function?" A good rule to follow is that
you should use a User Defined Function unless the overhead of creating and
calling a UDF are greater than that of a Code Block. But alas there are times
when a Code Block must be used such as with Clipper 5.0's Objects Oriented
Classes.
The three companion programs CBMULTI.PRG, CBSAVE.PRG and CBRESTOR.PRG show a
couple of uses of Code Blocks. Please take a look at them.
*******************************************************************************
I don't want to confuse this discussion but I would like to take a second to
explain something before you move on.
┌─────────────────────────────────────────────────────────────────────────────┐
│ bBlock := { | p | p + 1 } │
└─────────────────────────────────────────────────────────────────────────────┘
In the code above we created a simple Code Block. Then we assigned the
reference to that Code Block to the variable "bBlock". The Code Block's name
is not 'bBlock'.
┌─────────────────────────────────────────────────────────────────────────────┐
│ bNewBlock := bBlock │
└─────────────────────────────────────────────────────────────────────────────┘
Both variables, "bNewBlock" and "bBlock", now contain the same reference to the
Code Block that was created previously. Now do you see why they call them
`Unnamed Functions'?
┌─────────────────────────────────────────────────────────────────────────────┐
│ ? EVAL( bNewBlock, 3 ) // Result: 4 │
└─────────────────────────────────────────────────────────────────────────────┘
Calling the above EVAL() function will pass the Code Block's reference into the
EVAL() function. Now that the EVAL() function has the reference, it can find
the location of the Code Block and evaluate it.
I hope that didn't confuse you. Especially since it is time to move on.
*******************************************************************************