SCOUG-Programming Mailing List Archives
Return to [ 22 | 
February | 
2006 ]
<< Previous Message << 
 >> Next Message >>
 
 
 
Content Type:   text/plain 
I never know when I've communicated as opposed to just   
saying something.  If it went in one ear and out the other with   
nothing lingering inbetween, then along with Hud we have   
here a classic failure of communication.  I would like to   
change that.  Would you help me?  
 
Fourth generation programming languages use logic   
programming.  Making the distinction between the logic   
programming of fourth generation languages and the   
programming in logic of third generation, "procedural" or   
"imperative" languages occurs in the division of labor between   
the programmer and software for the overall (or global) logic   
of a program.  
 
In a procedural, which includes all third generation languages,   
the programmer has total responsibility for the overall logical   
organization of the program.  That means when a significant   
change in logic occurs resulting in a equally significant (and   
hopefully error free) reorganization (rewriting) of the source   
code that falls squarely on the programmer's shoulders (brain,   
hands, and employment opportunities).  
 
In fourth generation logic programming that global   
organization shifts largely to the software.  Thus significant   
logic changes which require significant reorganization   
(rewriting) occurs a few million times faster in software.  A   
few million here and there quickly adds up to less time   
overall, thus greater programmer productivity.  
 
Those most informed among you know that optimizing   
compilers analyse code and where possible perform global   
optimization.  This results in executable code whose   
instruction sequence equivalent to but different from that of   
the source.  However, this optimization does not occur at the   
source level, but at the intermediate level translated from the   
source.  Thus the source itself remains non-optimized.  Thus   
any real optimization of the source remains the responsibility   
of the programmer.  If we could rely on that, we wouldn't   
bother with doing a number on the intermediate code.  
 
Now if we rely on the software to perform all the program   
logic...optimally..., we could write all the necessary source   
code statements willy-nilly in any order, shove chaos in the   
input and get a perfect program as output.  Fat chance.  In   
fact, no chance.  Null.  Nil.  Zip.  
 
Somewhere between this complete, non-logical chaos of   
source and the complete programmer-written local and global   
source logic lies a point which has a minimal necessary   
programmer-written logical organization with a reliance on   
the software to complete the balance.  
 
Now we do have some examples of this fourth generation   
phenomenon.  In fact millions of them executing billions of   
times daily.  SQL.  Structured Query Language.  A fourth   
generation programming language (though don't tell this to   
those writing in it).  Shhh.  Don't let them know they're   
engaged in using a language advanced over that used by the   
vast majority of "professional" programmers who continue to   
muddle about in C-based slime.  
 
Now logic programming, e.g. SQL, uses a two-stage proof   
engine of a completeness proof and an exhaustive true/false   
proof.  As its name implies the completeness proof looks at   
the input, the source SQL, verifies its syntax, checks its   
semantics (does it refer to a known database, a known table   
in that database, and a known column within a row in that   
table?), which includes its logic, creating optimized   
intermediate code (there it is again).  By "creating" we mean   
organizing the code according to its its own internals as well   
as that imbedded in the SQL source.  
 
If the completion proof fails due to a failure in the query, it   
has a gadzillion return codes detailing the possible failures.    
Get through these and the completeness proof now has an   
optimal logical organization ready for execution.  
 
Whew!  
 
It now becomes the responsibility of the exhaustive true/false   
proof to execute that optimized code against the rows of the   
tables in the database and to return all "true" instances, i.e.   
zero, one, or more.  Note that the data must exist and that   
different data, e.g. changes in the database from one   
execution to the next, can produce different results.  
 
Now what we have here is an instance of clausal logic.  Logic   
programming which relies on clausal logic relies on some   
independent means of generating "test" data.  SQL uses   
clausal logic.  Prolog, the most used fourth generation   
programming language, also uses clausal logic.  If we want to   
test a Prolog program, we have to somehow create the "test"   
data.  
 
Enter predicate logic.  Stage left.  Predicate logic associates   
values with a variable.  In essence it says for X with values of   
Y through Z, the following is true.  It then iterates the values   
of Y through Z in an expression involving X, keeping those   
values of X for which the expression results in "true" (zero,   
one, or more) instances.  Just like SQL and Prolog, except the   
software generates the data.  
 
