PONY λ M2 Modula-2

Fortran.CodeCompared.To/APL

An interactive executable cheatsheet comparing Fortran and APL

Fortran 2018 (GCC 15.2) ngn/apl
Program Structure
Hello, World
program hello implicit none print *, "Hello, World!" end program hello
'Hello, World!'
Fortran needs a full program name ... end program name wrapper and an explicit print *, statement. In APL, the value of the last expression is displayed automatically with no print statement at all — a bare string literal at the top level is a complete, runnable program.
Comments
program comments_demo implicit none ! This is a full-line comment integer :: total ! This is a trailing comment total = 10 print *, total end program comments_demo
⍝ This is a comment 10
Fortran comments start with !. APL comments start with (the "lamp" symbol, U+235D) — both run to the end of the line, and neither language has a block-comment syntax.
Assignment vs. ← (No Auto-Display After Assignment)
program assignment_demo implicit none character(len=20) :: greeting greeting = "Hello, World!" print *, trim(greeting) end program assignment_demo
greeting←'Hello, World!' greeting
Fortran assigns with a bare =. APL assigns with (left arrow, U+2190) — and unlike an ordinary expression, an assignment produces no automatic display at all, so a second line naming the variable is needed to actually show its value, mirroring how Fortran always needs an explicit print statement to show anything.
Arrays & Vectors
Array Literal
program array_literal_demo implicit none integer :: numbers(5) numbers = [1, 2, 3, 4, 5] print *, numbers end program array_literal_demo
1 2 3 4 5
Fortran builds an array literal with square brackets and comma-separated elements: [1, 2, 3, 4, 5]. APL needs neither brackets nor commas at all — space-separated numbers already form a vector, the most fundamental data structure in the language. Even a lone number is technically a length-1 vector.
Generating a Range: Fortran Loop Bounds vs. ⍳
program range_demo implicit none integer :: values(5), i do i = 1, 5 values(i) = i - 1 end do print *, values end program range_demo
⍳5
Fortran has no dedicated "generate a range" intrinsic — a sequence of numbers is built with an explicit do loop writing into pre-declared storage, as shown here for the values 0 through 4. APL's monadic (iota) function generates the same sequence in a single glyph: ⍳5 produces 0 1 2 3 4 directly, no loop and no pre-declared array needed.
SIZE Intrinsic vs. ≢ (Tally)
program size_demo implicit none integer :: numbers(5) numbers = [10, 20, 30, 40, 50] print *, size(numbers) end program size_demo
≢10 20 30 40 50
Fortran's size() intrinsic returns the number of elements in an array. APL's monadic (tally, U+2262) returns the same count for a vector — one glyph in place of a named function call.
2D Array Declaration vs. Reshape
program matrix_demo implicit none integer :: matrix(2,3) matrix = reshape([1, 2, 3, 4, 5, 6], [2,3]) print *, matrix end program matrix_demo
2 3⍴1 2 3 4 5 6
Both languages build a matrix by reshaping a flat sequence of values: Fortran's reshape([1,2,3,4,5,6], [2,3]) and APL's 2 3⍴1 2 3 4 5 6 (the dyadic , "rho", reshapes its right argument to the shape given on the left) both produce a 2×3 matrix from the same six values — though the two languages fill it in opposite memory orders (Fortran column-major, APL row-major).
Whole-Array Arithmetic (Both Languages Agree)
program whole_array_demo implicit none real :: prices(4) prices = [10.0, 20.0, 30.0, 40.0] prices = prices * 0.9 print *, prices end program whole_array_demo
0.9×10 20 30 40
Both languages agree here: arithmetic between an array and a scalar applies element-wise automatically with no loop, in Fortran and in APL alike. This is the deepest similarity between the two languages — the sharper contrasts on this page are about how much further APL takes the same idea, not whether it exists at all.
Elementwise Arithmetic Between Two Arrays
program two_array_demo implicit none integer :: a(4), b(4) a = [1, 2, 3, 4] b = [10, 20, 30, 40] print *, a + b end program two_array_demo
1 2 3 4+10 20 30 40
Elementwise addition between two same-length arrays needs no loop in either language — Fortran's a + b and APL's 1 2 3 4+10 20 30 40 both pair up corresponding elements automatically. Unlike R, neither language recycles a shorter array to match a longer one — both require matching shapes.
Arithmetic
⚠ ** Is Exponentiation in Fortran; * Is Exponentiation in APL Too, but × Is Multiply
program exponent_demo implicit none real :: result_value result_value = 2.0 ** 8 print *, "2^8 =", result_value end program exponent_demo
2*8
Fortran's exponentiation operator is **. APL's exponentiation operator is a bare * — and APL reserves the actual multiplication sign × (U+00D7) for multiplication, never the asterisk. A Fortran programmer's reflex to reach for * when they mean "multiply" produces exponentiation in APL instead — 2*8 is 256, not 16.
Integer Division vs. Division Always Produces a Real Result
program division_demo implicit none integer :: numerator, denominator real :: result_value numerator = 7 denominator = 2 result_value = real(numerator) / real(denominator) print *, result_value end program division_demo
7÷2
Fortran's plain / performs integer division when both operands are integers (7 / 2 is 3), requiring an explicit real() conversion to get the fractional result shown here. APL's ÷ (division, U+00F7, a distinct glyph from /, which means reduce) always produces the exact real result — 7÷2 is 3.5 with no conversion needed at all.
⚠ Unary Minus vs. High Minus (¯)
program negative_demo implicit none integer :: value value = -5 print *, value end program negative_demo
¯5
Fortran writes a negative literal with an ordinary hyphen-minus: -5. APL uses a visually distinct "high minus" glyph, ¯ (U+00AF, raised above the baseline), for a negative literal — the ordinary - is reserved exclusively for the subtraction function. Writing -5 in APL where a literal is expected is a syntax error, not a negative number.
FLOOR/CEILING Intrinsics vs. ⌊/⌈
program rounding_demo implicit none real :: value value = 3.7 print *, floor(value) print *, ceiling(value) end program rounding_demo
⌊3.7 ⌈3.7
Fortran's floor() and ceiling() intrinsics map onto APL's monadic (floor) and (ceiling) glyphs. Both symbols are also dyadic in APL — 3⌊5 returns the smaller of two values and 3⌈5 the larger, functioning as APL's min/max, a role Fortran covers separately with the min()/max() intrinsics.
Math Intrinsics — Both Always Available
program math_demo implicit none print *, sqrt(16.0) print *, abs(-7) end program math_demo
16*0.5 |¯7
Fortran's sqrt() is a dedicated intrinsic; APL instead expresses a square root as raising to the power of one-half (16*0.5), reusing the exponentiation glyph rather than a separate function. Fortran's abs() maps onto APL's monadic | (magnitude) — both are always available with no import in either language.
Strings
CHARACTER Fields vs. Character Vectors
program string_demo implicit none character(len=5) :: word word = "hello" print *, word end program string_demo
'hello'
Fortran's character(len=5) declares a fixed-width text field. APL has no separate string type at all — a quoted literal like 'hello' is simply a character vector, a 5-element array where each element happens to be a character; every array operation shown elsewhere on this page (reduction, indexing, reshaping) applies to strings automatically as a consequence.
LEN_TRIM vs. ≢ on a Character Vector
program length_demo implicit none character(len=20) :: greeting greeting = "Hello" print *, len_trim(greeting) end program length_demo
≢'Hello'
Fortran needs the dedicated len_trim() intrinsic to get a string's meaningful length, ignoring the padding a fixed-width field always carries. APL needs no special string function at all — (tally), the exact same glyph used to count elements of any array, already gives the correct length of a character vector, since a string is just an ordinary array in APL.
String Concatenation (//) vs. Comma (,)
program concat_demo implicit none character(len=5) :: first_word, second_word character(len=10) :: combined first_word = "Hello" second_word = "World" combined = trim(first_word) // trim(second_word) print *, trim(combined) end program concat_demo
'Hello','World'
Fortran concatenates strings with the dedicated // operator. APL uses the dyadic , (catenate) — the same operator that joins any two arrays end to end, whether they hold characters or numbers, since APL treats concatenating text as just one instance of the general array-joining operation, not a distinct string-specific feature.
No Fortran Intrinsic — Reverse (⌽)
program manual_reverse_demo implicit none character(len=5) :: word, reversed integer :: i word = "hello" do i = 1, 5 reversed(i:i) = word(6-i:6-i) end do print *, reversed end program manual_reverse_demo
⌽'hello'
Fortran has no built-in string- or array-reversal intrinsic — reversing a string means writing an explicit loop that copies characters from the end backward, as shown here. APL's monadic (reverse) reverses any vector, string or numeric, in a single glyph with no loop.
Array Shape
SHAPE Intrinsic vs. ⍴ (Monadic)
program shape_demo implicit none integer :: matrix(2,3) matrix = reshape([1,2,3,4,5,6], [2,3]) print *, shape(matrix) end program shape_demo
⍴2 3⍴1 2 3 4 5 6
Fortran's shape() intrinsic returns an array's dimension sizes. APL's monadic (rho) does the same — and since the same glyph is also the dyadic reshape operator used to build the matrix here, a single symbol covers both "what shape is this" and "make this shape," a genuine economy of notation Fortran does not have.
Array Slicing vs. Take (↑) and Drop (↓)
program slicing_demo implicit none integer :: numbers(5) numbers = [1, 2, 3, 4, 5] print *, numbers(1:3) print *, numbers(4:5) end program slicing_demo
3↑1 2 3 4 5 3↓1 2 3 4 5
Fortran's numbers(1:3) range syntax selects the first three elements by explicit position. APL's (take) and (drop) select or remove a count from either end instead of naming positions: 3↑numbers takes the first three, 3↓numbers drops the first three (returning the rest). A negative count in APL (¯2↑numbers) takes from the end — a capability Fortran's positional range syntax already covers differently, via explicit end-relative indices.
No Direct Fortran Equivalent — Enlist (∊)
program manual_flatten_demo implicit none ! Fortran arrays are already flat and rectangular by construction — ! there is no nested/ragged array type to "flatten" in the first place. integer :: numbers(4) numbers = [1, 2, 3, 4] print *, numbers end program manual_flatten_demo
∊(1 2)(3 4)
Fortran arrays are always flat and rectangular by construction — there is no nested or ragged array type to flatten in the first place, so this concept has no real Fortran counterpart. APL does allow genuinely nested arrays (an array whose elements are themselves arrays), and the monadic (enlist) flattens one into a simple vector, collecting every scalar regardless of nesting depth.
Selection & Indexing
Array Indexing
program index_demo implicit none integer :: numbers(5) numbers = [10, 20, 30, 40, 50] print *, numbers(3) end program index_demo
numbers←10 20 30 40 50 numbers[2]
Fortran indexes from 1 by default, so the third element is numbers(3). ngn/apl indexes from 0, matching Ruby, Python, and JavaScript — the third element is numbers[2]. Classic APL defaults to 1-based indexing the way Fortran does (controlled by ⎕IO), so this is a case where the specific in-browser interpreter this site runs genuinely differs from Fortran, unlike Julia or R, which both keep the traditional 1-based convention.
Selecting Multiple Elements by Index
program multi_index_demo implicit none integer :: numbers(5), selected(3) numbers = [10, 20, 30, 40, 50] selected = [numbers(1), numbers(3), numbers(5)] print *, selected end program multi_index_demo
numbers←10 20 30 40 50 numbers[0 2 4]
Selecting a scattered set of elements in Fortran means writing out each index explicitly. APL's bracket indexing accepts an entire vector of indices at once — numbers[0 2 4] ("fancy indexing") returns all three selected elements in a single expression, with no explicit list of individual accesses needed.
Fortran WHERE/PACK vs. Boolean Compress (/)
program pack_demo implicit none integer :: numbers(5) numbers = [1, 2, 3, 4, 5] print *, pack(numbers, numbers > 3) end program pack_demo
numbers←1 2 3 4 5 (numbers>3)/numbers
Fortran's pack(array, mask) intrinsic extracts the elements where a logical mask is true — conceptually identical to APL's dyadic / (compress): numbers>3 produces a Boolean vector, and / keeps only the corresponding elements of numbers. The two languages express nearly the same idea with a named intrinsic in Fortran versus a composed pair of glyphs in APL.
Matrix Indexing
program matrix_index_demo implicit none integer :: matrix(2,3) matrix = reshape([1,2,3,4,5,6], [2,3]) print *, matrix(2, 2) end program matrix_index_demo
matrix←2 3⍴1 2 3 4 5 6 matrix[1;1]
Fortran indexes a matrix with comma-separated subscripts inside one set of parentheses: matrix(2, 2) (1-based). APL uses a semicolon to separate dimensions inside brackets: matrix[1;1] (0-based in ngn/apl) — the semicolon, not a comma, is what separates row and column here, since a bare comma inside brackets would mean something different (selecting along one axis only).
Boolean Logic
⚠ LOGICAL Type vs. Booleans Are Just 0 and 1
program logical_demo implicit none logical :: is_ready is_ready = .true. print *, is_ready end program logical_demo
1
Fortran has a genuine logical type distinct from integer, with its own literals .true./.false.. APL has no boolean type at all — comparisons and logical operations simply produce ordinary numbers, 1 for true and 0 for false, fully interchangeable with any other number: 1+1 after a comparison works exactly like arithmetic on any other integer.
Vectorized Comparison
program comparison_demo implicit none integer :: numbers(5) logical :: mask(5) numbers = [1, 5, 3, 8, 2] mask = numbers > 3 print *, mask end program comparison_demo
1 5 3 8 2>3
Both languages compare an entire array against a scalar in one expression with no loop — Fortran's numbers > 3 and APL's 1 5 3 8 2>3 both produce a whole array of results, one comparison per element.
.AND./.OR./.NOT. vs. ∧/∨/~
program logical_ops_demo implicit none logical :: is_weekday, is_holiday is_weekday = .true. is_holiday = .false. print *, is_weekday .and. .not. is_holiday end program logical_ops_demo
1∧~0
Fortran spells its logical operators with surrounding dots: .and., .or., .not.. APL uses dedicated mathematical glyphs: (and, U+2227), (or, U+2228), and ~ (not) — all of which, unlike Fortran's operators, also vectorize automatically across whole Boolean arrays with no special syntax.
ALL/ANY Intrinsics vs. ∧/ and ∨/
program all_any_demo implicit none logical :: flags(4) flags = [.true., .true., .false., .true.] print *, all(flags) print *, any(flags) end program all_any_demo
∧/1 1 0 1 ∨/1 1 0 1
Fortran's all() and any() intrinsics check whether every element (or at least one element) of a logical array is true. APL reaches the identical result by reducing with the logical operators directly: ∧/ ("and-reduce") is all, and ∨/ ("or-reduce") is any — no dedicated intrinsic needed, since reduction with the right function already covers it.
Sorting & Searching
No Fortran Intrinsic — Grade Up (⍋)
program manual_sort_demo implicit none ! Fortran has no built-in sort intrinsic in the base language — ! sorting requires a hand-written algorithm or a library call. integer :: numbers(5) numbers = [30, 10, 40, 10, 50] print *, numbers end program manual_sort_demo
⍋30 10 40 10 50
Fortran has no sorting intrinsic in the base language at all — sorting an array means implementing an algorithm by hand (or calling into an external library). APL's monadic (grade up) returns the indices that would sort the array in ascending order in a single glyph — applying those indices back to the original array (numbers[⍋numbers]) produces the sorted values.
No Fortran Intrinsic — Membership (∊)
program manual_membership_demo implicit none integer :: numbers(4), i logical :: found numbers = [10, 20, 30, 40] found = .false. do i = 1, 4 if (numbers(i) == 30) found = .true. end do print *, found end program manual_membership_demo
30∊10 20 30 40
Fortran has no built-in "is this value present in this array" intrinsic — checking membership means writing a search loop by hand, as shown here. APL's dyadic (member of) checks membership directly: 30∊10 20 30 40 returns 1 (true) with no loop, and works elementwise when the left side is itself an array of values to check.
No Fortran Intrinsic — Index Of (⍳ Dyadic)
program manual_index_of_demo implicit none integer :: numbers(4), i, position numbers = [10, 20, 30, 40] position = -1 do i = 1, 4 if (numbers(i) == 30) position = i end do print *, position end program manual_index_of_demo
10 20 30 40⍳30
Fortran has no "find the position of this value" intrinsic — locating an element means a manual search loop. The dyadic form of (the same glyph as the monadic iota-range function, but with two arguments) searches: 10 20 30 40⍳30 returns the 0-based position of 30, or the array's length if the value is not found at all — a single overloaded glyph doing double duty as both "generate a range" and "find a position."
Sorting Descending: A Second Loop vs. Grade Down (⍒)
program manual_sort_desc_demo implicit none ! Sorting descending in Fortran means writing (or calling into) ! essentially the same sort algorithm as ascending, with the ! comparison direction flipped throughout. integer :: numbers(5) numbers = [3, 1, 4, 1, 5] print *, numbers end program manual_sort_desc_demo
numbers←3 1 4 1 5 numbers[⍒numbers]
Sorting descending in Fortran means writing (or calling) essentially the same sort algorithm as ascending, with every comparison flipped. APL's monadic (grade down) is the direct complement of (grade up) — it returns the indices for a descending sort in one glyph, and numbers[⍒numbers] applies them to get the sorted-descending array, with no second algorithm to write or maintain.
Reduction & Scanning
SUM Intrinsic vs. Reduce with + (/)
program sum_demo implicit none integer :: numbers(5) numbers = [1, 2, 3, 4, 5] print *, sum(numbers) end program sum_demo
+/1 2 3 4 5
Fortran's sum() intrinsic is a single named call. APL's / (reduce) operator inserts a function between every pair of elements — +/1 2 3 4 5 computes 1+2+3+4+5. The real power is that reduce works with any function, not just +: ×/ is product, ⌈/ is maximum, ∧/ is "all true" — one operator generalizes what Fortran needs a whole family of separate named intrinsics (sum, product via a loop, maxval, all) to cover.
MAXVAL/MINVAL vs. ⌈/ and ⌊/
program maxval_demo implicit none integer :: numbers(5) numbers = [3, 1, 4, 1, 5] print *, maxval(numbers) print *, minval(numbers) end program maxval_demo
⌈/3 1 4 1 5 ⌊/3 1 4 1 5
Fortran's maxval()/minval() intrinsics map onto APL's ⌈/ (ceiling-reduce) and ⌊/ (floor-reduce) — the same glyphs used for the dyadic max/min functions, now reducing across a whole array instead of comparing just two values.
Factorial: Loop vs. Reduction
program factorial_demo implicit none integer :: result_value, i result_value = 1 do i = 1, 5 result_value = result_value * i end do print *, result_value end program factorial_demo
×/1+⍳5
Fortran computes a factorial with an explicit accumulator loop: initialize to 1, then multiply by each number from 1 to 5 in turn. APL composes the same result from array primitives with no loop and no accumulator variable: ⍳5 generates 0 1 2 3 4, adding 1 shifts it to 1 2 3 4 5, and ×/ multiplies everything together — three glyphs chained into one expression.
⚠ No Fortran Equivalent — Scan (\)
program running_sum_demo implicit none integer :: numbers(5), running(5), i, total numbers = [1, 2, 3, 4, 5] total = 0 do i = 1, 5 total = total + numbers(i) running(i) = total end do print *, running end program running_sum_demo
+\1 2 3 4 5
Fortran has no built-in "running total" intrinsic — computing one at every position requires an explicit accumulator loop, exactly the pattern shown here. APL's \ (scan) operator is like reduce but keeps every intermediate result: +\1 2 3 4 5 directly returns 1 3 6 10 15, the running sum at each position, in a single glyph with no loop or accumulator variable at all.
Higher-Order & Dfns
ELEMENTAL Functions vs. Each (¨)
program elemental_demo implicit none integer :: numbers(5) numbers = [1, 2, 3, 4, 5] print *, square(numbers) contains elemental function square(n) result(squared) integer, intent(in) :: n integer :: squared squared = n * n end function square end program elemental_demo
{⍵×⍵}¨1 2 3 4 5
A Fortran elemental function is written as if for a single scalar, but the compiler automatically applies it across an entire array with no explicit loop. APL's ¨ (each) operator plays the identical role explicitly: {⍵×⍵}¨1 2 3 4 5 applies the squaring dfn to every element — the same broadcasting idea, but visible in the syntax as its own operator rather than a compiler-inferred property of the function's declaration.
⚠ No Closures in Fortran — Dfns Are First-Class
program no_first_class_demo implicit none print *, double_it(5) ! Fortran has no way to pass this function around as a value, ! store it in a variable, or define it anonymously inline — ! it must be a named subprogram declared up front. contains function double_it(n) result(doubled) integer, intent(in) :: n integer :: doubled doubled = n * 2 end function double_it end program no_first_class_demo
double←{⍵×2} double 5
Fortran functions must always be named subprograms declared up front — there is no way to define one anonymously inline, store it in a variable, or pass it around as an ordinary value. APL's dfns (direct functions, written {body}) are genuinely first-class: double←{⍵×2} assigns an anonymous function to a name exactly like assigning any other value, and it can just as easily be used inline with no name at all: {⍵×2} 5.
Two-Argument Function vs. Dyadic Dfn
program two_arg_demo implicit none print *, add(3, 4) contains function add(a, b) result(sum_value) integer, intent(in) :: a, b integer :: sum_value sum_value = a + b end function add end program two_arg_demo
add←{⍺+⍵} 3 add 4
A Fortran function with two parameters is called with ordinary parenthesized syntax: add(3, 4). An APL dyadic dfn instead places its two implicit arguments as (alpha, left) and (omega, right), and is called by placing the function name between them: 3 add 4 — closer to how + or × already read in ordinary APL arithmetic than to a Fortran-style function call.
Nested DO Loops vs. Outer Product (∘.f)
program multiplication_table_demo implicit none integer :: table(3,3), i, j do i = 1, 3 do j = 1, 3 table(i, j) = i * j end do end do print *, table end program multiplication_table_demo
1 2 3∘.×1 2 3
Building a multiplication table in Fortran means nesting two do loops, one per dimension. APL's outer product operator ∘.f applies a function to every combination of elements from two arrays in a single expression: 1 2 3∘.×1 2 3 produces the entire 3×3 multiplication table directly, with × swappable for any other function — ∘.= builds a Boolean equality table, ∘.+ an addition table — with no change to the looping structure, since there is none.
RECURSIVE Keyword vs. ∇ (Self-Reference)
program recursive_demo implicit none print *, "5! =", factorial(5) contains recursive function factorial(n) result(product_value) integer, intent(in) :: n integer :: product_value if (n <= 1) then product_value = 1 else product_value = n * factorial(n - 1) end if end function factorial end program recursive_demo
factorial←{⍵≤1:1 ⋄ ⍵×∇⍵-1} factorial 5
Fortran requires the explicit recursive keyword before a function may call itself by name. Inside an APL dfn, (del) refers back to the dfn itself with no separate keyword needed — ∇⍵-1 calls the current function on ⍵-1. The guard syntax condition:result (with , diamond, separating clauses) is APL's primary conditional inside a dfn, playing the role Fortran's if/else plays here.
IF/ELSE IF Chain vs. Guards in a Dfn
program sign_demo implicit none print *, sign_of(5) contains function sign_of(x) result(sign_value) integer, intent(in) :: x integer :: sign_value if (x < 0) then sign_value = -1 else if (x > 0) then sign_value = 1 else sign_value = 0 end if end function sign_of end program sign_demo
signOf←{⍵<0:¯1 ⋄ ⍵>0:1 ⋄ 0} signOf 5
Fortran expresses a multi-branch conditional with if / else if / else / end if, each branch on its own indented lines. A dfn's guards use the compact form condition:result, with (diamond) separating each guard and a final bare expression as the default — evaluated left to right, with the first true guard winning, the entire three-branch conditional fits on one line.
Trains
⚠ No Fortran Equivalent — Tacit Composition (Trains)
program average_demo implicit none integer :: numbers(5) real :: average_value numbers = [1, 2, 3, 4, 5] average_value = real(sum(numbers)) / size(numbers) print *, average_value end program average_demo
(+/÷≢)1 2 3 4 5
Fortran always names every intermediate step explicitly — computing an average means naming a sum, naming a count, and naming their quotient, even if only briefly. APL's trains let three functions compose directly with no variables anywhere: (+/÷≢) is a genuine, nameless function that computes sum-divided-by-count on whatever it is given, built by writing +/ (sum) and (count) side by side around ÷ with no argument names at all — a form of point-free, "tacit" programming that has no Fortran counterpart whatsoever.
Function Composition: Named Steps vs. Atop
program composition_demo implicit none integer :: numbers(5) numbers = [3, 1, 4, 1, 5] print *, -sum(numbers) end program composition_demo
(-+/)3 1 4 1 5
Fortran composes two operations by writing them out in sequence with an intermediate result, or nesting one call inside another: -sum(numbers). APL's two-function train, "atop," does the same with no intermediate name at all: (-+/) reads as "negate the sum of" — +/ runs first (sum), then - negates the result, chained together as a single tacit function with the argument supplied only once, at the very end.
⚠ Gotchas for Fortran Programmers
⚠ No Operator Precedence — Strictly Right to Left
program precedence_demo implicit none integer :: result_value result_value = 2 * 3 + 4 ! Fortran: * before +, so this is 6 + 4 = 10 print *, result_value end program precedence_demo
2×3+4
Fortran follows ordinary mathematical operator precedence: 2 * 3 + 4 computes 2*3=6 first (multiplication binds tighter than addition), then adds 4, giving 10. APL has no operator precedence rules at all — every expression evaluates strictly right to left, with no exceptions. 2×3+4 computes 3+4=7 first (the rightmost operation), then 2×7=14 — the identical-looking expression means two different numbers in the two languages. Parentheses are the only way to override APL's right-to-left order.
⚠ APL Has No Loop Construct in the Language
program has_loops_demo implicit none integer :: numbers(5), i, total numbers = [1, 2, 3, 4, 5] total = 0 do i = 1, 5 total = total + numbers(i) end do print *, total end program has_loops_demo
+/1 2 3 4 5
Fortran's whole-array arithmetic covers elementwise operations, but a do loop remains the everyday tool for search, accumulation, per-element branching, and anything not already an intrinsic — Fortran is an array-aware language built around loops as the general-purpose fallback. APL has no loop construct in the language at all (dfns can achieve iteration only indirectly, through recursion via ) — reduction, scan, compress, each, and outer product between them replace essentially every use of iteration a Fortran programmer would otherwise reach for do to express.
Fortran Column-Major vs. APL Row-Major
program column_major_demo implicit none integer :: matrix(2,3) matrix = reshape([1,2,3,4,5,6], [2,3]) ! Fortran fills column-by-column: 1,2 | 3,4 | 5,6 print *, matrix(1,1), matrix(2,1), matrix(1,2) end program column_major_demo
matrix←2 3⍴1 2 3 4 5 6 ⍝ APL fills row-by-row: 1,2,3 | 4,5,6 matrix[0;0] matrix[0;1] matrix[0;2]
Fortran's reshape fills a matrix column-by-column — the same six values 1 2 3 4 5 6 reshaped to 2×3 lands as columns (1,2), (3,4), (5,6). APL's reshape fills row-by-row — the identical six values become row (1,2,3) then row (4,5,6). The same flat data and the same target shape produce two genuinely different matrices, one more instance of the memory-layout mismatch a Fortran programmer needs to watch for when moving to almost any other array language.
LOGICAL Is a Distinct Type; APL Booleans Are Ordinary Numbers
program logical_type_demo implicit none logical :: flag integer :: count_value flag = .true. ! flag + 1 would be a TYPE ERROR in Fortran — logical and ! integer are genuinely distinct types, never interchangeable. count_value = 1 print *, count_value end program logical_type_demo
(3>2)+1
Fortran's logical is a genuinely distinct type from integer — mixing them (adding a number directly to a logical value) is a compile-time type error. In APL there is no such boundary to cross: a comparison like 3>2 simply produces the number 1, which can be added to, multiplied by, or reduced alongside any other number with no conversion of any kind — (3>2)+1 is 2, ordinary arithmetic on what looks like a boolean result.
A Single Glyph Can Be a Complete Working Program
program not_a_single_char_demo implicit none ! There is no way to express "sum this array" as a single ! character or symbol in Fortran — sum() is the shortest form, ! itself a five-character named intrinsic call. integer :: numbers(5) numbers = [1, 2, 3, 4, 5] print *, sum(numbers) end program not_a_single_char_demo
+/1 2 3 4 5
Even Fortran's shortest expression of an idea is a named intrinsic call like sum(numbers) — recognizable English words remain the unit of vocabulary. APL pushes information density to the opposite extreme: +/ is two characters, and many single APL primitives (, , , ) each replace what would otherwise be an entire named function or a small loop. This is deliberate design, not abbreviation for its own sake — but it does mean an unfamiliar glyph sequence can be far harder to read at a glance than the equivalent Fortran, despite doing more work per character.