Skip to content

Overview of Programming Languages

Introduction

Programming languages serve as the bridge between humans and computers. From the earliest machine code to modern high-level languages, the evolution of programming languages reflects the ongoing pursuit of abstraction, expressiveness, and productivity. This article provides a comprehensive survey across four dimensions: programming paradigms, type systems, execution models, and memory management.


1. Programming Paradigms

A programming paradigm is the design philosophy and organizational approach of a programming language.

1.1 Imperative Programming

Imperative programming accomplishes computation by executing a sequence of statements that modify program state.

Core concepts:

  • Variables: mutable storage locations
  • Assignment: changing the value of a variable
  • Control flow: sequential execution, branching (if/switch), loops (for/while)
// C language example
int sum = 0;
for (int i = 1; i <= 100; i++) {
    sum += i;
}

Representative languages: C, Pascal, Fortran.

1.2 Object-Oriented Programming (OOP)

OOP centers on objects, encapsulating data and operations together.

Four principles:

Principle Meaning Purpose
Encapsulation Hiding internal implementation Reducing coupling
Inheritance Subclass reuses superclass code Code reuse
Polymorphism Same interface, different implementations Flexible extension
Abstraction Extracting commonalities, ignoring details Simplified modeling
class Animal:
    def speak(self):
        raise NotImplementedError

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

# Polymorphism
for animal in [Dog(), Cat()]:
    print(animal.speak())

Representative languages: Java, C++, Python, C#.

1.3 Functional Programming

Functional programming treats computation as the evaluation of mathematical functions, emphasizing immutability and freedom from side effects.

Core concepts:

  • Pure functions: the same input always produces the same output, with no side effects
  • Immutable data: data cannot be modified once created
  • Higher-order functions: functions can be passed as arguments or returned
  • Recursion: using recursion instead of loops
  • Lazy evaluation: delaying computation until results are needed
-- Haskell example: factorial
factorial :: Integer -> Integer
factorial 0 = 1
factorial n = n * factorial (n - 1)

-- Higher-order function: map
doubleAll = map (*2)
-- doubleAll [1,2,3] = [2,4,6]

Representative languages: Haskell, Erlang, Clojure, Scala.

1.4 Logic Programming

Logic programming accomplishes computation by declaring facts and rules, with an inference engine automatically deriving solutions.

% Prolog example
parent(tom, bob).
parent(tom, liz).
parent(bob, ann).

grandparent(X, Z) :- parent(X, Y), parent(Y, Z).
% ?- grandparent(tom, ann). => true

Representative languages: Prolog, Datalog.

1.5 Paradigm Family Tree

graph TD
    A[Programming Paradigms] --> B[Declarative]
    A --> C[Imperative]

    B --> D[Functional]
    B --> E[Logic]
    B --> F[Dataflow]

    C --> G[Procedural]
    C --> H[Object-Oriented OOP]

    D --> D1[Haskell / Erlang / Clojure]
    E --> E1[Prolog / Datalog]
    G --> G1[C / Pascal / Fortran]
    H --> H1[Java / C++ / Python]

    style A fill:#f9f,stroke:#333
    style B fill:#bbf,stroke:#333
    style C fill:#bfb,stroke:#333

2. Type Systems

A type system is a set of rules in a programming language that constrains the kinds of values and their permissible operations.

2.1 Static Typing vs Dynamic Typing

Dimension Static Typing Dynamic Typing
When types are checked Compile time Runtime
Type declarations Usually required (can be inferred) Not required
Error detection At compile time At runtime
Representative languages Java, C++, Rust, Go Python, JS, Ruby
Advantages Early error detection, performance optimization Flexibility, faster development

2.2 Strong Typing vs Weak Typing

Dimension Strong Typing Weak Typing
Implicit conversion Disallowed or strictly limited Widely permitted
Representative languages Python, Java, Haskell C, JavaScript, PHP
// JavaScript (weak typing) implicit conversion
"5" + 3    // "53" (string concatenation)
"5" - 3    // 2    (numeric operation)
# Python (strong typing) raises an error
"5" + 3    # TypeError

