This lecture introduces the main programming paradigms, focusing on imperative programming and its limitations due to the Von Neumann bottleneck. It explains the need for theories without mutation to define high-level abstractions and the principles of functional programming. The history of functional programming languages is explored, highlighting their origins and advantages in reducing errors, improving modularity, and increasing developer productivity. The lecture also addresses the relevance of functional programming in handling concurrency and parallelism in modern computing environments, emphasizing the importance of avoiding mutable state for deterministic processing.