Character set APL has been criticized and praised for its choice of a unique character set. In the 1960s and 1970s, few terminal devices or even displays could reproduce the APL character set. The most popular ones employed the
IBM Selectric print mechanism used with a special APL type element. One of the early APL
line terminals (line-mode operation only,
not full screen) was the Texas Instruments TI Model 745 () with the full APL character set which featured
half and full duplex telecommunications modes, for interacting with an APL
time-sharing service or remote mainframe to run a remote computer job,
remote job entry (RJE). Over time, with the universal use of high-quality graphic displays, printing devices and
Unicode support, the APL character font problem has largely been eliminated. However, entering APL characters requires the use of
input method editors, keyboard mappings, virtual/on-screen APL symbol sets, or easy-reference printed keyboard cards which can frustrate beginners accustomed to other programming languages. With beginners who have no prior experience with other programming languages, a study involving high school students found that typing and using APL characters did not hinder the students in any measurable way. In defense of APL, it requires fewer characters to type, and keyboard mappings become memorized over time. Special APL keyboards are also made and in use today, as are freely downloadable fonts for operating systems such as Microsoft Windows. acting on
arrays. APL has many nonstandard
primitives (functions and operators) that are indicated by a single symbol or a combination of a few symbols. All primitives are defined to have the same
precedence, and always associate to the right. Thus, APL is
read or best understood from
right-to-left. Early APL implementations ( or so) had no programming loop
control flow structures, such as do or while loops, and if-then-else constructs. Instead, they used array operations, and use of
structured programming constructs was often unneeded, since an operation could be performed on a full array in one statement. For example, the iota function (ι) can replace for-loop
iteration: ιN when applied to a scalar positive integer yields a one-dimensional array (vector), 1 2 3 ... N. Later APL implementations generally include comprehensive control structures, so that data structure and program control flow can be clearly and cleanly separated. The APL environment is called a
workspace. In a workspace the user can define programs and data, i.e., the data values exist also outside the programs, and the user can also manipulate the data without having to define a program. In the examples below, the APL interpreter first types six spaces before awaiting the user's input. Its own output starts in column one. The user can save the workspace with all values, programs, and execution status. APL uses a set of non-
ASCII symbols, which are an extension of traditional arithmetic and algebraic notation. Having single character names for single instruction, multiple data (
SIMD) vector functions is one way that APL enables compact formulation of algorithms for data transformation such as computing
Conway's Game of Life in one line of code. In nearly all versions of APL, it is theoretically possible to express any computable function in one expression, that is, in one line of code. Due to the unusual
character set, many programmers use special
keyboards with APL keytops to write APL code. Although there are various ways to write APL code using only ASCII characters, in practice it is almost never done. (This may be thought to support Iverson's thesis about
notation as a tool of thought.) Most if not all modern implementations use standard keyboard layouts, with special mappings or
input method editors to access non-ASCII characters. Historically, the APL font has been distinctive, with uppercase italic alphabetic characters and upright numerals and symbols. Most vendors continue to display the APL character set in a custom font. Advocates of APL claim that the examples of so-called
write-only code (badly written and almost incomprehensible code) are almost invariably examples of poor programming practice or novice mistakes, which can occur in any language. Advocates also claim that they are far more productive with APL than with more conventional computer languages, and that working software can be implemented in far less time and with far fewer programmers than using other technology. They also may claim that because it is compact and terse, APL lends itself well to larger-scale software development and complexity, because the number of lines of code can be reduced greatly. Many APL advocates and practitioners also view standard programming languages such as
COBOL and
Java as being comparatively tedious. APL is often found where time-to-market is important, such as with trading systems.
Terminology APL makes a clear distinction between
functions and
operators. Functions take arrays (variables or constants or expressions) as arguments, and return arrays as results. Operators (similar to
higher-order functions) take functions or arrays as arguments, and derive related functions. For example, the
sum function is derived by applying the
reduction operator to the
addition function. Applying the same reduction operator to the
maximum function (which returns the larger of two numbers) derives a function which returns the largest of a group (vector) of numbers. In the J language, Iverson substituted the terms
verb for
function and
adverb or
conjunction for
operator. APL also identifies those features built into the language, and represented by a symbol, or a fixed combination of symbols, as
primitives. Most primitives are either functions or operators. Coding APL is largely a process of writing non-primitive functions and (in some versions of APL) operators. However a few primitives are considered to be neither functions nor operators, most noticeably assignment. Some words used in APL literature have meanings that differ from those in both mathematics and the generality of computer science.
Syntax APL has explicit representations of functions, operators, and syntax, thus providing a basis for the clear and explicit statement of extended facilities in the language, and tools to experiment on them.
Examples Hello, world This displays "
Hello, world": 'Hello, world' A design theme in APL is to define default actions in some cases that would produce syntax errors in most other programming languages. The 'Hello, world' string constant above displays, because display is the default action on any expression for which no action is specified explicitly (e.g. assignment, function parameter).
Exponentiation Another example of this theme is that exponentiation in APL is written as , which indicates raising 2 to the power 3 (this would be written as or in some languages, or relegated to a function call such as in others). Many languages use to signify multiplication, as in , but APL chooses to use . However, if no base is specified (as with the statement in APL, or in other languages), most programming languages one would see this as a syntax error. APL, however, assumes the missing base to be the natural logarithm constant
e, and interprets as .
Simple statistics Suppose that is an array of numbers. Then gives its mean. Reading
right-to-left, gives the number of elements in X, and since is a dyadic operator, the term to its left is required as well. It is surrounded by parentheses since otherwise X would be taken (so that the summation would be of —each element of X divided by the number of elements in X), and gives the sum of the elements of X. Building on this, the following expression computes
standard deviation: Naturally, one would define this expression as a function for repeated use rather than rewriting it each time. Further, since assignment is an operator, it can appear within an expression, so the following would place suitable values into T, AV and SD:
Pick 6 lottery numbers This following immediate-mode expression generates a typical set of
Pick 6 lottery numbers: six
pseudo-random integers ranging from 1 to 40,
guaranteed non-repeating, and displays them sorted in ascending order: x[⍋x←6?40] The above does a lot, concisely, although it may seem complex to a new
APLer. It combines the following APL
functions (also called
primitives and
glyphs): • The first to be executed (APL executes from rightmost to leftmost) is dyadic function ? (named deal when dyadic) that returns a
vector consisting of a select number (left argument: 6 in this case) of random integers ranging from 1 to a specified maximum (right argument: 40 in this case), which, if said maximum ≥ vector length, is guaranteed to be non-repeating; thus, generate/create 6 random integers ranging from 1 to 40. • This vector is then
assigned (←) to the variable x, because it is needed later. • This vector is then
sorted in ascending order by a monadic ⍋ function, which has as its right argument everything to the right of it up to the next unbalanced
close-bracket or close-parenthesis. The result of ⍋ is the indices that will put its argument into ascending order. • Then the output of ⍋ is used to index the variable x, which we saved earlier for this purpose, thereby selecting its items in
ascending sequence. Since there is no function to the left of the left-most x to tell APL what to do with the result, it simply outputs it to the display (on a single line, separated by spaces) without needing any explicit instruction to do that. ? also has a monadic equivalent called roll, which simply returns one random integer between 1 and its sole operand [to the right of it], inclusive. Thus, a
role-playing game program might use the expression ?20 to roll a twenty-sided die.
Prime numbers The following expression finds all
prime numbers from 1 to R. In both time and space, the calculation complexity is O(R^2)\,\! (in
Big O notation). (~R∊R∘.×R)/R←1↓⍳R Executed from right to left, this means: •
Iota ⍳ creates a vector containing
integers from 1 to R (if R= 6 at the start of the program, ⍳R is 1 2 3 4 5 6) •
Drop first element of this vector (↓ function), i.e., 1. So 1↓⍳R is 2 3 4 5 6 •
Set R to the new vector (←,
assignment primitive), i.e., 2 3 4 5 6 • The /
replicate operator is dyadic (binary) and the interpreter first evaluates its left argument (fully in parentheses): • Generate
outer product of R multiplied by R, i.e., a matrix that is the
multiplication table of R by R (°.× operator), i.e., • Build a vector the same length as R with 1 in each place where the corresponding number in R is in the outer product matrix (∈,
set inclusion or
element of or
Epsilon operator), i.e., 0 0 1 0 1 • Logically negate (
not) values in the vector (change zeros to ones and ones to zeros) (∼, logical
not or
Tilde operator), i.e., 1 1 0 1 0 • Select the items in R for which the corresponding element is 1 (/
replicate operator), i.e., 2 3 5 (This assumes the APL origin is 1, i.e., indices start with 1. APL can be set to use 0 as the origin, so that ι6 is 0 1 2 3 4 5, which is convenient for some calculations.)
Sorting The following expression
sorts a word list stored in matrix X according to word length: X[⍋X+.≠' ';]
Game of Life The following function "life", written in Dyalog APL, takes a Boolean matrix and calculates the new generation according to
Conway's Game of Life. It demonstrates the power of APL to implement a complex algorithm in very little code, but understanding it requires some advanced knowledge of APL (as the same program would in many languages). life ← {⊃1 ⍵ ∨.∧ 3 4 = +/ +⌿ ¯1 0 1 ∘.⊖ ¯1 0 1 ⌽¨ ⊂⍵}
HTML tags removal In the following example, also Dyalog, the first line assigns some HTML code to a variable txt and then uses an APL expression to remove all the HTML tags: txt←'This is emphasized text.' {⍵ /⍨ ~{⍵∨≠\⍵}⍵∊'<>'} txt This is emphasized text. == Naming ==