Why you should consider using PL/I:

What's good about PL/I?

  1. The best part of PL/I is the input and output. You can rely on it.
    The input/output is achieved with statements that are ready to use, and easy to use.
    There's no setting up to do. They are not procedures or functions dressed up to look like statements.
    In formatted output, you don't get silly numbers displayed when you include the format specification, but omit the name of the variable (as happens with the language C). PL/I converts to or from the type that you specify, be it integer, fixed-point, or string. You don't get silly things happening because you left off the "&" from the "scanf" function in C. That's because the input operation (GET) is a statement, not a function.
    And when you want formatted output, you have a variety of formats that you can choose, such as PICTURE format, with drifting signs and drifting currency sign ($). You can even define your own currency symbol. You can insert commas or spaces in very long numbers, to make the output readable (e.g. 123,456,789.356,251 is better than 123456789.356251). You can use either PICTURE formats or the specific format codes to get integer, decimal fixed-point, and floating-point outputs.
    If you prefer the European numbering system, the PICTURE format brings you 123.456.789,25.
    And if you don't want to be bothered with formats, you can use simple free-formatted output, e.g. PUT (X);
  2. For business applications, you can have decimal data, whereby data is stored exactly (e.g. 5.14 is stored EXACTLY, not as 5.13999), and arithmetic operations give exact results (e.g. 3 x 5.14 gives you 15.42 precisely, not 15.41998)
  3. There are no annoying restrictions on where you can use I/O. For example, in Fortran you cannot have input/output statements in a function, when that function is referenced in an output statement.
    In PL/I there is no such restriction. This is of great help when debugging, as one can slip in an output statement in a function to check a result. Especially helpful in a recursive function.
    In Fortran, it is not possible to read in an array of unknown size using free format. In such a case, the variable used in an implied DO becomes undefined, and is unavailable to determine the number of elements read in.
    In PL/I, the number of elements is available two different ways (specifically through the COUNT function and through the control variable).
  4. Files are easy to use. If you can do output to the screen, and input from the keyboard, you can do Input/Output to files, simply by inserting the file name into the GET or PUT statement thus: GET FILE (MYDATA) LIST (V); etc.
  5. Arguments for procedures can be passed by address or by value. A constant passed to a procedure has a temporary generated for it. This prevents a procedure corrupting a constant (In Fortran, for example, constants aren't.)
    Compare with Fortran: if a Fortran function or subroutine makes an assignment to a dummy argument [i.e., a PL/I parameter], and the argument is a constant, Fortran can change the constant without warning.
  6. In PL/I procedures are generic.
    In Fortran, although a generic facility for procedures is provided, it breaks down when the parameters of two procedures happen to transform to the same precision.
    So if you write two procedures, one having a floating-point argument having a precision of, say, 6 digits, and the other procedure having 12 digits, and the machine on which the program is compiled has 64-bit as single precision, these two procedures both map to the same real kind, and the generic mechanism breaks down completely because the procedures are then ambiguous.
    This cannot happen in PL/I, because the PL/I generic mechanism differentiates between the procedures based on the declared precision, not the machine precision.
    Similar problems occur with Fortran integer types.

Outstanding and helpful PL/I facilities include:

  1. The debugging facilities are all part of the language (for example, checking for subscript bound errors and string reference errors with SUBSCRIPTRANGE and STRINGRANGE etc are most helpful, along with appropriate ON statements to display the values of variables).
    The best part of this is that you can display everything you need (statement number, values of variables, a trace of procedure calls, etc) to help you find the error. All this, and more, instead of those cryptic messages (from other languages) such as "floating-point trap" at some unidentified location somewhere in the program. (When you've had this message in a 20,000 line program, you'll know what I mean!)
    See the example.
  2. And if your program gets stuck in a loop, just hit CTRL-BREAK, and your ATTENTION ON-unit will tell you precisely which statement it's executing. Not only that, it lets you do anything you want, including printing the values of all (or preselected) variables, and changing any or all of the values of variables.
    You don't have to re-run your program (with new output statements) to find out in which loop it's stuck! (and then run it yet again to display the values of variables you think you need).
    And if your program was running OK after all, you can resume execution again, as if nothing had happened.
  3. The ability to intercept errors (via ON statements) and to continue execution;
  4. The simple, handy I/O statements GET LIST, PUT LIST, along with the very handy PUT DATA statement (for debugging mostly).
  5. Everything is "ready to go" unlike some other languages, such as Ada!
  6. The "whole array" operations simplify programming and increase understanding, and increase execution speed into the bargain; If A and B are arrays, you can write A = B; to copy an array. You can use PUT (A); to print an array. To add two arrays, write A = B + C; [these are trivial examples -- much more is available]
  7. Dynamic arrays provide the means to write a general program for any size of array. You aren't bound by some artificial limit. You automatically obtain exactly the amount of storage you need for an array.
  8. The COMPLEX data type is provided, which simplifies the preparation of programs because commonsense complex arithmetic is available.
    A number of essential functions is at hand for producing: complex square root, the conjugate, the absolute value, and for extracting either the real or complex components, and for fabricating a complex number from two real numbers (SQRT, CONJG, ABS, REAL, IMAG, CPLX). The ** operator is available for raising a complex number to a given power. A range of (complex) trigonometric functions is provided (includes SIN, COS, SINH, COSH, etc, and mathematical functions such as LOG).
    Even more importantly, debugging is simplified, because the error messages are specific to complex number operations. (If you have used complex arithmetic without using the COMPLEX facilities, the best that the error messages can tell you is in terms of real (floating-point) operations, which don't necessarily make sense).
    And the COMPLEX type can be applied to integer as well as to float- ing-point data and fixed-point decimal data.
  9. PL/I has excellent string-handling facilities. PL/I provides two types of string -- the fixed-length string and the varying-length string. These two data types are supported by a range of functions that speed up string processing compared to other languages. It isn't necessary to write your own "string-search" routines like you need to in other languages such as C and Pascal, for example. The search functions are already there (INDEX, SEARCH, VERIFY).
    What's more, if the machine has a "search" instruction, PL/I can use that, and can search faster than some hand code using a loop. (Having to write your own search routine is like having to turn out your own nuts and bolts on a machine lathe.)
    PL/I can search from either the right-hand end or from the left-hand end of a string (SEARCH, SEARCHR, VERIFYR)
    Joining strings is a simple operation (catenation). PL/I's varying-length strings make this a breeze. The length of a string can be discovered by using the LENGTH function; strings containing blanks (or any unwanted character) at the beginning or the end can be removed using the TRIM function. Strings can be centered using the CENTERing built-in functions (helps with page headings etc) and so on.
    Other functions include TRANSLATE, for changing ASCII <--> EBCDIC, and for converting upper to lower case, or for replacing special codes such as TAB to blank or for any other conversion; and VERIFY, for performing a search, validating data, etc.
  10. PL/I has a Year 2000 DATETIME function that returns a four-digit year. IBM's Enterprise PL/I for OS/390 and VisualAge PL/I for Windows, OS/2, and AIX, have built-in functions that support the Millennium Language Extensions that are now part of the workstation and mainframe compilers. With these extensions, PL/I can work on 2-digit dates, without the need to have the external data in 4-digit form.
    On Enterprise PL/I and VisualAge PL/I, the DATETIME built-in function can produce the date in one of 37 different formats (e.g. year first, day first, month as Feb or FEB, for example). The other functions are: DAYS, DAYSTODATE, DAYSTOSECS, SECS, SECSTODATE, SECSTODAYS, VALIDDATE and WEEKDAY. With these functions, it is easy to perform day computations, for example, to calculate the day name of a day that is, say, 40 days hence.
    These functions include REPATTERN, Y4DATE, Y4JULIAN, and Y4YEAR, the latter three converting 2-digit years to 4-digit years.
  11. A macro pre-processor is available for PL/I on IBM mainframe (OS) and IBM OS/2 for the PC, Windows NT, AIX, and Liant OPEN PL/I, and probably others.
  12. And when you need to do something special (rarely, but it's nice to know that you have something to fall back on in an emergency) it's there -- With UNSPEC you can peek at the bits of a data item (be it a character string, an integer, bit string, or floating-point data).
    For further information about PL/I, systems, and suppliers, see: IBM's PL/I home page, Liant Software Corporation , and the PL/I Resource Page.
    Updated: 14th September 2009.