
























|
 |
Articles: Programming - A Walk Through the Code
|
|
Programming - A Walk Through the Code
Although there are many articles, web sites and books detailing the history of computing, the wonderous inventions and the people behind them, there's something of a gap between the silicon chip and playing Quake 4. Software is the 'missing link' between man and machine but where does software come from? Do computers magically generate software or do pixies from wonderland deliver programs and applications in the middle of the night? Yes dear reader it's another slow period at work so we're going to look at yet another less than rivetting subject and this sad, pathetic excuse for a contrived introduction is how we're going to get onto the subject of programming...eventually. Anyway, back to the subject in hand.
Note: This document aims to be a brief history of programming and the languages involved. At the time of writing though there are over 2500 known programming languages and covering all of them would send me even madder. Apologies if I've missed out 'your' language and, while I'll try to do justice to the 'biggies' such as COBOL and FORTRAN, covering academic and niche languages such as POP-11 just ain't going to happen. Oh, and I don't consider SQL to be a programming language - it queries databases and at this it's good but I certainly wouldn't like to create a word processor using it (so it stays out).
Software? What's The Point?
Most people are aware of this entity known as 'software' but what is it, where does it come from and why do we need it? A quick look at the history of computing hardware will show that as machine's have evolved, so too has software but why do we need software? Originally computing hardware was designed to do just one job and only one job. The machine knew what it had to do and it did it, but what about a machine that could do many jobs? Yes, instead of having ten machines to do ten jobs, why not have one machine that can do all ten. Now the simple answer to this would be to combine all ten machines into one and, outside of the computing arena, manufacturers often adopt this which is why we end up with multi-function devices that can tell the time, act as a radio, and make tea in the morning. This works when you're dealing with a strict set of set tasks but what if you don't know what you want to do yet or you have so many tasks to do that combining them together would make such a complex and cumbersome machine that it would take a lifetime just to read the manual?
Withdrawing from creating the world's largest chaos engine, we can look at this in a slightly simpler way. Suppose you have one machine that can add two numbers together, one machine that can subtract two numbers, and one machine that can multiply two numbers. You have three boxes but it'd be a lot better if they were all combined into one box. The problem that you now face though is how to tell your combined 'wonder' machine what it's supposed to do with the pair of numbers that you input into it. This is very simple stuff but it does demonstrate the problem: you need to be able to communicate with the machine without having to physically change sprockets, cogs, gears or whatever it is that your machine is using to do what it does. It's also the problem that the early computer developers faced.
The First Generation - Binary
It Shouldn't Be This Tough
The race to build a 'generic' computer that could do any task asked of it had thrown up many wonderous (and often monstrous) machines. ENIAC could perform calculations faster than any human but it could only do one job and if you wanted to change that job, the machine had to be physically re-wired (in ENIAC's case an arduous task that could take several weeks). Conrad Zuse's Z3 machine had already beaten ENIAC to completion (by several years) but it also employed a mechanism for entering not only data but also the instructions telling the machine what to do with that data. Christened Plankalkül it's now identified as the world's first computer programming language and was certainly a step in the right direction. WWII soon put paid to it though and Plankalkül wouldn't actually receive a programmer's reference guide until 1972 - really useful given that the machine itself only existed in rebuilt form in a museum.
So ENIAC, public favourite that it was (at the time), epitomised the vast majority of computers in its hardwired tasks. The concept of modifying the machine's task was very much alive and well but ENIAC's actual hardware was a little less brilliant and lacked the ability to remember what it was supposed to do with all of the data it was given. The result was that it ran through a physically wired set of instructions and would continue to use them until it was physically changed. With the wiring in place ENIAC could do what it was set to do but changing the task (or program) required swapping hundreds (and sometimes thousands) of wires, physically connecting the various elements of the machine so that it was configured to do what it was required to do. More complex certainly but still the same problem as faced by our three box 'super' calculator.
As Zuse had proved (although no-one knew it due to the war) the future lay in seperating the program from the hardware so that as the machine needed to do a new task it was simply fed in, in exactly the same way as data was already being fed in. While ENIAC wasn't able to handle this, other machines were appearing that could. Of course communicating with the machine provided all manner of problems in itself.
As I write this on my shiny desktop PC it's all too easy to click the mouse, move the window, position the cursor and enter text via the keyboard. It's easy, and every machine on the planet understands English, numbers, sound, pictures and every form of communication that man can dare to throw at it. Well if only that was the case...
It All Comes Down To 0's and 1's
At their core, even modern machines are still binary by nature and they understand nothing but binary values - 1 and 0. The evolution of hardware and software has allowed machines to appear to understand everything else but, stripped bare, computers still 'think' in 1 and 0. The letter 'A' equates to a stream of 1's and 0's by way of an integer value. If we adopt the common ASCII format using an 8 bit storage, 'A' transforms into 65 (its ASCII value) and then to 01000001 (its binary value). The machine 'knows' what 01000001 represents and we (as people, I'm assuming that there are no animals or plants reading this) what 'A' represents. It's the software in between makes the translation for us. This might seem to be a world away from Mac OS and Windows (boo) but this is actually how deep we need to go if we're to understand the need for software and how it's evolved over time.
Surely that must be the end of our little insight though...isn't it? We can tell the computer what we want it to and it'll do it. Sadly it's not that easy. Although we've already stated that we can can represent 'A' as 01000001 it doesn't mean that the computer knows what it is, or even what to should do with it. Presented with 01000001 the computer will effectively shrug it's shoulders and do nothing. The machine doesn't know what it's supposed to do with it and whether this stream of numbers is an instruction telling it do something, a number for use in a calculation, a representation of some text etc. What's needed is a way to distinguish instructions from data and then ways to identify what the data is (a stream of binary digits could be representing a whole number, a floating point number, a character etc.). With this in place we could now tell the computer whether we're giving it data or whether we're telling it to do something with that data. All great stuff but how do we tell it what to actually do?
It Might Just Do The Job
Nothing beats a good example and, in place of a good example, we'll create our own little virtual computer which can do a few simple tasks (add, subtract and multiply). As with all machines there are rules that govern how we need to structure any instructions we need to make and we'll define that our machine needs two numbers to be fed into it, followed by the instruction telling the machine what to do with it. The machine will 'remember' the two numbers and then add, subtract or multiply them, returning the result to us when it's done. As we're looking at a binary machine (did I forget to mention that? Well tough) we need to be able to identify what's data and what's an instruction - therefore we need to supply a value telling the machine what we're passing in (the 'type'), and then the value that we're passing in (the 'value'). We'll stick with the 8 bit storage we used before (meaning that each value must occupy 8 binary digits) so we can think of a 'chunk' as being a 'type' followed 'value'.
We still have no way of identifying data and instructions so we'll define the following convention: instructions have the 'type' set to 00000001 and data has the 'type' set to 00000000 (therefore to pass in some data we need to pass 00000000 and then the 'value'). In our machine, if we wanted to pass in the numbers 2 and 9 we'd therefore need to pass 00000000 00000010 00000000 00001001 (or, in English, 'data' 2 'data' 9). It's hardly brilliant but it works. This covers the data but what about the instructions? We know that '+' tells us to add something, '-' tells us to subtract something and 'x' tells us to multiply something. For our machine we need something similar but, as we're stuck with binary, it's going to be 1 and 0 based:
Add = 00000000 Subtract = 00000001 Multiply = 00000010
This is logical and will get the job done and, just as with the data, we'll need to supply the 'type' value before we supply the operation itself. In our machine if we wanted to tell it to multiply we'd therefore need to enter 00000001 00000010 (or, in English, 'instruction' multiply). Combining the data example and the instruction example together we get 00000000 00000010 00000000 00001001 00000001 00000010 (or, in English, 'data' 2 'data' 9 'instruction' multiply). Our little machine would then return 00010010 (or '18'). All of those 1's and 0's just to do a simple multiplication and our 'program' wouldn't even allow us to enter new values (so we'd be stuck with 2 and 9 as the data). And we never did get anywhere near to creating Unreal Tournament or Adobe Photoshop.
While the above is a bit of a convoluted and drawn out example, it does demonstrate the problems that the early computer designers faced when they had to communicate using the computer's native language. Talking to the machine in binary was difficult and ardous but it was also the only option available and early machines were programmed in this way. Naturally the chances for error were incredibly high (just one errorneous bit could ruin everything) and this limited the complexity of programs and seriously challenged even the most mathematically gifted of users, operators and designers.
Help was at hand though and in 1949 a simple language called 'Short Code' appeared but it wasn't quite what modern languages would call 'ideal' - in fact it wasn't really a language but we'll come onto that. Although the first 'language' specifically used on a digital computer (aside from Zuse's Plankalkül) Short Code was paper based and it still required that the resultant 'code' being translated, by hand, into binary (making it more of an aide than an actual language). Yes it was easier to understand (when on paper) but it was just as difficult and error prone to actually enter.
The Second Generation - Assembler
The Magic of Symbols
With binary programming being so difficult, it fell to the British EDSAC machine to lead the way with the introduction of assembly language. In the first step down the road of automatic translation, assembly language allowed users to enter programs in a far more familiar way, using short sequences to represent instructions etc. (e.g. MUL indicated multiply, SUM indicated add). The machine itself then translated the assembly language into the pure binary 1's and 0's (adding whatever was needed to differentiate between data, instructions, numbers, letters etc.). While binary programming had been first generation, assembly language was considered second generation but it still wasn't what we'd today consider a 'modern language'.
Today if you wanted to learn how to program you might go to the local book shop, buy a book, go home and start entering the code and watch it run. In the late 1940's and early 50's this wasn't an option and, while assembly language was a huge leap forward, it still wasn't perfect. As we saw with our virtual machine we were able to define precisely which values corresponded to which instruction and how we could differentiate between data and instructions. This was purely our own decision and while we used 00000000 and 00000001 to distinguish data from instructions, we could just as easily have used 11111111 and 01010101. This was the exact same problem that faced the early machines as, due to their bespoke nature, no two machines used exactly the same set of instructions or formatted their instructions the same way. We used 8 digits but we could have used 16, 24, 32. Our instructions were numbered from 0 and increased but we could have started at any point or just chosen them at random.
Assembly language, while simplifying programming, didn't address this inconsistency problem as each machine now had it's own unique assembly language. Again this was partly down to choices made by the design team and also partly down to what features the machine offered (one machine may have offered a multiplication function, another may have simply implemented an addition function and repeatedly added values together to simulate multiplication). The scarcity of machines kind of rendered the problem academic but it did mean that the sharing of information and the movement of experts was limited - your knowledge of programming one machine could be next to useless on another machine as they both used entirely different languages (in human terms one spoke French, another spoke Spanish). What was needed was something new and IBM were about to come to the programming world's rescue.
Example Assembler code (Intel Pentium) to extract values from memory and draw them to the screen:
.model tiny .code .586P
ORG 100h start: call fillscreen; mov ax,4c00h; int 21h; fillscreen proc mov esi,0FFFFFF70h; mov edi,0B8000h; mov cx,160; mov ah,1Eh; myloop: mov al,fs:[esi]; mov fs:[edi],ax; inc esi; inc edi; inc edi; loop myloop; ret; fillscreen endp end start
The Third Generation - The 3GLs
Enter The Compiler
IBM had entered the digital computing industry relatively late but had quickly become the number one player in the field, offering a range of machines capable of different tasks for different markets. It was this range of machines that was causing problems though as, even though IBM had created them all, they still all used their own unique sets of instructions, unique formatting etc. While programs and applications could be developed for one machine, they'd have to be totally re-written to work on another and this was causing frustration as the lack of programmers meant that it was taking far too long for software to become available. The solution was to get everything talking in the same language.
In 1951 a mathematician and programmer by the name of Grace Hopper had started work on a program that she hoped would make life far easier for herself. Her aim was to create a program that would translate English into something that the computer could understand and work with, freeing up her time and letting her get back to the mathematics that she much preferred working on. The project was called the A-O-compiler (or AT3) and would form the basis of computer programming thereafter.
Just as with assembly language, the 'compiler' aimed to translate from a 'human' language into the binary that the machine could understand. Unlike assembly language though, the language that the compiler translated from (i.e. that entered by the user) was no longer tied to the hardware so while even assembly language was limited by the instructions and standards imposed by the hardware designer, the language understood by the compiler was totally arbitrary. This wasn't to say that the compiler itself was a simple program as it still had to be written either in pure binary or in the assembly language available on the target machine but it offered a layer of abstraction for the programmer and did the hard, laborious work of translating into binary. Programmers now only had to worry about programming the language and let the compiler worry about converting that into the corresponding instructions (or sets of instructions) needed by the actual hardware.
Science Gets A Voice - FORTRAN
A-O had already inspired Alick Glennie to develop the AutoCode compiler for the Manchester Mark 1 machine and an algebraic translation system had been developed in 1953 for the MIT Whirlwind but in 1954 IBM started work on something that would gain far wider acceptance - FORTRAN. Even if it would take another three years for it to be finished.
Developed initially for the IBM 704 machine, FORTRAN (FORmula TRANslation) was designed specifically for the scientific community and included such concepts as floating point numbers and even arrays of values (as well as offering commands to make decisions (IF) and even loops (DO)). Computers had been available for several years by the mid 1950's and as science was starting to make real use of the power of digital computing, the need had arisen for scientists to be able to use computers. The nightmare that was binary (and even assembly language to a lesser degree) was a major stumbling block and IBM's FORTRAN simplified the process enormously. There were also other benefits though and, as the program was no longer tied to a specific piece of hardware, it became possible for programs written on one machine to be entered into an entirely different machine. Provided that there was a compiler available that could translate the FORTRAN program into something that the target machine could understand, it would work.
Example FORTRAN code to input two numbers, add them together, and output the result:
program add c This is a simple program to read 2 numbers and print the sum c You'll notice that all lines with a comment on them begin with a 'c'
implicit none real a,b,s
c Ask for some user input print *, ' Please enter two numbers separated by a comma or space'
c Read the data read *, a,b
c Now calculate the sum s = a + b
c Print out the results with a description print *, 'The sum of ', a,' and ' , b print *, ' is ' , s stop end
Designed By Committee...Ignored By The King
If a FORTRAN compiler was available, FORTRAN code would run. That was the theory but in practice FORTRAN had limitations, and the computing community knew it. IBM had invested a great deal of time and money in FORTRAN and was keeping tight control of it, making sure that it was only available to IBM customers and would only run on IBM hardware (FORTRAN compilers for non-IBM hardware simply didn't exist). For IBM this was great but outside of Big Blue's world it caused something of a problem. In 1958 a committee of international computer experts set out to develop something that would rival FORTRAN but not be controlled by a multi-national (and therefore used as a money spinner). The result was ALGOL-58 (ALGOrithmic Language) which aimed to be a more general form of FORTRAN but resulted in trying too hard to be all things for all men (or machines in this case).
Intended to be machine independent ALGOL focused purely on the mathematical side of tasks and simply couldn't stray into areas such as input and output (as these were still too bespoke - what was implemented on one machine was implemented in an entirely different way on another machine...if it was implemented at all). This caused problems as it became very difficult to share code across machines. Yes the core functionality was fine but to get the code to work on your particular machine you still had to tailor the software to fit your hardware. It was hardly an ideal solution and IBM's refusal to support it (FORTRAN was selling excellently so why upset things?) meant that ALGOL never managed to become as popular as it might have been.
Example ALGOL code to input a stream of numbers and then output the average value:
// the main program (this is a comment) begin integer N; //Read how many numbers the user is going to input Read Int(N);
begin real sum, avg; integer i; sum:=0;
//Get the user to enter the values for i:=1 step 1 until N do begin real val; Read Real(val); sum:=sum + (if val<0 then -val else val) end;
//Output the result avg:=sum/N; Print Real(avg) end end
With FORTRAN an immense success, IBM could have sat back but instead pushed onwards and, in 1958, released FORTRAN II. More of an evolution rather than someting new, FORTRAN II did still advance the state of programming. Computing was still a new industry and the machines on offer, although pushing the boundaries of technology, were far from reliable. By 1958 most machines were offering decent performance but reliability was still a problem and storage was still relatively small. Binary programs had been short due to the inherant nightmare that was programming in binary but FORTRAN had opened up a new world to programmers and programs were starting to appear that were huge by comparrison. Although 300-400 lines of code is tiny by modern standards, it was enough to cause problems in 1958 and the original FORTRAN would either give up or it would take so long to compile that a hardware failure could quite easily ruin the process, forcing it to be started all over again.
FORTRAN II allowed programs to be broken down into smaller chunks (sub-routines) that could then be compiled independently and then combined together. This concept of sub-routines was vitally important and not only solved the compilation problem but created a new way of thinking when it came to programming as regularly used pieces of code could be 'procedurised' and then called as and when needed rather than having to repeat them time and time again (which meant that if there was a problem you only had to fix it in one place (the sub-routine) rather than in 18 places scattered throughout the program, forever worrying that you'd missed an instance of it). Eventually FORTRAN II would be replaced by FORTRAN IV in 1962 and FORTRAN 66 (in 1966) but the next major milestone for the language was the new version of FORTRAN released in 1977. This new version introduced the ability to handle text strings and not only make decisions through IFs but also do something else if the conditions of the IF weren't met...the classic IF ELSE . A further release in 1990 (imaginatively titled FORTRAN 90) keeps FORTRAN alive even to the time of writing...even if it is still used primarily within the scientific community.
Like FORTRAN though, ALGOL was released in a revised version in 1960 (ALGOL-60) but, again, failed to really find widespread acceptance (although it did fare far better in Europe than it did in America, lasting until the end of the decade) - it's ideas though would influence a great many languages to come. With ALGOL effectively out of the picture, IBM looked to have the monopoly on programming languages once again but a couple of languages called LISP and COBOL set themselves up as challengers for the king programming language title.
Developed by John McCarthy between 1958 and 1959 LISP (LISt Processing language) was unlike FORTRAN and was intended as a language for programming artificial intelligence. Identified by its use (and, more often than not, over use) of brackets, LISP would eventually introduce garbage collection (it cleaned up after itself, freeing up memory) and recursion (in that a routine could call itself) and provded to be a favourite torture tool for computer science lecturers the world over (or was it just me who had to wrangle with it?). It's use in the field of artificial intelligence did eventually come to fruition but in 1959 LISP had to take a back seat as one of the big languages was about to be released and even the all-powerful FORTRAN would find itself ousted as the programmer's language of choice: COBOL.
Example LISP code to work out if two numbers are odd or even:
(defun CHECK (x y) (format t "Your two numbers are") (cond((and (evenp x)(evenp y)) 'both_odd) ((and (oddp x)(oddp y)) 'both_even) (T 'there_a_mixture) ) )
The Big Guy Arrives - COBOL
Just as the scientific community had accepted and welcomed computing at the start of the 1950s, by the end of the decade business was starting to recognise the advantages that computing had to offer and machines were starting to appear in offices around the world. Business faced the same problem that the scientists faced though - programming was practically a black art. IBM's FORTRAN had made the scientist's job easier but it was tailored for the needs of the scientist - business had different needs. As with ALGOL, the decision to make a business based programming language fell to an open forum rather than a single manufacturer and, in 1959 the Conference on Data Systems and Languages (CODASYL) defined the rules for the Common Business Orientated Language - COBOL.
FORTRAN was good at what it did but still required a fair amount of brainpower to understand. COBOL, by comparisson, was designed to be easy to read and understood not only by novice programmers but even by, heaven forbid, business managers. This was a big boost for the business user and, unlike ALGOL, COBOL was capable of being implemented on many hardware platforms but still retain portability. Now the option existed to create software for one machine and then use it on another machine...and not just another machine by the same manufacturer as had been the case with FORTRAN.
Optimised for the task of processing business orientated data (although it did find many uses outside of the business sector), COBOL rapidly spread and imbedded itself into the core of many businesses around the world and, although long and somewhat wordy (it's often been claimed that COBOL code includes both the actual code and the documentation that goes along with it - and we're not just talking comments here) became firmly entrenched. Even today (November 2005) COBOL based software still rears its ugly head from time to time despite being hopelessly out of date and nowhere was this better demonstrated than in the year 2000 debacle. With the rollover into the new century it was feared (and in some cases known) that hardware and software would reset itself to 1900 rather than 2000 and many young programmers suddenly found themselves presented with a heap of COBOL code and told to 'fix that' - a boom time for the old programmers though (sadly not me - firstly I'm not old enough and secondly I've never actually seen any COBOL code, let alone coded any).
Example COBOL code to input two numbers, add them and output the result:
000100 ID DIVISION. 000200 PROGRAM-ID. ACCEPT1. 000300 DATA DIVISION. 000400 WORKING-STORAGE SECTION. 000500 01 WS-FIRST-NUMBER PIC 9(3). 000600 01 WS-SECOND-NUMBER PIC 9(3). 000700 01 WS-TOTAL PIC ZZZ9. 000800* 000900 PROCEDURE DIVISION. 001000 0000-MAINLINE. 001100 DISPLAY 'ENTER A NUMBER: '. 001200 ACCEPT WS-FIRST-NUMBER. 001300* 001400 DISPLAY 'ANOTHER NUMBER: '. 001500 ACCEPT WS-SECOND-NUMBER. 001600* 001700 COMPUTE WS-TOTAL = WS-FIRST-NUMBER + WS-SECOND-NUMBER. 001800 DISPLAY 'THE TOTAL IS: ', WS-TOTAL. 001900 STOP RUN.
Languages, Languages Everywhere
With two big players in the field, there should have been little room for anything else but while FORTRAN and COBOL were both good at what they did, it was what they didn't do that left the field open for other languages. FORTRAN was aimed at science and was ideal for number crunching. COBOL was aimed at business and was also ideal for number crunching. What neither language did well was handle text, and as that was how most people communicated, it still left a gap between man and machine.
Developed by Bell Laboratories and released in 1962, SNOBOL (StriNg Orientated symBOlic Language) was aimed not at number crunching problems but string manipulation tasks and included a variety of high level string processing functions. Programmers could easily search, dissect, append, cut, paste, add, split, combine and process text based information in a way that had been practically impossible beforehand. While good at what it did though SNOBOL didn't really gain much of a foothold and only really saw any major interest when the FASTBOL and SPITBOL (SPeedy ImplemenTation of snoBOL) compilers released in 1971.
Example SNOBOL code to count the number of words in a text file:
&TRIM = 1
WORDPAT = BREAK(&LCASE &UCASE) SPAN(&LCASE &UCASE "'-") . WORD COUNT = ARRAY('3:9',0)
READ LINE = INPUT :F(DONE)
NEXTW LINE WORDPAT = :F(READ)
COUNT = COUNT+ 1 :(NEXTW)
DONE OUTPUT = "WORD LENGTH NUMBER OF OCCURRENCES" I = 2
PRINT I = I + 1 OUTPUT = LPAD(I,5) LPAD(COUNT<I>,20) :S(PRINT) END
Elsewhere research was proceeding on several fronts but most significant were Kenneth Iverson's APL (A Programming Language) and John G. Kennedy and Thomas E. Kurtz's BASIC (Beginner's All Purpose Symbolic Instruction Code) - we'll come back to BASIC later though.
Although there were few languages around at the time, they did all follow a similar pattern of having a series of simple commands combined to perform a more complex task. The syntax may have differed by they basically did the same thing. APL on the other hand was radically different and didn't even look like any other language. Relying far more on algebraic formulae than commands, APL used a heavily extended character set and programmers could easily produce code that was nigh on unintelligible (I would give an example at this point but the 102 key keyboard I'm typing this on still doesn't have enough symbols to do the job). David Given was noted as saying "APL, in which you can write a program to simulate shuffling a deck of cards and then dealing them out to several players in four characters, none of which appear on a standard keyboard." - and he was right. Despite its problems though, APL was hugely appreciated and first saw the light of day in a commercial product when none other than IBM created APL/360 in 1964 for their 360 series of machines.
Example APL code to open and display a hexadecimal/ASCII format file:
[0] Z{<-}HEXDUMP F;B;E;H;N;P;Q;V;#IO [1] @ Hex dump of file F [2] #IO{<-}0 @ use index origin 0 [3] [4] @ Read the file (using APL*PLUS operations) [5] N{<-}-1+0{max}{max}/-#NNUMS @ available tie number [6] F #NTIE N @ open the file [7] E{<-}#NSIZE N @ file size [8] V{<-}#NREAD N,82,E,0 @ read file as character data [9] #NUNTIE N @ close the file [10] [11] @ Form the hex dump [12] Q{<-}16 @ display 16 bytes/line [13] N{<-}{ceiling}E{divide}Q @ number of lines [14] Z{<-}8 HEX Q{times}{iota}N @ addresses [15] Z{<-}(0 2+{shape}Z){take}Z @ add two blank columns [16] H{<-},' ',2 HEX #AV{iota}V @ data in hex [17] P{<-}(Q{times}3){reshape}' ' @ padding for short last row [18] H{<-}(N,Q{times}3){reshape}H,P @ turn hex display into a matrix [19] Z{<-}Z,(0 3+{shape}H){take}H @ append it to the result [20] B{<-}#AV[127],32{take}#AV @ nonprinting chars [21] V[(V{epsilon}B)/{iota}{shape}V]{<-}'.' @ change 'em to "." [22] Z{<-}Z,(N,Q){reshape}V,P @ append ASCII display to result
[0] Z{<-}N HEX V [1] @ N-digit hex representation of values V [2] Z{<-}'0123456789ABCDEF'[{transpose}(N{reshape}16){represent}V]
Spaghetti Coding
1964 was a bit of a watershed for programming, although few would notice it at the time (or even afterwards - history can be so cruel). APL had gained acceptance by the 'big boys' but it also marked the year that Kennedy and Kurtz's BASIC first sprang into being. BASIC was originally intended as a teaching tool for those starting out in the world of programming but rapidly spread outside of the education world and out into the 'real' world. The language was certainly simple to use and learn but it included many elements that would marked it out as being a thing of horror rather than a work of art.
So on the fateful morning of 1st May 1964 (at about 4am if reports are to be believed) the very first BASIC program was run and the programming world would never be the same again. Perhaps I'm over-dramatising the point (I do have to do something to keep interest levels up though) but BASIC would become the bane of many a programmer's life. As a teaching language it was fine but its freedom and ability to do very unstructured operations could quickly lead to unintelligible code that followed an almost random pattern of execution. Most famous for it's GOTO statement, BASIC programs could jump about and become massive tangles of spaghetti which were nigh on impossible to follow. For example:
10 PRINT "Hello world" 20 GOTO 50 30 PRINT "Confused yet?" 40 GOTO 10 50 GOTO 30
Admittedly this example isn't too bad but the possibility for total illogical code and, even worse, code that could end up just getting stuck jumping around forever is pretty obvious. The emergence of the home computer in the late 1970's unfortuneately released the nightmare onto a wider audience and BASIC's simplicity to understand and learn meant that it was the language of choice for manufacturers who were desperate to widen the appeal of their machines to a market that, up until that time, still regarded computing and computer programming as a black art. And of course no two manufacturers ever released a version of BASIC that was 100% compatible with any other manufacturer's version of BASIC.
Example BASIC code to input two numbers, add them and output the result:
10 INPUT "ENTER TWO NUMBERS SEPARATED BY A COMMA:" 20 LET S = N1 + N2 30 PRINT "THE SUM IS ", S 40 END
All Things To All Men...I Don't Think So
So in 1964 BASIC was the spawn of Satan and APL was the language of the mathematics professor, leaving COBOL and FORTRAN as the two mainstream languages. IBM hadn't stood still though and had realised that, good as every language was in its specialist field, there was no language that was good at everything and could be used in all industries, markets etc. And of course the release of their System/360 series also warranted the need for something that could show the machines off to their maximum potential. The result was Programming Language 1, or just PL/1 (originally it was to be called NPL (New Programming Language) but was changed to avoid confusion with the UK's National Physical Laboratory). IBM wholeheartedly adopted PL/1 but elsewhere support was less than enthusiastic. Yes the language was all encompassing (it incorporated both floating point, integer, and list processing capabilities) but this was also it's major problem (in most people's eyes). The vast scope and size of PL/1 made it too complex and large for most programmers to deal with and was hardly an ideal starting point for those new to the programming world. IBM persisted though and it's still in use to this day.
Example PL/1 code to repeatedly output the text 'Hello world':
HELLO: PROCEDURE OPTIONS (MAIN);
/* A PROGRAM TO OUTPUT HELLO WORLD */ FLAG = 0;
LOOP: DO WHILE (FLAG = 0); PUT SKIP DATA('HELLO WORLD!'); END LOOP;
END HELLO;
With 1964 being such a big year, the following years seemed a little devoid of any major language innovations. Instead there were various tweaks and updates (FORTRAN 66, LISP 2, SNOBOL4 etc.) but nothing that would really shake things up much. Then 1968 rolled around and a monster from the past raised its ugly head again (amongst other things - 1968 was another busy year in programming land).
1968 - The Birth of Perfection
ALGOL had promised much but failed to really gain widespread acceptance due to it's inability to supply a standard set of input/output specifications but in 1968 a new ALGOL, ALGOL 68, appeared. Designed, once again, by committee, ALGOL 68 was soon identified as being a monster of a language that received scorn from many programming experts, including some who actually sat on the committee to design the thing. It's complexity made it a nightmare to implement and perhaps C.A.R. Hoare summed up the design of ALGOL 68 perfectly when he said "I conclude that there are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies and the other way is to make it so complicated that there are no obvious deficiences."
Aside from ALGOL causing more arguements and problems, elsewhere COBOL was back in the headlines. Having become the dominant language in the computing world COBOL was granted an American National Standards Institute (ANSI) standard. Despite the fact that it had been available for several years the new ANSI-COBOL was now the de-facto standard that all COBOL implementations could be measured against and it guaranteed that any ANSI compatible implementation of COBOL would work on any other ANSI compatible implementation of COBOL, regardless of hardware, environment etc. Of course the use of the language then started to decline and the rest is history.
The final big event of 1968 fell to a chap by the name of Niklaus Wirth who, having been vocal in his opposition of ALGOL 68, set about starting work on his own language - Pascal. Named after Blaise Pascal (famous French computer trailblazer) the language would not be commercially implemented until 1970 when the CDC-6000 series gained a Pascal compiler but its impact was profound (Note: I apologise in advance but I'm a Pascal programmer by trade so I'm going to be bigging this one up a bit =;) ).
Like BASIC before it, Pascal was initially designed as a teaching language but, unlike BASIC, it was very strongly typed and structured - the ALGOL influence was blatantly obvious though. Programmers were encouraged to use sub-routines and the like but the spaghetti like code possible through BASIC's reviled GOTO command was far harder to achieve (believe me, you really do have to try hard). Wirth designed Pascal to be simple yet powerful and included what he considered to be the best elements of many of the earlier languages. The result was a language that was easy to learn but also prepared programmers for other languages (unlike BASIC which tended to corrupt the mind) and could actually be used in more than just the education market.
Example Pascal code to repeatedly input a value and output various calculations based on that value:
program Arithmetic; const ExitValue = 0.0; var X : real; begin writeln('After each line enter a real number or 0.0 to stop'); writeln; writeln('X', 'Trunc(X)':16, 'Round(X)':10, 'Abs(X)':10, 'Sqr(X)':10, 'Sqrt(Abs(X))':15);
//Get the first value to process readln(X); while X <> ExitValue //Loop until we recieve our 'exit' value do begin //Output the calculation results writeln(Trunc(X):16, Round(X):10, Abs(X):10:2, Sqr(X):10:2, Sqrt(Abs(X)):10:2);
//Get the next value to process readln(X); end; end.
In practical terms Pascal was the greatest programming language in the history of the world and its use, although still relatively small even to this day, contributed more to human development than any other event, invention or cosmic spectacle. Through Pascal the stars were visited, communication with dolphins was established, and global poverty was abolished. Ok so maybe I'm stretching the truth on a couple of those examples but it's still a very good language.
The Fourth Generation - But Not For All
1970's Intelligence For Everyone
Programming had reached the 1970's and, with a seeming wealth of languages available, was there really any need for any more of them? Of course there was and the 70's would see the birth of new languages, the evolution of languages, and even the demise and death of languages (in practical terms). Of course by 1970 computing was no longer a brand new industry and it was obvious that many experts were starting to view the old 3rd generation languages as being outdated (despite the fact that the likes of Pascal had only just been developed). The push was now towards fourth generation languages and nowhere was this more apparent than in the release of PROLOG (PROgramming LOGic) and Forth.
Charles Moore's Forth had started life in the late 1960's at the Stanford Linear Accelerator Center when Moore set out to create a language that would further remove the need for programmer's to think in computing terms - kind of the same thought that every other language developer had dreamt of before. Although initially a research project Forth did have practical uses and even went comemrcial in 1973.
The other great stab at the 4th generation was a product of the technological giant that is France (although there was collaboration with the University of Edinburgh so the British are partly to blame too). PROLOG was designed as the language that would crack the problems of artificial intelligence...and any programmer who has ever dealt with a 4th generation language will know the frustrations and head scratching moments that these 'simple' languages cause. Instead of the more traditional series of simple commands that execute one after another, PROLOG (and its ilk) instead worked on the concept of having data and then defining rules to specify how that data is used to achieve certain goals. Sounds ethereal and floaty (i.e. illogical gibberish)? Trust me, it is. The existing approach of following a set sequence of tasks goes out of the window and instead users and programmers 'asked' the program questions and it answered them based on the rules that had been defined. In theory it sounds great but creating more 'traditional' tasks (i.e. writing a game, creating something to calculate and file taxes) would prove to be far too difficult.
Example PROLOG code to define and query a 'bicycle':
/* Describe the parts required to make a bicycle. Firt the elementary parts are given (basicpart). Then a description of various subassemblies. Ask: ?-partsof( hub, P ). to get all the basic parts required to make a hub. Ask: ?-partsof( bike, P ). for the whole bike. */
basicpart( rim ). basicpart( rearframe ). basicpart( gears ). basicpart( nut ). basicpart( spoke ). basicpart( handles ). basicpart( bolt ). basicpart( fork ).
assembly( bike, [quant( wheel, 2 ), quant( frame, 1 )] ). assembly( wheel, [quant( spoke, 20 ), quant( rim, 1 ), quant( hub, 1)] ). assembly( frame, [quant( rearframe, 1), quant( frontframe, 1 ) ] ). assembly( frontframe, [quant( fork, 1 ), quant( handles, 1 )] ). assembly( hub, [quant( gears, 1 ), quant( axle, 1 ) ] ). assembly( axle, [quant( bolt, 1 ), quant( nut, 2) ] ).
partsof( X, [X] ) :- basicpart( X ). partsof( X, P ) :- assembly( X, Subparts ), partsoflist( Subparts, P ).
partsoflist( [], [] ). partsoflist( [quant( X,N ) | Tail ], Total ) :- partsof( X, Headparts ), partsoflist( Tail, Tailparts ), append( Headparts, Tailparts, Total ).
append( [], L, L ). append( [X|L1], L2, [X|L3] ) :- append( L1, L2, L3 ).
As Easy As A, B, C
COBOL and FORTRAN had introduced third generation languages onto the world and there had certainly been a wealth of imitators, rip-offs and alternatives available by the 1970s. The introduction of Forth and PROLOG had brought fourth generation languages to life and the introduction of these newer more abstract languages quickly spelled doom and death for the older 3GLs. Actually it didn't as although 4GLs were a nice idea, in reality they just didn't work in the 'real' world. Besides which, one of the biggest, and in my opinion hideous, languages was about to be released onto the world: C.
Like most languages, C didn't just magically appear and instead it evolved from the earlier B (which itself evolved from BCPL and CPL). CPL (Combined Programming Language) had been spawned in the wake of the ever nasty ALGOL-60 and it it even managed to pre-date ALGOL-68 in that it tried to be all things to all people (instead of being specialised to just one industry). Like ALGOL-68 it eventually turned out to be big, inelegant and far too complex. BCPL (Basic CPL or Bootstrap CPL) took this behemoth and streamlined it, and, instead of aiming for the generic programmer, became optimised as a systems programming language (as opposed to a language that was better suited to writing applications). Bell Laboratories picked up BCPL and, mostly through the work of Ken Thompson, stripped out anything that they felt wasn't actually needed. Was this merely a whim or an academic exercise? Of course not and Bell had their eye on the mini-computer market that was springing into life in the late 1960s. Unlike mainframes, mini-computers had, by comparisson, limited memory and only a streamlined language was ever going to fit into them.
Like BCPL (and even Forth) B relied on just a single type of data and it was up to the programmer to interpret it as he/she needed to - characters, floating point numbers, integer numbers etc. were all just stored the same. This was fine on the older machines but as newer machines were starting to appear that supported concepts such as letters, B was starting to show its limitations. It was time for an update and as C followed B in the alphabet, so did the C language come about.
Charged with the task of updating B, Dennis Ritchie's C was closely tied to AT&T's UNIX operating system and it was through this that the language really exploded. Actually included as part of the OS, C stuck to the third generation approach employed by its predecessors but offered far more flexibility and power. FORTRAN had been, initially, tied to IBM hardware, and COBOL and the like had been (largely) designed by committees external to the computing manufacturers. C, as designed by Bell Labs, needed to be able to be run on different hardware from different manufacturers and this led to one of the language's true strengths - portability. Nowadays many languages are portable but, in 1972, languages that were intended for systems programming were still closely tied to the hardware that they were to be programming for - C wasn't.
At it's core C was fairly limited, instead relying on libraries of routines to handle input, output, communication etc. This gave the language it's flexibility and power but also allowed it the portability that made it so adaptable and led to its widespread use. With C all that was needed to make it run on a new piece of hardware were the libraries that actually interfaced with the underlying hardware. It's limited core also had other advantages and C programs could be written so that they were very efficient and, more importantly, quick to execute. By adapting the pointer approach used by Pascal (whereby programs can 'point' to values rather than just store the values themselves) C offered great power and control but this didn't come for free and programs often became difficult to follow.
So far I've been fairly positive about C, and, while it's a certainly got its fans, I'm not one of them (I'm a Pascal trained programmer and C just confuses the hell out of me). C certainly offers power and flexibility but it's this that is one of its major problems. While there are usually several ways to write the same piece of software, C goes beyond this and offers far more possibilities for misunderstanding and confusion. Its reliance on pointers makes it ideal for many tasks but it's all too easy to get confused between values and pointers and even end up with pointers to pointers and code that becomes horrendous to understand and maintain. These are the pitfalls, these are my pet hates - I live with them. Anyway, back to the job in hand.
Despite its flaws, C took the world by storm and quickly became the language of choice for programmers around the globe. For beginners it proved slightly too big a leap with its use of pointers and the like and it seemed that the much reviled BASIC was ideally suited to fill that particular need.
Example C code to repeatedly input in a lbs value, convert it to ounces and output the result:
include <stdio.h>
main( ) { int pounds;
/* Read first weight in pounds */ printf("\n\n\tWeight in pounds?"); scant("%d",£s);
/* Loop until user signals halt with negatie integer */ while(pounds >= 0) { /* Output the converted value */ printf("\n\n\tEquivalent weight in ounces: %d", pounds * 16); printf("\n\n\tWeight in pounds?");
/* Read the next weight in pounds */ printf("\n\n\tEnter a negative integer to quit."); scanf("%d", £s); } }
Back To BASICs
We've already looked at the problems of BASIC but, for all its problems, it was still a language that beginners could quickly understand. Programmers starting life on a mainframe or a mini-computer didn't have this problem (as, typically, they joined an existing team of programmers who could be used as teachers) but the emergence of the microprocessor was starting to see the release of machines aimed at the home user and it was this particular type of would-be programmer that BASIC came to the rescue of. BASIC was easy to understand but how could a BASIC compiler be worked into a machine that had precious little memory? Just as Bell labs had squeezed BCPL onto minicomputers (by stripping it down to become B) due to the lack of memory, the developers writing software for the first microcomputers faced just the same challenge - how to create a usable language that offered enough features and power but didn't require huge amounts of memory? 1975 would be the big turning point.
Getting a compiler to run on a machine that had as little as 4Kb of memory was always going to be a challenge but in 1975 the problem was cracked...and more than once. Although now largely forgottten now, Bob Albrecht and Dennis Allison saw their Tiny BASIC implemented run on just about every Intel and Zilog microprocessor (then) available. Taking up a measly 2Kb of memory it still allowed a 'massive' 2Kb for the program itself - more than enough for most users. Tiny BASIC was free but elsewhere the seeds of capitalistic doom were about to be sown. Again BASIC was the target language and William Gates and Paul Allen decided to turn their hands to creating a version of BASIC that could be run on the upcoming MITS Altair machine. Unlike Tiny BASIC, Microsoft BASIC certainly wasn't free, instead Gates and Allen received a royalty payment for every copy of the software sold.
The home computing boom of the late 1970s and early 80s brought programming to the novice user. BASIC was definitely the language of choice though and just about every home computer had a BASIC compiler released for it (occasionally BASIC wasn't the language of choice - the Jupiter Ace, for example, used Forth). Sometimes, as in the case of the BBC Micro, the compiler was actually built into the hardware as opposed to the more usual loading from magnetic tape. Using BASIC, home users could write all manner of programs that would revolutionise their lives and free them up from the drudgery of everyday life. In reality though this meant typing in page after page of program listings from the backs of computing magazines and then wondering why the hell they didn't work.
OOPs
Away from the home computer, programming was still ever evolving. By 1980 COBOL was long dead but the vast number of legacy applications that had been developed using it meant that it, and to a lesser degree FORTRAN (which had received an update in 1977), still reared its ugly head and would continue to do so for decades to come. Pascal was still considered an 'academic' language but Niklaus Wirth still had more to give to the programming world and, in 1980, officially released Modula 2. While its Pascal influence was obvious, Modula 2 was less rigid than Pascal and paved the way for the future. Sadly this wasn't to be the case and, despite eventually appearing on most hardware platforms, the language soon came up against a brick wall in the late 1980s.
By 1980 C had become the number one language of choice for the professional programmer (novice programmers were still mostly stuck with BASIC) but the language itself hadn't stood still and was more than ready to adopt the next 'big thing' in programming - Object Orientated Programming.
Object Orientated Programming (OOP) had been used in the groundbreaking work done at Rank Xerox's Palo Alto Research Centre in the 1970's and had led to the creation of the Smalltalk language and, subsequently, the graphical user interface.
Example Smalltalk code to count the letters in a sentence:
| s f |
s := Prompter prompt: 'Enter line' default: ''. f := Bag new.
s do [ :c | c isLetter ifTrue: [f add: c asLowerCase}}.
^f
But OOP wasn't a programming language. Instead OOP was a way of thinking. Instead of thinking of the program as a vast single entity, OOP prescribed breaking the program (or problem) down into smaller modules that all worked together. Instead of writing a program that asked for input, did some processing and then displayed some output, the OOP approach broke the problem down into a module that handled input, a module that handled processing, and a module that handled output. Then all that was needed was a small piece of code to use these other three modules. By defining how the modules talked, the 'controlling' code didn't have to worry about how they did what they did - just how to get them to do it. There were other benefits though as the input module, for example, could be used in another program or rewritten to handle something else (e.g. input validation) without having to modify the 'controlling' program.
Anyone familiar with programming will probably identify the above description and say "But you could do that with sub-routines" and they'd be right. The difference between sub-routines and 'objects' was that sub-routines only did one thing - objects went far beyond this. In our above example we used an input module, a processing module, and an output module. This is fine in programming terms but what if we want to create something more 'real'. If we wanted to create an 'apple' object we could define various things that we could do with an apple as well as the attributes of the apple. We could define a 'property' for the apple's colour and one for its weight. This is great as we could create an 'apple' and then specify that it's green and that it weighs 50g. Using the OOP approach we could do easily this but we could also create 'methods' that allow us to do things to/with the apple. We might, for example, create a method called 'eat'. Using the 'eat' method would set the apple's weight to be 0g (as we've just eaten it).
OOP was a major breakthrough and its use and advantages were quickly identified. Complex programs could now be broken down into smaller parts and be attacked by teams of programmers. Source code became easier to understand (assuming that everything was named sensibly and clearly) and it was the logical way to proceed. Outside of Smalltalk though (which had first appeared in 1972), very few languages could actually make use of it but, in 1980, Bjarne Stroustrup began work on a series of languages that were referred to as 'C With Classes'. Three years later these would lead to the release of C++. So C had gained OOP and looked to be the market leader (not hindered by the release of the first C compilers for home computers in late 1983/early 1984) but there were other developments and the venerable Pascal was about to make a major comeback.
So It Comes Back Down To Two
Software developer Borland stunned the world with the release of Turbo Pascal in 1983. Available for the IBM PC, Turbo Pascal brought the simplicity and power of Pascal to the desktop computer and provided almost the industry standard version of Pascal (certainly as far as the PC would be concerned). In one form or another Turbo Pascal remains with us to this day, evolving into the much applauded Delphi (although it would be Apple who'd release the first version of OOP based version of the language - Object Pascal For Macintosh in 1986). I unashamedly look at Turbo Pascal through rose tinted spectacles as once upon a time, in a classroom far, far away a tiny TheNeil (aged about 16) sat down, followed the isntructions to fire up the PC emulator on the Acorn Archimedes and launched Turbo Pascal. OK so I'd been defiling BASIC on a BBC Micro for a few years by then but this was real and typing 10 line programs into a command line didn't compare with actually taking a 'real' programming course. Now we were learning how to do real things using a real language. It was here that I built up my affection for Niklaus Wirth's creation and it's something that I still practice to this day, having devolved into a fully fledged (un)professional Delphi coder. So that was Turbo Pascal - the singularly most amazing piece of programming quantum-leap-o-logy ever made.
Away from desktops and home computers, one of the last major industry only languages was also released in 1983: Ada. Named after Lady Augusta Ada Byron who'd worked with Charles Babbage on his analytical engine, Lady Byron had regularly been identified as the very first computer programmer and to mark the fact Ada was christened after her. Designed for the US Department of Defence, Ada was intended for military applications where errors simply could not be allowed and its excellent exception and error handling were testament to this. Incredibly robust, Ada did not come without its problems and its syntax was considered to be overly complex and the very early compilers weren't able to produce hugely efficient (or quick) software.
Example Ada code to output the text 'Hello world':
with Text_To; use Text_To procedure hello is begin put("Hello World"); end hello
By the end of the 1980's the programming world had started to concentrate on either Pascal or C/C++. Yes some legacy systems still demanded FORTRAN or COBOL and there was always research and small pockets of development that used more 'obscure' languages but it was Pascal and C/C++ that ruled the roost. Microsoft's Windows had taken the world by storm (sadly) as the operating system of choice but this had led to problems that C and Pascal were ill suited to deal with.
I Can See Clearly Now
Traditionally the command line interfaces of machines had allowed a sequential execution of tasks. The program asked for input, the user enetered it, the program processed it, and then spat out the results. And that was that. The graphical user interface had presented problems as events no longer necessarily happened in a sequential manner. With three programs running at once, the user could jump between them. In fact having three programs at once meant that your program no longer had exclusive control of the screen so you had to create windows for it to live within...and then be able to react to events that happened to the window (e.g. the user resizing it or closing it). Microsoft had traditionally favoured C/C++ for this kind of development work but it was often difficult and very laborious to create event driven code (i.e. code that responded to events) using a traditional programming style/environment. Amazingly Microsoft's answer seemed to favour arguably the least capable of all languages - BASIC.
In March 1988 Alan Cooper demonstrated a little program of his to a fellow by the name of Bill Gates. Called Tripod, the program was little more than a concept but was enough to convince Microsoft to buy that concept. Three years later in 1991, Microsoft released Visual Basic. Having taken the ideas presented in Tripod and married them with Microsoft's own Quick Basic, Visual Basic allowed software to be designed in a far more graphical way and it handled all of the low level programming that was needed to allow software to work within the Windows environment. Now users could simply drag buttons onto a window, resize them and then attach code to only the events that they wanted to handle. In C this would have been extremely difficult but, using Visual Basic, all it took was a drag of the mouse to get the button onto the window and then a few clicks to get the 'Click' event selected. The user just entered the code that he/she wanted to run when the button was clicked and that was that.
Example Visual Basic code to output the text 'Hello world' when the user clicks a button (includes form definition):
VERSION 4.00 Begin VB.Form Form1 Caption = "Hello" ClientHeight = 6030 ClientLeft = 1095 ClientTop = 1515 ClientWidth = 6720 Height = 6435 Left = 1035 LinkTopic = "Form1" ScaleHeight = 6030 ScaleWidth = 6720 Top = 1170 Width = 6840 Begin VB.CommandButton Command1 Caption = "Hello World" Height = 975 Left = 2040 TabIndex = 0 Top = 2280 Width = 2535 End End
Attribute VB_Name = "Form1" Attribute VB_Creatable = False Attribute VB_Exposed = False
Private Sub Command1_Click() Cls Print "Hello World" End Sub
Visual Basic was certainly good stuff but it wasn't great stuff and it had some serious drawbacks. Firstly the BASIC language still had the same problems that it had always had but secondly, and possibly more importantly, Visual Basic did not actually create programs as such. Instead it created files that were interpreted when the user tried to run the software. This was hardly a major distinction but it made a major difference as the resultant software ran very sluggishly. C then received the 'Visual' overhaul and that only left Pascal and Borland did a significantly better job of it.
Rebranded as Delphi, Pascal's entry into the world of visual programming was a revelation. Unlike Visual Basic, Delphi produced 'proper' programs that not only ran at full speed (approximately 20 times faster than the equivalent Visual Basic application) but didn't need the software to interpret them so was far easier to distribute. Borland's development environment had always been strong even in MS-DOS but within Windows the Delphi IDE (Integrated Development Environment) was far more powerful and easy to navigate and use than Microsoft's offering.
The visual programming element was important in that it brought Windows programming to the masses (both novice and professional) but away from this little incident the programming world had been fairly stagnant for a quite a while. No new significant languages had been developed and the world seemed to have accepted that 3GLs in the form of Pascal, C and, heaven forfend, BASIC were the major languages. It was outside of the traditional computer that things were happening and it was partly because of this that the next 'quantum leap' was about to take place.
Just Read The HTML Script Darling
The rise of the internet had influenced a great many aspects of the computer industry but programming was an area that was seriously at a loss as to how to proceed. Even from the earliest days of computing, programs developed for one type of hardware could not be run on another type of hardware without the need for it to be re-compiled (if this was even possible at all given the potentially vast differences in hardware). The internet, at the time of it's initial creation, was machine independent being nothing more than a network of machines all connected together. How do you get these machines to run software if they could all be, potentially, different hardware?
The invention of HyperText Mark-Up Language (HTML) solved the initial problem of creating and representing data and information that could be displayed on any type of hardware but it relied on the availability of software to decode and display that information. Called a 'scripting language', in its raw form HTML was nothing more than text with some control elements (these controlled text colour, page layout etc.) and it needed software to understand this and translate it for the machine that was viewing it. Web browsers soon appeared and the problem looked to be solved, but perhaps it was all too easy.
As you view this now you've probably been to numerous sites on the internet and had all kinds of animations, sounds and adverts popup. Maybe you've played games online, chatted online and done your banking online. HTML can't handle this too well and it would need something that allowed programmers to create programs that were hardware independent before it would become easy. Of course in the early 1990's nothing like this existed...not until Unix giant Sun looked into it anyway.
Example HTML code to display the text 'Hello world':
<HTML> <HEAD> <TITLE>Hello World in HTML</TITLE> </HEAD> <BODY> <CENTER><H1>Hello World!</H1></CENTER> </BODY> </HTML>
The Sun Has Come Out To Play
In 1991 Sun had developed Oak, an interactive language that, sadly, didn't cause much of a stir. The rise of the internet though gave it a new lease of life in 1995, and a new name too: Java. Knowing that producing a hardware independent language is impossible Sun's Java worked by having an 'engine' installed on the machine and then have the engine interpret the code that was downloaded via the internet. To make it widespread all that was needed was an engine for each hardware platform. To some this is similar to how the early versions of Visual Basic were working (in that the programs were never really created - they were just translated at run time) and, in a sense, they were. Where Microsoft had hit a brick wall though, Sun didn't. Visual basic hadn't been free and it had only ever been released for the Windows (on Intel) platform. Java was different and certainly didn't cost anything and Sun wisely not only developed engines themselves but actively encouraged others to develop engines for other platforms. Yes it may not have been as all-encompassing as Visual Basic and it may not have offered as much power but by being truly hardware independent it gained acceptance and, unlike Oak, it succeeded.
Example Java code to display the text 'Hello world':
class HelloWorld { public static void main(String args[]) { System.out.println("Hello world!"); } }
Java was a big success but it certainly wasn't the first internet based programming language. The likes of Perl, Python and PHP had all offered hardware independent programming languages but had never really gained a foothold outside of the enthusiast and specialist markets. That's not to say that they weren't good as they were, but they just didn't gain the acceptance that they needed.
The Microsoft .Net Widens
By the end of the 20th century programming had come along way since the very first attempts to program in pure binary, but by the year 2000 the emergence of new languages had practically stopped within the mainstream. Pascal and C were still the major languages and both Delphi and C had received several updates. The languages were very much, from a desktop PC perspective, very closely identified with Microsoft and Borland (who, briefly, rebranded as Inprise...and then went back to being Borland). Microsoft had the financial weight and dominance but Borland's Delphi still ruled the roost. Despite having far fewer users worldwide, the Delphi IDE still demolished the Microsoft offerings for usability and speed. The shift of one of Delphi's major designers from Borland to Microsoft sounded like big news.
Microsoft had failed to create a market stranglehold with Visual Basic and its offshoots but at the dawn of the 21st century Microsoft made sure that its new .Net technology would be far more difficult to dismiss. Java had done a fantastic job of bringing the internet to life but it still had its limitations and, despite various technologies being bolted onto Pascal and C, web development was still far from easy when you needed to go beyond static information. Microsoft recognised this and devised its response - .Net. Using .Net, developers could easily create web sites (as well as more 'traditional' applications) that provided plenty of functionality but weren't forced to worry about client machines, server machines etc. The .Net framework would sit on machines (server side only - clients did not need to have it installed) and act as a cushion between the developer and the complexities of developing web based applications - it was kind of like a grown up version of Visual Basic where files were processed at run time rather than actually being run (you still need the .Net framework to be installed before desktop based .Net applications will run). C was Microsoft's language of choice but it was time to make use of their newly acquired Delphi knowledge and, in 2000, the new C# was released.
Forming the backbone of Microsoft's flagship Visual Studio, C# was undeniably C based but it borrowed a lot from Delphi in the way that the language worked, and Visual Studio's IDE certainly seemed familiar to Delphi developers. C# blurred the lines a little between Delphi and C and made sure that Delphi developers who wanted to move forward with the new .Net philosophy didn't face a quantum leap in learning. That's not to say that Microsoft hadn't learned from the past as they actively worked with Borland to make the .Net framework far more widely supported.
Keep Bashing The Keys
And with the .Net framework this brings us pretty much up to date with regards programming languages. While little pockets of specialist programming still exist (especially within reasearch projects and on the few remaining mainframe systems), C, especially with the introduction of C#, is becoming the truly dominant language as Pascal starts to fall by the wayside, when it comes to the PC platform. Away from the PC, Apple advocate C as their language of choice, and the various Unix flavours all still favour C (it is still tightly linked into the operating system after all). So what does the future hold? Will C remain as the dominant language? Will ALGOL-2005 spring up and terrify a whole new generation? The future is never clear but its seems unlikely that C will be de-throned in the near future with regards pure software development. Web development is another matter though and the rise of scripting and markup languages (e.g. PHP and HTML) makes software development quick and easy.
And of course there's another reason why the likes of C and HTML are unlikely to become obsolete in the near future and it's a factor that contributed to the long term existence of the COBOL dinosaur - entrenchment. Just as COBOL became firmly embedded in numerous businesses around the world, so too have C based programs and HTML based web pages. With the levels of desktop machines now in the millions (possibly even billions), a quantum shift in programming is becoming more and more unlikely as the upset to legacy systems would simply be too great. The world of programming is unlikely to undergo another major revolution...at least not in the near future.
|
|