2.3 Type Inference

Modern languages reduce explicit type annotations through type inference:

  • Hindley-Milner type inference: Haskell, ML family
  • Local type inference: Java (var), C++ (auto), Rust, Go
// Rust type inference
let x = 5;           // inferred as i32
let y = 3.14;        // inferred as f64
let v = vec![1,2,3]; // inferred as Vec<i32>

3. Compilation and Interpretation

3.1 Compiled Languages

Source code → Compiler → Machine code → Direct execution

  • Advantages: fast execution, deep optimization possible
  • Disadvantages: compilation takes time, platform-dependent
  • Representatives: C, C++, Rust, Go

3.2 Interpreted Languages

Source code → Interpreter → Line-by-line / statement-by-statement execution

  • Advantages: fast development, cross-platform
  • Disadvantages: slower execution
  • Representatives: Python, Ruby, JavaScript (early versions)

3.3 Bytecode + Virtual Machine

Source code → Compiler → Bytecode → Virtual Machine (VM) → Execution

  • Java → JVM bytecode → JVM
  • Python → .pyc bytecode → CPython VM
  • C# → IL bytecode → CLR

3.4 JIT Compilation

Just-In-Time compilation combines the advantages of compilation and interpretation:

  1. Initially interpret (or execute bytecode)
  2. Identify hot spots
  3. Compile hot code to machine code
  4. Execute machine code directly thereafter

Representatives: JVM HotSpot, V8 (JavaScript), PyPy.


4. Memory Management

4.1 Manual Memory Management

The programmer is responsible for allocating and freeing memory:

int *arr = (int *)malloc(100 * sizeof(int));
// use arr
free(arr);  // must be freed manually

Problems: memory leaks, dangling pointers, double frees.

4.2 Garbage Collection

Automatically reclaims memory that is no longer in use.

Reference Counting:

  • Each object maintains a reference count
  • Reclaimed immediately when the count reaches zero
  • Problem: circular references
  • Used by: Python (combined with mark-and-sweep), Swift (ARC)

Mark and Sweep:

  1. Starting from root objects, mark all reachable objects
  2. Sweep unmarked objects - Used by: Java, Go, JavaScript

Generational GC:

  • Hypothesis: most objects are short-lived (weak generational hypothesis)
  • Young generation: frequently collected (Minor GC)
  • Old generation: occasionally collected (Major GC)
  • Used by: Java (G1, ZGC), Python

4.3 Ownership System

Rust's unique approach:

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;  // ownership of s1 moves to s2
    // println!("{}", s1);  // compile error! s1 is no longer valid
    println!("{}", s2);     // OK
}  // s2 goes out of scope, memory is automatically freed

Core rules:

  1. Each value has exactly one owner
  2. When the owner goes out of scope, the value is dropped
  3. Borrowing (reference) rules ensure safety

5. Paradigm Comparison

Dimension Imperative OOP Functional Logic
Core abstraction Statement sequence Objects Functions Logical relations
State Mutable Mutable (encapsulated) Immutable Declarative
Control flow Explicit Message passing Recursion/composition Inference engine
Concurrency friendliness Low Medium High High
Typical applications Systems programming Enterprise apps Data processing AI reasoning
Learning curve Low Medium High High

6.1 Multi-Paradigm Fusion

Modern languages commonly support multiple paradigms:

  • Python: imperative + OOP + functional
  • Scala: OOP + functional
  • Rust: imperative + functional + ownership
  • Kotlin: OOP + functional + coroutines
  • Type safety: TypeScript, Rust, etc. emphasize type safety
  • Concurrency primitives: Go (goroutines), Rust (async/await), Erlang (actors)
  • Zero-cost abstractions: C++, Rust pursue abstractions without runtime overhead
  • Domain-specific languages (DSLs): SQL, regular expressions, Terraform HCL

References

  • "Programming Language Pragmatics" - Michael L. Scott
  • "Types and Programming Languages" - Benjamin C. Pierce
  • "Structure and Interpretation of Computer Programs" - Abelson & Sussman

评论 #