If the assertion results in zero true instances, it is "false".    
Otherwise it is "partially" true, i.e. it has one or more true   
instances, possibly all values in the range.  
 
Now pay attention.  We have two generating processes here.    
One involves the global logic of the source (and, yes, it is the   
actual source, not intermediate code, on which optimization   
occurs), which the software as part of completeness proof   
performs.  The other involves the generation of the test data   
based on programmer specified values, which again the   
software performs.  
 
Let's assume that we have our interpreter working with our   
two-stage proof engine.  Somewhere in our source we have a   
statement like "dcl henry char (20) varying range ('orange',   
'blue', 'red', 'Ford', 'Chevy','Simi Valley');"  We take our cursor   
and we "mark" it.  We click on the RMB (Right Mouse Button)   
and from the pop-up menu we select "test".  A window   
appears asking for a value for "henry".  We type in "Buick".  It   
returns "false".  Otherwise it would store the value in the   
location specified by henry.  
 
Now you say, "Wait a minute.  You, not the software, created   
the test data."  True.  I tried to give it a value outside the   
range specified and it rejected it.  Thus while I don't have an   
ability to override the values specified, I do have the ability to   
specify an unlimited range of values to use in any test.  
 
For example, if I use "henry" on the left-hand side of an   
assignment statement, e.g. "henry = somestringvalue;", the   
executable code will check the content (value) in   
"somestringvalue" against those specified for "henry".  Any   
none match (false) will produce an error condition.  
 
If I have a "capable" programming language like PL/I, I could   
have a code segment like "on range(henry) begin;.... end;" to   
allow me to recover within the program from an obvious error.  
 
Take another look at "dcl henry char (20) varying range   
('orange', 'blue', 'red', 'Ford', 'Chevy','Simi Valley');".  This puts   
the onus on the software to check any string value result   
before assigning it to henry.  Otherwise the onus belongs to   
the programmer.  If he happens to be new to the project or   
being human simply forgets the rule, an error in execution can   
occur.  
 
The onus not only falls on the programmer, but the writing of   
the checking logic prior to assigning a string value to henry   
does as well.  If a change occurs in the "range" attribute of   
henry, the necessary checking logic must occur for every use   
instance as well.  In point of fact no such "range" attribute   
exists in PL/I, thus the programmer must know the rules   
regarding value ranges for a variable as well as write and   
rewrite the checking logic for every use instance in every   
program.  You only have to miss one.  
 
Contrast this with having a "range" attribute and the   
responsibility on the software to insert the necessary   
checking code and to invoke the active "range" error when an   
exception occurs.  Remember in our system each source   
statement is automatically named and stored in a table in a   
database in our data repository/directory.  We make a change   
to a value in a range attribute, we create a new version of   
that statement.  We are then prompted how we want the   
effect the new version globally, i.e. in all its use instances   
across all programs, not just in the immediate program.  
 
Our example included just one statement.  It could have   
included (marked) any proper control structure at any level   
up to a program.  Mark any control structure, RMB to request   
a test, specify value ranges for the associated variables, and   
let the software enumerate the test data set instances for the   
exhaustive true/false proof.  
 
Get off the clausal logic.  Move on to predicate.  Get all that   
logic programming has to offer those of us mired in our third   
generation mentality.  
 
 
=====================================================  
 
To unsubscribe from this list, send an email message  
to "steward@scoug.com". In the body of the message,  
put the command "unsubscribe scoug-programming".  
 
For problems, contact the list owner at  
"postmaster@scoug.com".  
 
=====================================================  
 
  
<< Previous Message << 
 >> Next Message >>
Return to [ 22 | 
February | 
2006 ] 
  
  
The Southern California OS/2 User Group
 P.O. Box 26904
 Santa Ana, CA  92799-6904, USA
Copyright 2001 the Southern California OS/2 User Group.  ALL RIGHTS 
RESERVED. 
 
SCOUG, Warp Expo West, and Warpfest are trademarks of the Southern California OS/2 User Group.
OS/2, Workplace Shell, and IBM are registered trademarks of International 
Business Machines Corporation.
All other trademarks remain the property of their respective owners.
 
 |