APL (programming language)

from Wikipedia, the free encyclopedia
APL
Paradigms : functional , structured , modular
Publishing year: 1964
Designer: Kenneth E. Iverson
Developer: Kenneth E. Iverson
Typing : dynamic
Important implementations : Dyalog APL, IBM APL2, APL2000, Sharp APL, APLX, NARS2000, GNU APL
Dialects: A + , Dyalog APL, APLNext, ELI, J
Standardizations: ISO8485 (1989), ISO / IEC13751 (2001)
Influenced by: Mathematical notation
Affected: J , K, Mathematica , Matlab , Nial, PPL , Q, R , S

APL ( AP rogramming L anguage ) is a usually interpreting programming language , the syntax of which mainly consists of symbols . It was developed by Kenneth E. Iverson and his colleagues at IBM in the 1960s as algorithmic notation (among other things for math classes) and as a design language for mainframes.

history

IBM 5100 microcomputer with an APL keyboard

With the book A Programming Language from 1962, Kenneth Iverson initiated the use of a new concept in programming. Before the first interpreter was available, APL was already used as a metalanguage for describing the architecture of the then newly developed IBM System / 360 computer system from the perspective of the programmer. From 1965 APL was implemented as a programming language on mainframes (e.g. IBM System / 360) and offered to customers as a timeshare option. At that time, IBM ball-head typewriters were used as a "terminal". Therefore the original character set only had (italic) capital letters.

From 1975 there was an implementation on the IBM 5100 , a forerunner of the PC, which was already a microcomputer . Although the machine was considered to be quite powerful by the standards of the time, APL ran relatively slowly on it, as it was an emulation of the mainframe APL interpreter.

The first implementations on PCs required a special EPROM so that the APL character set could be displayed. The APL character set was originally chosen so that the symbols are as self-explanatory as possible , so that the functions can be derived intuitively from the symbols . For several years, the term APL is also called A rray P rocessing L anguage interpreted.

particularities

Operators and special characters

APL uses special operators or commands, each of which has the function of not only processing individual numerical values, but also entire vectors and matrices, e.g. B. add 2 matrices or calculate the scalar product of 2 vectors. There was a special character for each of these operators, which meant that an extended character set was required on the keyboard, in memory and on the screen - ever since there were such - as well as on the printer. Back then there were no laser or inkjet printers that could be programmed to generate virtually any character. The use of such characters with the function of operators enabled an extremely concise, but also cryptic code for outsiders, which deterred many people and was not mandatory. Reserved words could have been used as operators.

Interactivity

APL was interactive from the start: After entering a command (e.g. a calculation instruction 1234 - 777 ) you press the Enter key, the command is executed by the interpreter and the result is displayed. A special instruction for outputting the result, such as For example, the PRINT command in BASIC is not necessary, but exists in the event that a result is to be displayed that would normally not be displayed (e.g. when a value is assigned to a variable).

If an error occurs, you will receive a corresponding message. You can modify your input and execute it again. The direct interaction with the computer that this enables is still one of the great advantages of APL as a development tool.

From today's perspective this sounds trivial, but APL was one of the first programming languages ​​to offer this luxury: Competing languages ​​were not yet interactive, but had to be compiled.

Program code

Sequences of commands can be combined into functions. Functions can in turn call other functions. In fact, APL is one of the first functional programming languages . For more details and an example, see below .

Until the 1990s, APL lacked the control structures of “structured programming” . Logic had to be implemented using jump instructions . In APL control structures are used less often than in other imperative programming languages, on the one hand because APL functions process not only scalars but data structures of any dimension, on the other hand because it offers the operator Each .

Data types

APL knows at least the data types Char, Bool, Int and Float , but the programmer does not have to take this into account, because the interpreter automatically converts the data types whenever this is necessary. This also means that APL does not have a type test.

The data type of variables does not have to be declared separately; you can assign a floating point number to a variable (or a vector or a matrix of floating point numbers) and then a text without the need for a special instruction beforehand.

Memory management

The memory management is also taken over by the interpreter. An APL programmer does not have to worry about reserving or releasing memory while the program is running. The total working memory is made available in the so-called workspace for variables and programs; it can be specified when the program is started and, in some APL products, can also be dynamically expanded.

