Hacker News new | ask | show | jobs
by ryandv 654 days ago
The classic dichotomy drawn between functional programming (FP) and object-oriented programming is the "Expression Problem" [0]; in the former approach you optimize for extensibility of the number of operations in your model, at the cost of reduced developer ergonomics when attempting to extend the number of types you can operate upon. In the latter, object-oriented approach, you have the inverse tradeoff.

In FP the fundamental unit of composition is the function; your solution is expressed as a composition of functions, which are treated as first-class objects (first-class meaning, functions can be manipulated via higher-order functions, or "functions of functions"), a feature not always seen in object-oriented or multi-paradigm languages. Polymorphism is most frequently achieved through parametric polymorphism, or "generics," and ad-hoc polymorphism, or "trait bounds"/"typeclass constraints".

In OOP the fundamental unit of composition is the object; your solution is expressed as a composition of objects, whether through actual composition/aggregation (objects containing and possibly delegating to other objects [1]), or subtype polymorphism, also known as "inheritance." Parametric and ad-hoc polymorphism can often feature in OOP languages as well, but subtype polymorphism is a distinguishing characteristic of OOP.

Functions, particularly pure functions without side effects in the "real world" such as I/O or hardware access, are akin to equations in which an expression can be replaced by its value - the "left-hand side" equals the "right-hand side." Mutable state often does not enter into the picture, especially when programming in this "pure" (side-effect free) style. This makes functional programs easier to reason about equationally, as one can determine the value of an expression simply by inspection of whatever variables are in the function's scope, without having to keep track of the state of the entire program.

Objects are distinguished by their often stateful nature as they bundle together data/internal state, and operations over that internal state. Often such internal state is hidden or "encapsulated" from the client, and the internal state is only modifiable (if at all) via the object's class' set of public methods/operations. Objects with immutable internal state are more akin to closures from functional programming - that is, functions with access to a "parent lexical scope" or "environment."

Between the two extremes exists an entire spectrum of mixed-paradigm languages that incorporate features of both approaches to structuring and modelling a software solution.

[0] https://wiki.c2.com/?ExpressionProblem

[1] https://en.wikipedia.org/wiki/Composition_over_inheritance