Program Structure
Hello, World
program hello
implicit none
print *, "Hello, World!"
end program hello program HelloWorld;
begin
writeln('Hello, World!');
end. Fortran opens with
program name and closes with end program name. Pascal opens with program Name; and closes with a lone end. — the trailing period, not a repeated name, marks the end of the whole program. writeln is Pascal's direct equivalent of Fortran's print *,.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 program CommentsDemo;
var
total: Integer;
begin
{ This is a full-line comment }
total := 10; { This is a trailing comment }
writeln(total);
end. Fortran comments use
! and run to the end of the line. Pascal comments are bracketed with { ... } (or, equivalently, (* ... *)) and can span multiple lines, unlike Fortran's single-line-only comment marker.Declarations Section vs. VAR Block
program declarations_demo
implicit none
integer :: score
real :: average
score = 95
average = 88.5
print *, "Score:", score
print *, "Average:", average
end program declarations_demo program DeclarationsDemo;
var
score: Integer;
average: Double;
begin
score := 95;
average := 88.5;
writeln('Score: ', score);
writeln('Average: ', average:0:1);
end. Both languages separate declarations from executable code, but the shape differs: Fortran interleaves
integer ::/real :: declarations directly after implicit none, one type keyword per line (or per group). Pascal collects every declaration under a single var keyword, one name-and-type pair per line, all before the begin that starts the executable section.CONTAINS vs. Procedures Declared Before the Main Block
program contains_demo
implicit none
call greet()
contains
subroutine greet()
print *, "Hello!"
end subroutine greet
end program contains_demo program ContainsDemo;
procedure Greet;
begin
writeln('Hello!');
end;
begin
Greet;
end. Fortran places internal subprograms after the main body, introduced by
contains. Pascal is the mirror image: every procedure or function must be fully declared before the main begin...end. block that uses it, since Pascal compiles top-to-bottom in a single pass and has no forward-reference mechanism for ordinary procedures.Both Languages Are Case-Insensitive
program case_demo
implicit none
integer :: Total
Total = 10
print *, total
print *, TOTAL
end program case_demo program CaseDemo;
var
Total: Integer;
begin
Total := 10;
writeln(total);
writeln(TOTAL);
end. A rare point of agreement: both Fortran and Pascal treat identifiers and reserved words as case-insensitive, so
Total, total, and TOTAL all refer to the same variable in both languages. Convention in both is to pick one casing per identifier and use it consistently — the compiler does not enforce it.Data Types
INTEGER vs. Sized Integer Types
program integer_demo
use iso_fortran_env, only: int64
implicit none
integer :: normal_number
integer(kind=int64) :: large_number
normal_number = 2147483647
large_number = 9000000000_int64
print *, "Normal:", normal_number
print *, "Large:", large_number
end program integer_demo program IntegerTypes;
var
normalNumber: Integer; { 32-bit on most platforms }
largeNumber: Int64; { 64-bit }
begin
normalNumber := 2147483647;
largeNumber := 9000000000;
writeln('Normal: ', normalNumber);
writeln('Large: ', largeNumber);
end. Fortran controls integer width through the KIND system (
integer(kind=int64)). Pascal instead offers a family of differently-named types for each width — ShortInt (8-bit), SmallInt (16-bit), Integer (32-bit), Int64 (64-bit) — chosen by picking the type name directly rather than parameterizing one generic integer keyword.REAL/DOUBLE PRECISION vs. Single/Double
program real_demo
implicit none
real :: single_value
double precision :: double_value
single_value = 3.14159
double_value = 3.14159265358979d0
print *, "Single:", single_value
print *, "Double:", double_value
end program real_demo program RealTypes;
var
singleValue: Single; { 32-bit }
doubleValue: Double; { 64-bit — the everyday floating-point type }
begin
singleValue := 3.14159;
doubleValue := 3.14159265358979;
writeln('Single: ', singleValue:0:5);
writeln('Double: ', doubleValue:0:14);
end. Fortran's
real and double precision map directly onto Pascal's Single and Double — both languages give the programmer explicit 32-bit and 64-bit binary floating-point types with no default-precision ambiguity. Both are IEEE 754 under the hood, so both carry the same binary rounding error for values like 0.1.LOGICAL vs. Boolean
program logical_demo
implicit none
logical :: is_ready
is_ready = .true.
if (is_ready) then
print *, "Ready"
end if
end program logical_demo program BooleanDemo;
var
isReady: Boolean;
begin
isReady := True;
if isReady then
writeln('Ready');
end. Fortran's
logical literals are .true./.false., surrounded by dots. Pascal's Boolean literals are the bare words True/False, capitalized by convention but not required to be (Pascal is case-insensitive). Both are genuine boolean types, unlike COBOL, which has none at all.A Single CHARACTER vs. Char
program char_demo
implicit none
character(len=1) :: grade
grade = "A"
print *, "Grade:", grade
end program char_demo program CharDemo;
var
grade: Char;
begin
grade := 'A';
writeln('Grade: ', grade);
end. A single character is
character(len=1) in Fortran (a 1-element string, since Fortran has no separate character-vs-string distinction) and Char in Pascal (a genuinely distinct type from string). Both use single quotes for character/string literals.CHARACTER(len=n) vs. Dynamic String
program fixed_string_demo
implicit none
character(len=10) :: name
name = "Alice"
print *, "Name: [", trim(name), "]"
print *, "Declared length:", len(name)
end program fixed_string_demo program DynamicStringDemo;
var
name: string;
begin
name := 'Alice';
writeln('Name: [', name, ']');
writeln('Current length: ', Length(name));
name := name + ' Smith';
writeln('After append: ', name, ' (length ', Length(name), ')');
end. Fortran's
character(len=10) is a fixed-width, blank-padded field — its length never changes, and appending text beyond 10 characters truncates. Pascal's string type is dynamically sized: appending text grows it automatically, with no declared maximum and no padding at all. This is a role reversal worth noting, since Pascal is otherwise the more manual, lower-level language of the two.Variables & Constants
Assignment (=) vs. Assignment (:=)
program assignment_demo
implicit none
integer :: count
count = 5
count = count + 1
print *, count
end program assignment_demo program AssignmentDemo;
var
count: Integer;
begin
count := 5;
count := count + 1;
writeln(count);
end. Fortran uses a bare
= for assignment, the same symbol used for equality comparisons in an if. Pascal uses the two-character := for assignment specifically, reserving bare = exclusively for equality comparison — so count = 5 would be a comparison expression in Pascal, not an assignment, and would not even compile as a standalone statement.PARAMETER vs. Const
program parameter_demo
implicit none
real, parameter :: pi = 3.14159265358979
real, parameter :: gravity = 9.81
print *, "Pi:", pi
print *, "Gravity:", gravity
end program parameter_demo program ConstDemo;
const
Pi = 3.14159265358979;
Gravity = 9.81;
begin
writeln('Pi: ', Pi:0:11);
writeln('Gravity: ', Gravity:0:2);
end. Fortran's
real, parameter :: and Pascal's const block both declare true compile-time constants that the compiler rejects any attempt to reassign — a direct, one-to-one mapping. Pascal collects all constants under one const keyword the same way var collects variables.Declaring Several Variables at Once
program multiple_demo
implicit none
integer :: first_number, second_number, third_number
first_number = 1
second_number = 2
third_number = 3
print *, first_number, second_number, third_number
end program multiple_demo program MultipleDemo;
var
firstNumber, secondNumber, thirdNumber: Integer;
begin
firstNumber := 1;
secondNumber := 2;
thirdNumber := 3;
writeln(firstNumber, ' ', secondNumber, ' ', thirdNumber);
end. Both languages let a comma-separated list of names share one type declaration: Fortran's
integer :: a, b, c and Pascal's a, b, c: Integer read almost identically, just with the type on opposite sides of the name list.Arithmetic
Integer Division & MOD
program division_demo
implicit none
integer :: numerator, denominator, quotient, remainder_value
numerator = 17
denominator = 5
quotient = numerator / denominator
remainder_value = mod(numerator, denominator)
print *, "Quotient:", quotient
print *, "Remainder:", remainder_value
end program division_demo program DivisionDemo;
var
numerator, denominator, quotient, remainderValue: Integer;
begin
numerator := 17;
denominator := 5;
quotient := numerator div denominator;
remainderValue := numerator mod denominator;
writeln('Quotient: ', quotient);
writeln('Remainder: ', remainderValue);
end. Fortran overloads
/ for both integer and real division, inferring integer division from operand types. Pascal keeps them syntactically distinct: div is always integer division (a dedicated keyword, not the / symbol, which is reserved for real division and would return a Double even given two integers), and mod is the remainder operator in both languages with the same spelling.⚠ ** Operator vs. Power Function
program exponent_demo
implicit none
real :: result_value
result_value = 2.0 ** 10
print *, "2^10 =", result_value
end program exponent_demo program ExponentDemo;
uses Math;
var
resultValue: Double;
begin
resultValue := Power(2.0, 10);
writeln('2^10 = ', resultValue:0:1);
end. Fortran has a dedicated
** exponentiation operator built into the language. Pascal has no exponentiation operator at all — raising a number to a power always goes through the Power function from the Math unit. This is a genuine syntax trap for a Fortran programmer: writing 2 ** 10 in Pascal is simply a compile error, not an unexpected result.Math Intrinsics vs. the Math Unit
program math_intrinsics_demo
implicit none
print *, "sqrt(144):", sqrt(144.0)
print *, "abs(-42):", abs(-42)
print *, "sin(0.0):", sin(0.0)
end program math_intrinsics_demo program MathUnitDemo;
uses Math;
begin
writeln('sqrt(144): ', Sqrt(144.0):0:1);
writeln('abs(-42): ', Abs(-42));
writeln('sin(0.0): ', Sin(0.0):0:1);
end. sqrt, abs, and the trigonometric functions are intrinsic in Fortran — always available with no import. Pascal requires uses Math; for Sqrt, Sin, Cos, and friends, though Abs, Round, and Trunc live in the always-available System unit. A Fortran programmer's reflex of never needing an import for basic math needs adjusting for Pascal.MIN/MAX Intrinsics vs. Math Unit Functions
program min_max_demo
implicit none
integer :: score_a, score_b
score_a = 88
score_b = 95
print *, "Highest:", max(score_a, score_b)
print *, "Lowest:", min(score_a, score_b)
end program min_max_demo program MinMaxDemo;
uses Math;
var
scoreA, scoreB: Integer;
begin
scoreA := 88;
scoreB := 95;
writeln('Highest: ', Max(scoreA, scoreB));
writeln('Lowest: ', Min(scoreA, scoreB));
end. Fortran's
max()/min() intrinsics are always available and accept two or more arguments directly. Pascal's Max/Min live in the Math unit and only accept exactly two arguments — comparing three or more values means nesting calls, Max(a, Max(b, c)), rather than a single flat call.NINT/INT vs. Round/Trunc
program rounding_demo
implicit none
real :: value
value = 3.7
print *, "nint:", nint(value)
print *, "int (truncate):", int(value)
print *, "floor:", floor(value)
print *, "ceiling:", ceiling(value)
end program rounding_demo program RoundingDemo;
uses Math;
var
value: Double;
begin
value := 3.7;
writeln('Round: ', Round(value));
writeln('Trunc (truncate): ', Trunc(value));
writeln('Floor: ', Floor(value));
writeln('Ceil: ', Ceil(value));
end. Fortran's
nint() (nearest integer), int() (truncate toward zero), floor(), and ceiling() map directly onto Pascal's Round, Trunc, Floor, and Ceil — same four operations, same semantics, just different names for the first two.Strings
String Concatenation (//) vs. (+)
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 program ConcatDemo;
var
firstName, lastName, fullName: string;
begin
firstName := 'Alice';
lastName := 'Smith';
fullName := firstName + ' ' + lastName;
writeln(fullName);
end. Fortran concatenates with the dedicated
// operator. Pascal reuses the ordinary + arithmetic operator for string concatenation — the compiler decides its meaning from the operand types. Because Pascal strings are dynamically sized, no trim()-equivalent padding cleanup is needed the way it is with Fortran's fixed-width fields.LEN_TRIM vs. Length
program length_demo
implicit none
character(len=20) :: greeting
greeting = "Hello"
print *, "Trimmed length:", len_trim(greeting)
end program length_demo program LengthDemo;
var
greeting: string;
begin
greeting := 'Hello';
writeln('Length: ', Length(greeting));
end. Fortran needs two different length functions:
len() for the declared field width and len_trim() for the length ignoring trailing padding. Pascal needs only one — Length — because a dynamic string has no padding to ignore in the first place; its length is always exactly the number of characters it currently holds.Substring Slicing vs. Copy
program substring_demo
implicit none
character(len=11) :: phrase
phrase = "Hello World"
print *, phrase(1:5)
print *, phrase(7:11)
end program substring_demo program SubstringDemo;
var
phrase: string;
begin
phrase := 'Hello World';
writeln(Copy(phrase, 1, 5));
writeln(Copy(phrase, 7, 5));
end. Fortran's substring syntax
phrase(1:5) takes a start and an end position, both inclusive, directly in the variable's own indexing brackets. Pascal has no bracket-based slicing at all — extracting a substring always goes through the Copy(string, startPosition, count) function, whose third argument is a character count, not an end position.INDEX Intrinsic vs. Pos Function
program search_demo
implicit none
character(len=30) :: sentence
integer :: position
sentence = "the quick brown fox"
position = index(sentence, "brown")
print *, "Found at position:", position
end program search_demo program SearchDemo;
var
sentence: string;
position: Integer;
begin
sentence := 'the quick brown fox';
position := Pos('brown', sentence);
writeln('Found at position: ', position);
end. Fortran's
index(haystack, needle) and Pascal's Pos(needle, haystack) both return the 1-based starting position of a substring (0 if not found) — functionally identical, but note the argument order is reversed: Fortran takes the string being searched first, Pascal takes the substring being searched for first.Case Conversion
program case_convert_demo
implicit none
character(len=10) :: name
integer :: i, code
name = "alice"
do i = 1, len(name)
code = iachar(name(i:i))
if (code >= iachar('a') .and. code <= iachar('z')) then
name(i:i) = achar(code - 32)
end if
end do
print *, trim(name)
end program case_convert_demo program CaseConvertDemo;
uses SysUtils;
var
name: string;
begin
name := 'alice';
writeln(UpperCase(name));
end. Fortran has no built-in case-conversion intrinsic — converting case means writing a loop over character codes by hand with
iachar()/achar(). Pascal's SysUtils unit provides UpperCase and LowerCase directly, a case where Pascal's standard library is considerably more convenient than Fortran's for a common text operation.Arrays
Array Declaration with Explicit Bounds
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 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. Both languages let the programmer choose arbitrary array bounds rather than being locked to 0-based indexing: Fortran's
scores(1:5) and Pascal's array[1..5] both declare a 5-element array indexed 1 through 5. Either language could just as easily declare (0:4) or [0..4] — the bounds are a choice, not a language default, in both cases.⚠ Whole-Array Arithmetic vs. Element-by-Element Loops
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 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. This is the headline structural difference between these two otherwise-similar languages. 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, like C, 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 vs. Manual Accumulation
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 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. 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.Two-Dimensional Arrays
program two_d_demo
implicit none
integer :: matrix(3, 3)
integer :: row, col
do row = 1, 3
do col = 1, 3
matrix(row, col) = 0
end do
end do
matrix(2, 2) = 5
print *, matrix(2, 2)
end program two_d_demo program TwoDDemo;
var
matrix: array[1..3, 1..3] of Integer;
row, col: Integer;
begin
for row := 1 to 3 do
for col := 1 to 3 do
matrix[row, col] := 0;
matrix[2, 2] := 5;
writeln(matrix[2, 2]);
end. Fortran and Pascal both index a 2D array with comma-separated subscripts in one set of parentheses/brackets —
matrix(row, col) versus matrix[row, col] — an almost identical shape. Pascal's declaration array[1..3, 1..3] of Integer similarly parallels Fortran's integer :: matrix(3, 3), just with the dimension bounds spelled out explicitly rather than inferred as starting at 1.ALLOCATABLE Arrays vs. Dynamic Arrays
program allocatable_demo
implicit none
integer, allocatable :: items(:)
integer :: item_count, i
item_count = 3
allocate(items(item_count))
items = [100, 200, 300]
do i = 1, item_count
print *, items(i)
end do
deallocate(items)
end program allocatable_demo program DynamicArrayDemo;
var
items: array of Integer;
i: Integer;
begin
SetLength(items, 3);
items[0] := 100;
items[1] := 200;
items[2] := 300;
for i := 0 to High(items) do
writeln(items[i]);
end. Fortran's
allocatable arrays are sized at runtime with allocate()/deallocate() and keep whatever bounds you give them. Pascal's dynamic arrays (array of Integer, no bounds in the declaration) are sized with SetLength and are always 0-indexed regardless of how a same-named static array might have been indexed elsewhere — a subtle trap, since Pascal static arrays commonly start at 1 but dynamic arrays never do.Control Flow
IF / ELSE IF vs. IF / ELSE
program if_demo
implicit none
integer :: score
score = 85
if (score >= 90) then
print *, "Grade: A"
else if (score >= 80) then
print *, "Grade: B"
else
print *, "Grade: C or below"
end if
end program if_demo program IfDemo;
var
score: Integer;
begin
score := 85;
if score >= 90 then
writeln('Grade: A')
else if score >= 80 then
writeln('Grade: B')
else
writeln('Grade: C or below');
end. Both languages support a flat multi-branch chain, but Pascal has no dedicated
else if keyword — else if is simply an else clause whose body happens to be another if statement, which reads identically to a real elseif because Pascal statements need no begin/end wrapper when there is only one statement in a branch. Note also that Pascal never places a semicolon before an else — a semicolon there would terminate the if statement early and leave a dangling else with no matching if.SELECT CASE vs. CASE OF
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 (4, 5)
print *, "Thursday or Friday"
case default
print *, "Weekend"
end select
end program select_case_demo program CaseOfDemo;
var
dayNumber: Integer;
begin
dayNumber := 3;
case dayNumber of
1: writeln('Monday');
2: writeln('Tuesday');
3: writeln('Wednesday');
4, 5: writeln('Thursday or Friday');
else writeln('Weekend');
end;
end. Fortran's
select case/case/case default and Pascal's case...of/numbered branches/else are nearly interchangeable — both allow comma-separated value lists on one branch (case (4, 5) versus 4, 5:), and neither falls through to the next branch the way C's switch does.CASE Ranges
program case_ranges_demo
implicit none
integer :: score
score = 85
select case (score)
case (90:100)
print *, "A"
case (80:89)
print *, "B"
case default
print *, "C or below"
end select
end program case_ranges_demo program CaseRangesDemo;
var
score: Integer;
begin
score := 85;
case score of
90..100: writeln('A');
80..89: writeln('B');
else writeln('C or below');
end;
end. Fortran writes a case range as
lower:upper inside the parentheses. Pascal writes the same range as lower..upper — the same double-dot syntax Pascal already uses for array bounds (array[1..5]), so the two uses of .. reinforce each other once learned..AND./.OR. vs. and/or
program logical_ops_demo
implicit none
logical :: is_weekday, is_holiday
is_weekday = .true.
is_holiday = .false.
if (is_weekday .and. .not. is_holiday) then
print *, "Office is open"
end if
end program logical_ops_demo program LogicalOpsDemo;
var
isWeekday, isHoliday: Boolean;
begin
isWeekday := True;
isHoliday := False;
if isWeekday and not isHoliday then
writeln('Office is open');
end. Fortran surrounds its logical operators with dots (
.and., .or., .not.); Pascal spells the same operators as bare lowercase words (and, or, not) with no punctuation at all — otherwise the logic reads almost identically between the two languages.Loops
DO Loop vs. FOR/TO
program do_loop_demo
implicit none
integer :: i
do i = 1, 5
print *, "Iteration:", i
end do
end program do_loop_demo program ForToDemo;
var
i: Integer;
begin
for i := 1 to 5 do
writeln('Iteration: ', i);
end. Fortran's
do i = 1, 5 and Pascal's for i := 1 to 5 do are functionally identical: both count an explicit loop variable upward through an inclusive range with a step of 1, with the variable available and readable inside the loop body in both languages.Negative-Step DO vs. FOR/DOWNTO
program countdown_demo
implicit none
integer :: i
do i = 5, 1, -1
print *, i
end do
end program countdown_demo program DowntoDemo;
var
i: Integer;
begin
for i := 5 downto 1 do
writeln(i);
end. Fortran counts downward by giving
do a negative step: do i = 5, 1, -1. Pascal has a dedicated keyword for the same purpose — for i := 5 downto 1 do — with no explicit step argument at all, since downto always steps by exactly 1 in the negative direction.DO WHILE vs. WHILE/DO
program do_while_demo
implicit none
integer :: balance
balance = 1000
do while (balance > 0)
balance = balance - 300
print *, "Balance:", balance
end do
end program do_while_demo program WhileDemo;
var
balance: Integer;
begin
balance := 1000;
while balance > 0 do begin
balance := balance - 300;
writeln('Balance: ', balance);
end;
end. Fortran's
do while (condition) and Pascal's while condition do both test the condition before each iteration and may run zero times — identical semantics, with Pascal needing a begin...end wrapper only because its loop body here has more than one statement.REPEAT/UNTIL Has No Fortran Equivalent
program simulated_repeat_demo
implicit none
integer :: counter
logical :: keep_going
counter = 1
keep_going = .true.
do while (keep_going)
print *, counter
counter = counter + 1
if (counter > 5) keep_going = .false.
end do
end program simulated_repeat_demo program RepeatUntilDemo;
var
counter: Integer;
begin
counter := 1;
repeat
writeln(counter);
counter := counter + 1;
until counter > 5;
end. Pascal's
repeat...until condition tests its condition after the loop body, guaranteeing at least one execution, and continues until the condition becomes true (the opposite sense of while). Fortran has no direct equivalent — a Fortran programmer must simulate a post-tested loop with a do while and a manually managed flag, as shown here, or an infinite do with an if/exit at the bottom.EXIT/CYCLE vs. Break/Continue
program exit_cycle_demo
implicit none
integer :: i
do i = 1, 10
if (mod(i, 2) == 0) cycle
if (i > 7) exit
print *, i
end do
end program exit_cycle_demo program BreakContinueDemo;
var
i: Integer;
begin
for i := 1 to 10 do begin
if i mod 2 = 0 then
continue;
if i > 7 then
break;
writeln(i);
end;
end. Fortran's
cycle (skip to next iteration) and exit (break out of the loop) map directly onto Pascal's continue and break — nearly identical vocabulary between the two languages, unlike COBOL, which has neither.Procedures & Functions
SUBROUTINE vs. Procedure
program subroutine_demo
implicit none
call greet("Alice")
call greet("Bob")
contains
subroutine greet(person_name)
character(len=*), intent(in) :: person_name
print *, "Hello, " // trim(person_name) // "!"
end subroutine greet
end program subroutine_demo program ProcedureDemo;
procedure Greet(const personName: string);
begin
writeln('Hello, ', personName, '!');
end;
begin
Greet('Alice');
Greet('Bob');
end. A Fortran
subroutine is called with the call keyword; a Pascal procedure is called by name alone, with no equivalent keyword required. Both describe a callable unit that performs an action and returns no value — the direct structural counterpart of each other, unlike COBOL, which has no comparable parameterized unit at all outside a full subprogram.INTENT(IN) vs. Const Parameter
program intent_in_demo
implicit none
call display_info("Alice", 95)
contains
subroutine display_info(person_name, score)
character(len=*), intent(in) :: person_name
integer, intent(in) :: score
print *, trim(person_name), ": ", score
end subroutine display_info
end program intent_in_demo program ConstParamDemo;
procedure DisplayInfo(const personName: string; const score: Integer);
begin
writeln(personName, ': ', score);
end;
begin
DisplayInfo('Alice', 95);
end. Fortran's
intent(in) and Pascal's const parameter modifier serve the identical purpose: both tell the compiler the parameter is read-only, and both cause a compile-time error if the procedure tries to assign to it. This is one of the closest one-to-one mappings between the two languages' feature sets.INTENT(INOUT) vs. Var Parameter
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 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. Fortran's
intent(inout) and Pascal's var parameter modifier both pass the caller's actual variable by reference, letting the procedure both read and modify it in place — another near-exact mapping. Pascal additionally has a write-only out parameter mode matching Fortran's intent(out), completing the correspondence across all three of Fortran's intent modes.FUNCTION vs. Function — Both Usable in Expressions
program function_demo
implicit none
print *, "Fahrenheit:", to_fahrenheit(100.0)
contains
function to_fahrenheit(celsius) result(fahrenheit)
real, intent(in) :: celsius
real :: fahrenheit
fahrenheit = celsius * 9.0 / 5.0 + 32.0
end function to_fahrenheit
end program function_demo program FunctionDemo;
function ToFahrenheit(celsius: Double): Double;
begin
ToFahrenheit := celsius * 9.0 / 5.0 + 32.0;
end;
begin
writeln('Fahrenheit: ', ToFahrenheit(100.0):0:1);
end. Unlike COBOL, Pascal has real user-defined functions with return values that can be used directly inside expressions, exactly like Fortran. The return value is set by assigning to the function's own name (
ToFahrenheit := ...) — Free Pascal also accepts the more modern Result := ... — rather than Fortran's optional result() clause, but the calling convention is identical: ToFahrenheit(100.0) can be nested inside any expression exactly as to_fahrenheit(100.0) can in Fortran.Recursive Functions
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 program RecursiveDemo;
function Factorial(n: Integer): Int64;
begin
if n <= 1 then
Factorial := 1
else
Factorial := n * Factorial(n - 1);
end;
begin
writeln('5! = ', Factorial(5));
end. Fortran requires the explicit
recursive keyword before a function or subroutine can call itself — an important safety default, since ordinary Fortran subprograms are not guaranteed reentrant. Pascal has no such keyword: every Pascal function and procedure may call itself freely with no special declaration at all.RETURN vs. Exit
program early_return_demo
implicit none
print *, "Absolute value of -5:", absolute_value(-5)
print *, "Absolute value of 5:", absolute_value(5)
contains
function absolute_value(number) result(magnitude)
integer, intent(in) :: number
integer :: magnitude
if (number >= 0) then
magnitude = number
return
end if
magnitude = -number
end function absolute_value
end program early_return_demo program EarlyReturnDemo;
function AbsoluteValue(number: Integer): Integer;
begin
if number >= 0 then begin
AbsoluteValue := number;
Exit;
end;
AbsoluteValue := -number;
end;
begin
writeln('Absolute value of -5: ', AbsoluteValue(-5));
writeln('Absolute value of 5: ', AbsoluteValue(5));
end. Fortran's
return statement exits a subprogram immediately, before reaching its natural end. Pascal's equivalent is the built-in Exit procedure — same purpose, different name, and both languages require the return value to already have been assigned before the early exit statement runs.Records
Derived Type vs. Record
program derived_type_demo
implicit none
type :: person
character(len=20) :: name
integer :: age
end type person
type(person) :: employee
employee = person("Alice", 30)
print *, trim(employee%name)
print *, employee%age
end program derived_type_demo program RecordDemo;
type
TPerson = record
name: string;
age: Integer;
end;
var
employee: TPerson;
begin
employee.name := 'Alice';
employee.age := 30;
writeln(employee.name);
writeln(employee.age);
end. A Fortran
type and a Pascal record are nearly identical concepts: both group named fields of possibly different types into one value, both are declared once and instantiated many times, and both use a member-access operator to reach a field — % in Fortran, . in Pascal. Pascal record type names are conventionally prefixed with T.Array of Derived Types vs. Array of Records
program array_of_types_demo
implicit none
type :: point
real :: x
real :: y
end type point
type(point) :: points(2)
points(1) = point(1.0, 2.0)
points(2) = point(3.0, 4.0)
print *, points(1)%x, points(1)%y
print *, points(2)%x, points(2)%y
end program array_of_types_demo program ArrayOfRecordsDemo;
type
TPoint = record
x, y: Double;
end;
var
points: array[1..2] of TPoint;
begin
points[1].x := 1.0; points[1].y := 2.0;
points[2].x := 3.0; points[2].y := 4.0;
writeln(points[1].x:0:1, ' ', points[1].y:0:1);
writeln(points[2].x:0:1, ' ', points[2].y:0:1);
end. Both languages combine arrays and records the same way: an array whose element type is a record/derived type, accessed by combining the subscript and the member operator —
points(1)%x versus points[1].x. The shape of the two lines is nearly a character-for-character translation of each other.Nested Records
program nested_type_demo
implicit none
type :: address
character(len=20) :: city
end type address
type :: employee_type
character(len=20) :: name
type(address) :: home_address
end type employee_type
type(employee_type) :: employee
employee%name = "Alice"
employee%home_address%city = "Springfield"
print *, trim(employee%name)
print *, trim(employee%home_address%city)
end program nested_type_demo program NestedRecordDemo;
type
TAddress = record
city: string;
end;
TEmployee = record
name: string;
homeAddress: TAddress;
end;
var
employee: TEmployee;
begin
employee.name := 'Alice';
employee.homeAddress.city := 'Springfield';
writeln(employee.name);
writeln(employee.homeAddress.city);
end. A record/derived type can contain another record/derived type as a field in both languages, and the member-access chain reads the same way in both:
employee%home_address%city versus employee.homeAddress.city. Pascal declares both nested types in a single type block separated by semicolons; Fortran gives each its own separate type ... end type block.Units & Modules
MODULE/USE vs. Unit/Uses
program module_use_demo
use iso_fortran_env, only: real64
implicit none
real(kind=real64) :: value
value = 3.14159265358979_real64
print *, value
end program module_use_demo program UnitUsesDemo;
uses
Math, { trigonometry, Power, floor, ceil }
SysUtils; { Format, UpperCase, string utilities }
var
value: Double;
begin
value := Pi;
writeln(value:0:14);
end. Fortran's
use module_name, only: names and Pascal's uses UnitName; both import a library of related declarations — the mechanism a Rubyist would compare to require. Fortran can selectively import only specific names with only:; a plain Pascal uses clause always imports everything a unit exports, with no selective-import syntax.Internal Files vs. Format Function
program internal_io_demo
implicit none
character(len=20) :: label_text
integer :: year
year = 2026
write(label_text, '("Report_", i4, ".txt")') year
print *, trim(label_text)
end program internal_io_demo program FormatDemo;
uses SysUtils;
var
labelText: string;
year: Integer;
begin
year := 2026;
labelText := Format('Report_%d.txt', [year]);
writeln(labelText);
end. Fortran builds a formatted string by writing to a character variable used as an "internal file" — an
sprintf-equivalent reached through the ordinary write statement. Pascal reaches the same result through SysUtils's Format function, whose %d-style placeholders and array-of-arguments syntax will look immediately familiar to anyone who has used C's printf.Output & Formatting
PRINT * vs. Writeln
program print_demo
implicit none
integer :: count
real :: price
count = 42
price = 9.99
print *, "Count:", count
print *, "Price:", price
end program print_demo program WritelnDemo;
var
count: Integer;
price: Double;
begin
count := 42;
price := 9.99;
writeln('Count: ', count);
writeln('Price: ', price:0:2);
end. print *, ... in Fortran and writeln(...) in Pascal both write a comma-separated list of values to standard output followed by a newline. Pascal additionally offers write (no trailing newline) for building up a line across several calls — Fortran has no equivalent no-newline print statement in its simple print *, form.FORMAT Descriptors vs. Field-Width Syntax
program format_demo
implicit none
real :: amount
amount = 1234.5
write(*, '(a, f10.2)') "Amount: ", amount
end program format_demo program FieldWidthDemo;
var
amount: Double;
begin
amount := 1234.5;
writeln('Amount: ', amount:10:2);
end. Fortran controls output layout with a separate FORMAT descriptor string passed to
write, such as f10.2 (fixed-point, 10 characters wide, 2 decimal places). Pascal folds the same information directly into the writeln argument list using colon syntax: amount:10:2 means the same 10-wide, 2-decimal formatting, with no separate format string needed.Building a Line Without a Trailing Newline
program no_newline_demo
implicit none
integer :: i
do i = 1, 5
write(*, '(i0, a)', advance='no') i, " "
end do
print *, ""
end program no_newline_demo program NoNewlineDemo;
var
i: Integer;
begin
for i := 1 to 5 do
write(i, ' ');
writeln;
end. Fortran suppresses the trailing newline with
advance='no' on a write statement — an unusually verbose piece of syntax for such a common need. Pascal's plain write (as opposed to writeln) never emits a newline at all, so building up a line piece by piece across a loop is simpler in Pascal: call write repeatedly, then call bare writeln once to finish the line.⚠ Gotchas for Fortran Programmers
⚠ The Semicolon Is a Statement Separator
program semicolon_demo
implicit none
integer :: value
value = 5
print *, "Positive"
end program semicolon_demo program SemicolonDemo;
var
value: Integer;
begin
value := 5;
writeln('Positive')
end. Fortran statements are terminated by a newline, with nothing equivalent to a required trailing punctuation mark. Pascal semicolons are technically statement separators, not terminators — the last statement before an
end does not strictly need one, as shown here. A stray extra semicolon (e.g. right after then) silently creates an empty statement rather than a syntax error, which can make an intended if body execute unconditionally — a subtle bug a Fortran programmer's newline-based intuition will not catch by habit.⚠ Integer Overflow Wraps Silently in Both Languages
program overflow_demo
implicit none
integer(kind=1) :: tiny_value
tiny_value = 127
tiny_value = tiny_value + 1
print *, tiny_value
end program overflow_demo program OverflowDemo;
var
tinyValue: ShortInt; { -128..127 }
begin
tinyValue := 127;
tinyValue := tinyValue + 1;
writeln(tinyValue);
end. Both languages agree here, unlike Ruby or Python: a fixed-width integer that overflows its range wraps silently to a nonsensical value (127 + 1 becomes -128 in an 8-bit signed field) with no error, no warning, and no exception raised in either Fortran or Pascal. Neither language has an automatically-growing arbitrary-precision integer type as a fallback.
⚠ Dynamic Arrays Are Always 0-Indexed
program static_one_based_demo
implicit none
integer :: fixed_array(1:5)
fixed_array(1) = 100
print *, fixed_array(1)
end program static_one_based_demo program DynamicZeroIndexedDemo;
var
fixedArray: array[1..5] of Integer;
dynamicArray: array of Integer;
begin
fixedArray[1] := 100;
writeln(fixedArray[1]);
SetLength(dynamicArray, 5);
dynamicArray[0] := 100; { dynamic arrays always start at 0 }
writeln(dynamicArray[0]);
end. Fortran arrays default to 1-based indexing but can be declared with any custom bounds, including 0-based, and that choice is consistent everywhere the array is used. Pascal static arrays follow the same "choose your own bounds" rule — but Pascal dynamic arrays (
array of Integer, sized with SetLength) are always 0-indexed with no way to change it. Mixing static and dynamic arrays in the same Pascal program means living with two different indexing conventions side by side.⚠ No Whole-Array Comparisons or Boolean Masks
program where_demo
implicit none
integer :: numbers(5)
logical :: mask(5)
numbers = [1, -2, 3, -4, 5]
mask = numbers > 0
where (mask)
numbers = numbers * 10
end where
print *, numbers
end program where_demo program NoWhereDemo;
var
numbers: array[1..5] of Integer;
i: Integer;
begin
numbers[1] := 1; numbers[2] := -2; numbers[3] := 3;
numbers[4] := -4; numbers[5] := 5;
for i := 1 to 5 do
if numbers[i] > 0 then
numbers[i] := numbers[i] * 10;
for i := 1 to 5 do
write(numbers[i], ' ');
writeln;
end. Fortran's
where construct applies an operation only to the array elements that satisfy a condition — a whole-array conditional built directly into the language, with the condition itself expressed as a whole-array comparison (numbers > 0 produces a whole array of booleans). Pascal has neither piece: no whole-array comparison operators and no masked-assignment construct, so the equivalent logic always becomes an explicit for loop with an if inside it — one more instance of the whole-array-versus-element-by-element gap that runs through every array-related concept on this page.