Array processing

Almost all functions in APL are also designed to be non-scalar. This means that functions can be applied not only to individual scalars (numbers or characters), but also to vectors (series of numbers), matrices (tables) and multi-dimensionally arranged data as well as lists .

Examples (the indented first line is the user input, the second line is the response of the APL interpreter)

Many programming languages ​​allow the addition of two scalars:

    2 + 3
 5

APL also allows the addition of vector and scalar:

    2 3 4 + 3
 5 6 7

and the addition of two vectors:

    2 3 4 + 5 6 7
 7 9 11

Execution and priority

There is only one rule of priority in APL: Everything is processed from right to left. Exception: expressions in brackets are processed first. Therefore:

    10×2+3
 50

but:

    (10×2)+3
 23

variables

In APL, variables do not have to be declared or typed (see data types). A variable is created by entering a name, followed by an assignment arrow (←), followed by the value or values ​​of the variable:

     XWERT←456.78
     YVECT←56 23 81.8 796 0.014 8.9 20 1
     TEXT1←'Dies ist ein Text'
     MATRIX←2 4ρYVECT

(The operator ρ, called rho , transforms the 8-part vector YVECT into a matrix with 2 rows and 4 columns. This way, arrays with more dimensions can also be formed.)

The concept of constants, i.e. unchangeable declared values, does not exist in APL, but it can be simulated by a function that requires no arguments and returns an explicit result.

scope

Each assignment creates a global variable; H. the variable can be seen and changed in the entire program. However, you can limit the scope of variables by including the name of the variable in the header of a function. Such a variable is called local because it is only visible when the function is running.

However, if a function F1 defines a local variable A and then calls a function F2, then A can be seen and changed within F2, which is now considered a design flaw. The Direct Functions in Dyalog APL behave differently, however: There local variables are actually local in the narrower sense and are also invisible in called functions.

Arrays

Data of all kinds are called arrays in APL. Arrays can have different dimensions. A single value is called a scalar . Several values ​​next to each other form a vector . The operator for concatenating ( concatenating ) several scalars is the comma. It is also possible to concatenate a single value with an empty set and thus obtain a vector that consists of a single element. Empty vectors are also allowed: These are vectors that contain no data element at all, only the structure information.

Values ​​that are arranged in rows and columns form tables , also called matrices or two-dimensional arrays .

The dimension of an array is given in APL with the Greek letter ρ ( Rho ). When the “rank” of an array is mentioned, one means the number of dimensions of the array, ie Rho of Rho. Accordingly, the rank of a scalar is 0, that of a vector is 1, that of a table is 2, and so on.

The levels of a three-dimensional array are called a plan . Arrays with n dimensions are possible, the number is only limited by the maximum size of the integer indexing (2 31 -1) and the available storage space.

A "nested array" in APL2

In 1986, IBM launched a significantly expanded APL called APL2 . The extension consisted mainly in the fact that each element of an array can consist of any other data structures ( nested array ). This results in nested structures. To illustrate this, there is an example on the right. It is a numerical matrix with 4 rows and 5 columns that has already been discussed. However, the 2nd element of the 2nd line consists of a text vector and the 4th element of the 3rd line consists of a 2x2 matrix. The text labels can thus also be linked with the numerical values ​​to form a table. APL2 made it possible to create mixed arrays as well as simple and complex lists .

As part of this expansion, new so-called "primitive functions" (were primitive function ) introduced for the processing of the new data structures and adapted the old functions and extends their scope. Other APL manufacturers brought out similar extensions to their implementations, with subtle differences making it difficult to port a program to another implementation. Today, the APL2 implementation is a reference for all manufacturers, and efforts are made to achieve the greatest possible compatibility.

Functions and Operators

APL knows both functions and operators, but the meaning of the terms is different than in mathematics: functions are applied to data, operators to functions and data. Functions return data, operators, so-called "derived functions" (Engl .: derived function ).

example

The character slash (/) stands for the operator reduce . Operators expect one or two operands. If only one operand is used, it must be to the left of the operator:

   +/

In this example the operand is the “Plus” function. Together with the operator, the derived function sum is formed.

