PONY λ M2 Modula-2

Pascal.CodeCompared.To/Fortran

An interactive executable cheatsheet comparing Pascal and Fortran

Free Pascal 3.2.2 Fortran 2018 (GCC 15.2)
Program Structure
Hello, World
program Hello; begin writeln('Hello, World!'); end.
program hello implicit none print *, "Hello, World!" end program hello
Both languages wrap the whole program in a single named block: Pascal's program Name; begin ... end. and Fortran's program name ... end program name. Fortran additionally requires implicit none as the very first statement in idiomatic modern code — without it, Fortran silently infers a variable's type from its first letter (a historical quirk Pascal never had, since Pascal has always required every variable to be declared).
Comments
program Comments; var total: Integer; { This is a trailing comment } begin { This is a full-line comment } total := 10; writeln(total); end.
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
Pascal comments use curly braces { ... } (or (* ... *)); Fortran comments start with ! and run to the end of the line. Both languages' comment styles are considerably more modern than their 1950s/1970s-era predecessors' fixed-column punch-card comment conventions.
Data Types
Integer and Real — nearly identical vocabulary
program TypesDemo; var count: Integer; price: Real; begin count := 42; price := 19.99; writeln(count); writeln(price:0:2); end.
program types_demo implicit none integer :: count real :: price count = 42 price = 19.99 print *, count print *, price end program types_demo
Both languages use nearly the same names for their basic numeric types — Pascal's Integer/Real and Fortran's integer/real — a genuinely close vocabulary match, unlike most other language pairs on this site.
implicit none: Fortran opts in to what Pascal always had
program AlwaysStrict; var total: Integer; begin { Pascal has never had implicit typing at all — every variable must always be declared before use, with no pragma needed to enforce it: } total := 10; writeln(total); end.
program strict_demo implicit none ! Without "implicit none", a variable starting with I-N would ! default to INTEGER and everything else to REAL, with no ! declaration required at all — a historical Fortran quirk ! Pascal has never had: integer :: total total = 10 print *, total end program strict_demo
Fortran's implicit none statement opts a program IN to mandatory variable declarations — without it, an undeclared variable's type is inferred from its first letter (I through N default to integer, everything else to real), a historical carryover from Fortran's earliest versions. Pascal has never had implicit typing at all; every variable has always required an explicit declaration, with no pragma needed to enforce what is simply the only way Pascal works.
Variables & Constants
const versus the PARAMETER attribute
program ConstDemo; const Pi = 3.14159265358979; var radius, area: Real; begin radius := 5.0; area := Pi * radius * radius; writeln(area:0:2); end.
program parameter_demo implicit none real, parameter :: pi = 3.14159265358979 real :: radius, area radius = 5.0 area = pi * radius * radius print *, area end program parameter_demo
Pascal's const block declares compile-time constants separately, before var. Fortran attaches the parameter attribute directly to a variable declaration (real, parameter :: pi = ...), folding the "this never changes" property into the type declaration itself rather than a separate section.
Arithmetic
Arithmetic operators — a direct match
program ArithmeticDemo; var balance: Integer; begin balance := 100; balance := balance + 50; balance := balance - 20; writeln(balance); end.
program arithmetic_demo implicit none integer :: balance balance = 100 balance = balance + 50 balance = balance - 20 print *, balance end program arithmetic_demo
Both languages use the same ordinary infix arithmetic operators. The only visible difference is the assignment operator itself: Pascal's := versus Fortran's bare = — Fortran has no separate equality-test symbol conflict to avoid, since == is reserved for logical comparison inside conditions instead.
Integer division: div/mod versus / and mod
program DivModDemo; var quotient, remainder: Integer; begin quotient := 17 div 5; remainder := 17 mod 5; writeln(quotient, ' ', remainder); end.
program div_mod_demo implicit none integer :: quotient, remainder quotient = 17 / 5 remainder = mod(17, 5) print *, quotient, remainder end program div_mod_demo
Pascal uses the dedicated keyword div for integer division and mod as an infix operator. Fortran overloads the ordinary / operator for integer division when both operands are integers (truncating automatically), and spells remainder as the function call mod(a, b) rather than an infix operator.
Dynamic Strings vs. Fixed-Width Fields
String concatenation: + versus //
program ConcatDemo; var firstName, lastName, fullName: string; begin firstName := 'Alice'; lastName := 'Smith'; fullName := firstName + ' ' + lastName; writeln(fullName); end.
program concat_demo implicit none character(len=20) :: first_name, last_name character(len=41) :: full_name first_name = "Alice" last_name = "Smith" full_name = trim(first_name) // " " // trim(last_name) print *, trim(full_name) end program concat_demo
Pascal reuses the ordinary + arithmetic operator for string concatenation — the compiler infers its meaning from the operand types. Fortran uses the dedicated // operator instead, and needs an explicit trim() call to strip trailing padding first, since a Fortran character(len=n) field is always exactly its declared width.
A role reversal: Pascal is the more dynamic string type here
program DynamicStringDemo; var greeting: string; begin greeting := 'Hello'; writeln('Length: ', Length(greeting)); greeting := greeting + ', World! And more!'; writeln('New length: ', Length(greeting)); end.
program fixed_width_demo implicit none character(len=20) :: greeting greeting = "Hello" print *, "Length:", len_trim(greeting) ! Growing "greeting" beyond its declared len=20 would silently ! TRUNCATE the extra characters — there is no dynamic resizing: greeting = greeting(1:len_trim(greeting)) // ", World! And more!" print *, "New length:", len_trim(greeting) end program fixed_width_demo
This is an unusual role reversal for a Pascal programmer: Pascal's string is a dynamically-sized, managed type that grows and shrinks automatically, needing no declared maximum size at all. Fortran's character(len=n) is a genuinely fixed-width field — n is chosen once at declaration, and any content beyond it is silently TRUNCATED rather than growing the field, closer to how a C string buffer with a hardcoded size behaves than to Pascal's own string type.
Length: one function versus two
program LengthDemo; var greeting: string; begin greeting := 'Hello'; writeln('Length: ', Length(greeting)); end.
program len_trim_demo implicit none character(len=20) :: greeting greeting = "Hello" print *, "Declared width:", len(greeting) print *, "Trimmed length:", len_trim(greeting) end program len_trim_demo
Pascal needs only one length function, Length, because a dynamic string has no padding to distinguish from its content — its length is always exactly the number of characters it currently holds. Fortran needs two: len() returns the declared field WIDTH (always 20 here, regardless of content), while len_trim() returns the length ignoring trailing padding — a distinction that only exists because of Fortran's fixed-width fields.
Whole-Array Operations: a New Capability
Array declaration with explicit bounds — a close match
program ArrayDeclarationDemo; var scores: array[1..5] of Integer; begin scores[1] := 85; scores[2] := 92; scores[5] := 78; writeln(scores[1]); writeln(scores[5]); end.
program array_declaration_demo implicit none integer :: scores(1:5) scores(1) = 85 scores(2) = 92 scores(5) = 78 print *, scores(1) print *, scores(5) end program array_declaration_demo
Both languages let the programmer choose arbitrary array bounds rather than being locked to 0-based indexing: Pascal's array[1..5] and Fortran's scores(1:5) both declare a 5-element array indexed 1 through 5 — either language could just as easily use [0..4] or (0:4) instead.
⚠ Whole-array arithmetic: a genuinely new capability
program ElementLoopDemo; var prices: array[1..3] of Double; i: Integer; begin prices[1] := 10.0; prices[2] := 20.0; prices[3] := 30.0; for i := 1 to 3 do prices[i] := prices[i] * 0.9; for i := 1 to 3 do write(prices[i]:0:2, ' '); writeln; end.
program whole_array_demo implicit none real :: prices(3) prices = [10.0, 20.0, 30.0] prices = prices * 0.9 ! scale every element at once print *, prices end program whole_array_demo
This is the headline structural difference between these two otherwise-similar languages, and a genuinely new capability for a Pascal programmer. Fortran treats an array as a value you can operate on directly: prices = prices * 0.9 multiplies every element in a single statement, with no loop at all. Pascal has no whole-array operators whatsoever — scaling every element always requires an explicit for loop written out by hand, even though the two languages agree on almost everything else about arrays (bounds, declaration style, 1-based-by-choice indexing).
SUM intrinsic versus manual accumulation
program ArraySumDemo; var numbers: array[1..5] of Integer; i, total: Integer; begin numbers[1] := 10; numbers[2] := 20; numbers[3] := 30; numbers[4] := 40; numbers[5] := 50; total := 0; for i := 1 to 5 do total := total + numbers[i]; writeln('Total: ', total); end.
program array_sum_demo implicit none integer :: numbers(5), total numbers = [10, 20, 30, 40, 50] total = sum(numbers) print *, "Total:", total end program array_sum_demo
Fortran's sum() intrinsic totals an entire array in a single call. Pascal has no equivalent built-in for a plain static array — the standard idiom is a for loop that adds each element into an accumulator initialized to zero, one more consequence of Pascal's lack of whole-array operations.
Control Flow
If / Else
program IfElseDemo; var score: Integer; begin score := 85; if score >= 90 then writeln('A') else if score >= 80 then writeln('B') else writeln('Below B'); end.
program if_else_demo implicit none integer :: score score = 85 if (score >= 90) then print *, "A" else if (score >= 80) then print *, "B" else print *, "Below B" end if end program if_else_demo
Both languages structure if/else if/else nearly identically. Fortran requires parentheses around the condition and an explicit end if closing statement; Pascal uses then with no parentheses and needs begin...end only when a branch has more than one statement.
case becomes SELECT CASE
program CaseDemo; var dayNumber: Integer; begin dayNumber := 3; case dayNumber of 1: writeln('Monday'); 2: writeln('Tuesday'); 3: writeln('Wednesday'); else writeln('Unknown'); end; end.
program select_case_demo implicit none integer :: day_number day_number = 3 select case (day_number) case (1) print *, "Monday" case (2) print *, "Tuesday" case (3) print *, "Wednesday" case default print *, "Unknown" end select end program select_case_demo
Pascal's case...of and Fortran's select case are close structural cousins, both matching a discrete value against a chain of alternatives with a catch-all (Pascal's else, Fortran's case default). Fortran additionally supports matching a contiguous range in one case (case (1:5)), something Pascal expresses instead with a comma-separated list of individual values.
Loops
for becomes do
program ForLoop; var counter: Integer; begin for counter := 1 to 5 do writeln(counter); end.
program do_loop_demo implicit none integer :: counter do counter = 1, 5 print *, counter end do end program do_loop_demo
Pascal's for counter := 1 to 5 do and Fortran's do counter = 1, 5 are close structural cousins — both iterate a counter over an inclusive range with a step of 1 by default. Fortran's do loop additionally accepts an explicit third step value (do i = 10, 1, -1), where Pascal needs the separate downto keyword just for stepping backward by exactly 1, with no other step size available at all.
While loop — nearly identical
program WhileLoop; var count: Integer; begin count := 0; while count < 5 do begin writeln(count); count := count + 1; end; end.
program while_loop_demo implicit none integer :: count count = 0 do while (count < 5) print *, count count = count + 1 end do end program while_loop_demo
Pascal's while condition do and Fortran's do while (condition) are nearly the same construct with the keyword order swapped — both continue looping WHILE the condition holds, unlike COBOL's inverted PERFORM UNTIL phrasing.
const/var/out vs. intent — a Near-Exact Mapping
const parameter versus intent(in) — a near-exact mapping
program ConstParamDemo; function CircleArea(radius: Real): Real; const Pi = 3.14159265358979; begin CircleArea := Pi * radius * radius; end; begin writeln(CircleArea(5.0):0:2); end.
program intent_in_demo implicit none print *, circle_area(5.0) contains function circle_area(radius) result(area) real, intent(in) :: radius real, parameter :: pi = 3.14159265358979 real :: area area = pi * radius * radius end function circle_area end program intent_in_demo
Pascal's plain value parameters (no var modifier, as used here for radius) and Fortran's intent(in) both tell the compiler the parameter is read-only for the duration of the call, and both are checked at compile time — this is one of the closest one-to-one mappings between the two languages' feature sets on the entire site.
var parameter versus intent(inout) — completing the correspondence
program VarParamDemo; procedure Swap(var firstValue, secondValue: Integer); var tempValue: Integer; begin tempValue := firstValue; firstValue := secondValue; secondValue := tempValue; end; var firstNumber, secondNumber: Integer; begin firstNumber := 1; secondNumber := 2; Swap(firstNumber, secondNumber); writeln(firstNumber, ' ', secondNumber); end.
program intent_inout_demo implicit none integer :: first_number, second_number first_number = 1 second_number = 2 call swap(first_number, second_number) print *, first_number, second_number contains subroutine swap(first_value, second_value) integer, intent(inout) :: first_value, second_value integer :: temp_value temp_value = first_value first_value = second_value second_value = temp_value end subroutine swap end program intent_inout_demo
Pascal's var parameter modifier and Fortran's intent(inout) both pass the caller's actual variable by reference, letting the procedure both read and modify it in place — another near-exact mapping. Fortran additionally has a write-only intent(out) mode matching a Pascal out parameter, completing the correspondence across all three modes both languages share.
Functions
Result versus an explicit result() clause
program SquareDemo; function Square(n: Integer): Integer; begin Square := n * n; end; begin writeln(Square(7)); end.
program square_demo implicit none print *, square(7) contains function square(n) result(squared) integer, intent(in) :: n integer :: squared squared = n * n end function square end program square_demo
Free Pascal assigns the return value with FunctionName := value — a special built-in variable sharing the function's own name. Fortran's result(squared) clause names a completely separate variable to hold the return value, avoiding any naming collision between the function and its own result — a small but genuine ergonomic difference.
Records vs. Derived Types
Record versus derived type — a close match
program RecordDemo; type TPoint = record X: Real; Y: Real; end; var point: TPoint; begin point.X := 3.0; point.Y := 4.0; writeln(point.X:0:1, ', ', point.Y:0:1); end.
program derived_type_demo implicit none type :: point_type real :: x real :: y end type point_type type(point_type) :: point point%x = 3.0 point%y = 4.0 print *, point%x, point%y end program derived_type_demo
Pascal's record and Fortran's derived type are a close structural match — both group named, typed fields under one named type. The field-access syntax differs slightly: Pascal's dot (point.X) versus Fortran's percent sign (point%x), a Fortran-specific choice made because . was already used for logical operators like .true./.and. in older Fortran.
A Numerical Toolkit Pascal Lacks
MAXVAL/MINVAL: no Pascal equivalent for a plain array
program MaxMinDemo; var numbers: array[1..5] of Integer; i, highest, lowest: Integer; begin numbers[1] := 30; numbers[2] := 10; numbers[3] := 50; numbers[4] := 20; numbers[5] := 40; highest := numbers[1]; lowest := numbers[1]; for i := 2 to 5 do begin if numbers[i] > highest then highest := numbers[i]; if numbers[i] < lowest then lowest := numbers[i]; end; writeln(highest, ' ', lowest); end.
program maxval_minval_demo implicit none integer :: numbers(5) numbers = [30, 10, 50, 20, 40] print *, maxval(numbers), minval(numbers) end program maxval_minval_demo
Fortran's maxval()/minval() intrinsics find the largest/smallest element of an entire array in one call each. Pascal has no built-in equivalent for a plain static array — finding either requires a hand-written loop tracking a running highest/lowest value, one more example of the numerical-array toolkit Fortran ships that Pascal simply does not have.
WHERE: conditional whole-array assignment with no Pascal parallel
program ConditionalLoopDemo; var values: array[1..5] of Real; i: Integer; begin values[1] := -3.0; values[2] := 5.0; values[3] := -1.0; values[4] := 8.0; values[5] := -2.0; for i := 1 to 5 do if values[i] < 0 then values[i] := 0.0; for i := 1 to 5 do write(values[i]:0:1, ' '); writeln; end.
program where_demo implicit none real :: values(5) values = [-3.0, 5.0, -1.0, 8.0, -2.0] where (values < 0) values = 0.0 end where print *, values end program where_demo
Fortran's where construct applies a condition and an assignment to every array element that matches, all in one statement, with no explicit loop or index variable at all — a genuinely new capability with no Pascal equivalent whatsoever, since Pascal always needs an explicit indexed loop to inspect and conditionally modify individual elements.
Gotchas for Pascal Developers
Array literal syntax: [ ] in both, but for different collections
program ArrayInitDemo; var numbers: array[1..3] of Integer; begin { Pascal has no bare array-literal assignment syntax at all in an executable statement — each element must be assigned individually: } numbers[1] := 1; numbers[2] := 2; numbers[3] := 3; writeln(numbers[1], ' ', numbers[2], ' ', numbers[3]); end.
program array_constructor_demo implicit none integer :: numbers(3) numbers = [1, 2, 3] print *, numbers end program array_constructor_demo
Fortran's [1, 2, 3] "array constructor" syntax builds and assigns a whole array in a single executable statement. Free Pascal has no equivalent for an ordinary executable assignment — a parenthesised literal like (1, 2, 3) is only valid inside a const initialiser, never in an executable := statement, so each element must be assigned individually as shown.
Both are 1-based only by convention, not by language rule
program ZeroBasedDemo; var numbers: array[0..4] of Integer; begin numbers[0] := 100; writeln(numbers[0]); end.
program zero_based_demo implicit none integer :: numbers(0:4) numbers(0) = 100 print *, numbers(0) end program zero_based_demo
A common misconception is that Fortran arrays are always 1-indexed. Both Pascal and Fortran default their examples in this comparison to 1-based indexing purely as a style convention shared with mathematical notation — both languages equally support explicit 0-based (or any other) bounds, as shown here with [0..4]/(0:4). Neither language enforces one convention over the other the way, say, C or Python effectively does with universal 0-indexing.