Applied to a vector:

   +/ 3 4 5

the Reduce operator causes the operand to be inserted between the individual components of the vector. In abstract terms:

   f/ n1 n2 n3  ==  n1 f n2 f n3

and in the specific example (the result is below):

   +/ 3 4 5  ==  3 + 4 + 5
12

How powerful this concept is becomes clear only when looking at another operator: Expand ( backslash , \) uses the operand in the same way as Reduce , but generates intermediate results and does not reduce the rank of the result ( Reduce converts a vector into a scalar , a matrix into a vector and so on - this reduces the need for program loops):

   +\ 3 4 5
3 7 12

Further examples

    ×/ 3 4 5
60
    ×\3 4 5
3 12 60
    -/3 4 5
4
    -\3 4 5
3 -1 4

There are also operators that require two operands. The Outer Product (.) Operator is one such operator. If you use the functions plus (+) and times (×) as operands, then the matrix multiplication arises in APL :

   1 2 3 +.× 40 50 60
320
APL statement

It works the same with matrices. To demonstrate this, some lines from an APL IDE (here Dyalog APL / W) are shown in the picture . In addition to + and ×, three APL functions are used:

  • The arrow pointing to the left symbolizes the assignment of a value to a variable name in APL.
  • The symbol ι ( Iota ), which is similar to an i, stands for the function Interval . In the first application, a string of numbers from 1 to 6 is generated.
  • The character ρ ( rho ), similar to the letter p, stands for the APL function shape and formats the data shown on the right. The number of axes is given to the left of the symbol. In the first application, a matrix with two rows and three columns is generated.
  • The formula “+. ×” symbolizes the matrix product.

Self-defined functions

In addition to the built-in functions (primitive functions) you can write your own functions, which are then called user-defined functions. Such a function can require zero, one or two arguments and is called a “niladic”, “monadic” or “dyadic” function. According to their descent from mathematical notation, monadic APL functions expect their argument on the right and dyadic functions on the right and left.

The function can return a value.

Example of a dyadic function:

R ← S Runde Z

Let “S” be the number of decimal places to which the argument “Z” (a real number) is to be rounded; the result is in R. Application:

   2 Runde 3.14159265
3.14

Functions can extend over several lines. Other functions can be called in functions. Branches were originally made by means of (possibly conditional) jump instructions and target marks ( labels ). Today this technology is hardly used any more: Except for APL2, all modern implementations offer control structures.

Program example to illustrate how APL works

    R ← S Runde Z
[1] ⍝ Runde eine reelle Zahl Z auf S Stellen
[2] ⍝ Standardwert für S ist 2, wenn der Wert beim Aufruf nicht spezifiziert wurde
[3] →(0≠⎕NC'S')/RN
[4] S←2
[5] RN: R←(10*-S)×⌊0.5+Z×10*S

This function and its application are intended to explain the properties of APL:

Explanation of the program example

  • Line 0: Definition of the function with two arguments S ("digits") and Z ("number") and an explicit result R.
  • Lines 1 and 2: Comment lines (recognizable by the "lamp" ⍝ as the first character).
  • Line 3: A condition is used to check whether the NameClass ("built-in function" ⎕NC) of the name S is not equal to 0. 0 means “not defined”. The branch to the label RN applies if the condition in brackets = 1, otherwise RN (which is simply line number 5) is reduced to the “empty vector” (“/” is by the normal APL instruction 0 / RN the operator reduce ) and there is no branching.
  • Line 4: If the condition in line 3 is not met (= value is unknown), S is set to 2.
  • Line 5: This is where the actual rounding takes place. A characteristic feature is the "passing on" of calculated values from right to left , e.g. B. the multiplication of the parameter Z with the rounding points S (Z × 10 * S). The value generated by S powers of ten is then (left of it) rounded commercially (addition of 0.5) (⌊ function, called “floor”) and thus freed from further decimal places, so that it is now an integer value. The result is passed on to the multiplication by (10 * -S) on the left, which reduces the value again by S powers of ten. This is the result R of the function.

Mode of action or application

Examples:

   1 Runde 3.14159265
3.1
   Runde 3.14159265
3.14
   3 Runde 3.14159265 77.123 99.9
3.142 77.123 99.900
   Runde 2 2 ρ(ι4)÷7
0.14 0.29
0.43 0.57
  • First example: application of the function to pi, rounding to 1 place (see also above).
  • Second example: Rounding Pi to two places, testing the default value (left argument missing).
  • Third example: Rounding of a vector to three places (missing zeros on the right are added).
  • Fourth example: Rounding a matrix (table) to two digits (default) - two rows and two columns generated by the function ρ from dividing the first four natural numbers (ι4, function iota ) by 7.

The lap function can not only be performed interactively as shown above, it can also be used in other programs:

X ← 4 Runde +/MAT

MAT is a table with arbitrary numbers, which is summed up in columns by the “sum reduction” ( + / ). The resulting n-digit numbers (a vector) are assigned to the variable X, rounded to 4 decimals. Instead, you could continue calculating with it, for example multiplying it by 2:

2 × 4 Runde +/MAT

"Modern" language concepts: recursion and control structures

One of the strengths of APL is recursion , the call of a function within itself. This was already included in the original implementation of APL (in contrast to most of the programming languages ​​of the time such as COBOL or FORTRAN ).

Example (without line numbers) using "modern" (control structures added later in other APL "dialects"):

  Z ← FAKULTÄT N
⍝ Da n! = n × (n-1)!, muss (am Anfang) die Rekursion
⍝ bei n=1 "gestoppt" werden (1! = 1)
:If N <= 1
   Z←1
:Else  Z←N×FAKULTÄT N-1
:EndIf

Note: Due to the processing sequence, "n-1" does not have to be in brackets (but can).

Power and readability

APL is powerful: there are (depending on the version) around 70 primitive functions, i.e. functions that are anchored in the interpreter (as opposed to self-defined) functions. These are represented by around 50 symbols, of which around 20 symbols represent two different functions depending on whether they are called with one or two arguments.

Example:

  • In 8 ÷ 4 the function “÷” is used dyadically as division. The result is 2.
  • In ÷ .25 the function "÷" is used monadically; it provides the reciprocal of the right argument. The result is 4.

Most of the functions “built into” APL act on scalars as well as on vectors, matrices and arrays. Where loops have to be used in other programming languages ​​in order to process a set of values, the use of a primitive function is usually sufficient with APL. In addition, many of these functions can be expanded using operators.

In addition to the primitive functions, which always consist of a single character, there are a large number of system functions and variables. Date and time are e.g. B. can be queried in a system variable ⎕TS (for T ime S tamp). System variables do not belong to the "primitive" language scope, but depend on the implementation. System functions are also partly implementation-dependent. For example, they provide interfaces to other programming languages ​​and to the operating system.

Defined functions fit seamlessly into this concept. They can be monadic or dyadic and can be used together with the primitive functions in a statement without any special syntax. You can even use self-programmed functions as arguments for an operator, or you can program operators yourself.

Since the primitive functions of APL only consist of a single character and these functions are also very powerful, no other language can offer comparable brevity and stringency. Where many lines are required in other programming languages, an instruction with a few symbols is often sufficient with APL.

These are the notorious "one-liners" on which many APL programmers have sharpened their "thinking tools" ("APL as a tool of thought"). Ken Iverson himself has created a one-liner that creates a list of the first prime numbers up to at most N:

 (2 = 0 +.= T o.| T) / T ← ιN

There are even more extreme examples. There is an APL solution to the n-queens problem also in one (!) Line. Critics sometimes speak of APL as a "write-once-read-never" language. This judgment is based on a misunderstanding: If as much happens in one line of APL as in two pages of C code, then one should realistically assume that this one line takes about the same time to understand as the two pages of C code.

APL has proven itself particularly in areas in which requirements change constantly and quickly: insurance, hedge funds, portfolio managers and prototyping for new applications.

The symbols used, the brevity of the formulation and the variable manipulation of abstract objects (the aforementioned scalars, vectors, matrices and so on - both in numerical and textual form and even mixed) make APL a language for mathematicians (which they did in the beginning was designed). It requires abstract thinking and spatial imagination, but it is also simple and very elegant.

Execution speed

Because APL is interpreted, it can be comparatively slow to execute. This is particularly noticeable when an APL program has to take care of individual data particles, for example in a KeyPress event handler. On the other hand, APL includes a large pool of highly specialized functions that are optimized for processing large arrays. If these functions are used on large amounts of data, then APL programs, like other interpreter programs, can be very fast.

As a functional language, APL is in principle suitable for using multiprocessor machines. In this area there are currently the largest further developments of the successful APL implementations on the market.

Development and current situation

Until around 1985, IBM was the leading provider on both PCs and mainframes with its APL2 interpreter. In the next 10 years or so, APL was very successful, but was not significantly further developed. Smaller software companies (APL2000, Dyalog APL, later also MicroAPL) have only been continuously developing APL since 1992. In the meantime, these implementations have left IBM's APL2 well behind in terms of performance. However, APL2 is the only APL implementation that (also) runs on mainframes.

Perhaps the best implementation currently available, Dyalog APL, has been accepted by Microsoft as one of the recognized .NET languages. IBM APL2, on the other hand, is the first choice in IBM's Websphere world.

Today, APL2 is still of particular importance in the banking, insurance and tourism sectors as well as in research and development.

Today APL is used in small projects by specialized software companies and as a tool by professionals who call themselves systems analysts or business analysts rather than programmers. It is also still being used successfully in the specialist departments of larger companies, research institutes and universities.

“APL is alive and well” and has its own wiki.

In 2012, the Computer History Museum was able to publish the assembler source code of APL in the 1969–1972 “XM6” version for System / 360 with the permission of IBM .

J and APL

In his later years, APL's lead designer, Ken Iverson, gave it a second try. The result is the J programming language , which has nothing to do with Microsoft's no longer supported J # programming language . This language is very similar in its concepts to APL, but only uses characters from the ASCII character set. This is seen by the supporters as a huge step forward, but rejected by the critics because the intelligibility is reduced and the self-explanations of the symbols are not exploited.

Individual evidence

  1. Falkoff, AD, KE Iverson, The Design of APL, IBM Journal of Research and Development, Volume 17, Number 4, 1973-07.
  2. Iverson KE, " Notation as a tool of thought ( Memento of August 24, 2012 in the Internet Archive ) (PDF; 2.2 MB)", Communications of the ACM , 23: 444-465 (August 1980).
  3. AD Falkoff, KE Iverson, EH Sussenguth: A formal description of SYSTEM / 360th In: IBM Systems Journal. Volume 3, Issue 2 (1964).
  4. The typewriter has a limited range of characters. Special symbols were therefore created by typing two characters on top of each other. Example: The character is generated by the sequence ⋂ [Backspace] ° .
  5. Take a video on YouTube as an example, in which two single-line APL functions are developed step by step: the first function calculates the next generation according to the rules for Conway's Game of Life , the second function represents the game: Conway's Game Of Life in APL
  6. ^ One-liner Wars in APL
  7. APL wiki
  8. Len Shustek: The APL Programming Language Source Code ( English ) computerhistory.org. October 10, 2012. Retrieved October 15, 2013.

literature

  • Bernard Legrand: Mastering Dyalog APL . 2009, ISBN 978-0-9564638-0-7 .
  • Kenneth E. Iverson: A Programming Language . Wiley, 1962, ISBN 0-471-43014-5 .
  • James A. Brown, Sandra Pakin, Raymnod P. Polivka: APL2 at a Glance . Prentice Hall, 1988, ISBN 0-13-038670-7 .
  • Hans Lochner: APL2 manual . Springer Verlag, 1989, ISBN 978-3-540-50677-5 .
  • Wulf-Dieter Wagner: Software engineering with APL2 . Springer Verlag, 1992, ISBN 3-540-54406-2 .
  • Hanspeter Bieri and Felix Grimm: Data structures in APL2 . Springer Verlag, 1992, ISBN 0-387-55747-4 .
  • Bernhard Legrand: Les APL étendus . Masson, Paris 1994.

Web links

Commons : APL (programming language)  - collection of images, videos and audio files

Implementations

Periodicals

About APL

syntax