2 Language Creators vs 2 Idiots | The Standup
Based on The PrimeTime's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.
Functional programming’s mainstream impact came largely through individual ideas (like lambdas, streams, and type inference) rather than through adopting “functional programming” as a unified identity.
Briefing
Functional programming didn’t “take off” in the way many early advocates expected—not because the ideas failed, but because the label became slippery and the mainstream world absorbed the useful parts without adopting the whole package. Jose Valim, creator of Elixir, frames functional programming as a bundle of ideas that later spread into mainstream languages (streams, lambdas, type inference), while other aspects never became universal. He also argues that newer languages often avoid the “functional vs object-oriented” branding entirely, preferring more specific categories like systems programming—suggesting that Elixir may not need to market itself primarily through the functional label in 2025.
Gingerbill, creator of Odin, pushes the critique further by attacking the term itself. “Functional programming” can mean everything from pure, side-effect-free code to broader styles like treating functions as first-class values and using closures. Under that joke definition, functional programming “never caught on” because pressing a button is a side effect. More seriously, Gingerbill says many people encounter functional languages as research projects—especially when they come with heavy complexity—making them hard to read and unattractive for everyday mutation-heavy software. Still, he points to concrete functional-adjacent features that show up everywhere: closures and immutability.
The conversation then pivots to why Erlang-style concurrency feels like a better fit than many “functional concurrency” attempts. Gingerbill calls Erlang his favorite language and describes its concurrency model as CSP-like: lightweight processes communicate by sending messages, and immutability by default helps fault tolerance by preventing shared-state corruption. He contrasts this with approaches that try to manage concurrency differently, which he says he doesn’t like as much.
From there, the debate expands into how language design trade-offs shape adoption. Jose compares immutability’s benefits—clarity and easier reasoning under concurrency—to the “banana/gorilla” problem of object-oriented code that can reach far into shared state. He also notes that Rust can deliver some immutability benefits via its type system even if it isn’t marketed as functional.
Gingerbill’s Rust rant is less about theory and more about ergonomics and ceremony. He characterizes Rust as “ML in disguise pretending to be a C++,” emphasizing ownership, lifetimes, pattern matching, and macro-heavy syntax. His complaint is that the language’s semantic machinery forces developers into constant friction—especially lifetime management—rather than letting them express intent directly. He also argues that macros often signal missing language features, and that debugging meta-programming is inherently harder.
Macros become a flashpoint with Jose defending Elixir’s approach. He says Elixir keeps macros limited in scope: Phoenix’s router is macro-heavy at the entry point, but controllers, templates, and LiveViews are regular code. Jose also defends macros as part of a “small extensible language” design philosophy—minimizing “cheating” by keeping the language’s core constructs under the language author’s control.
Finally, the group lands on tooling and ecosystem mechanics: LSPs are expensive to implement because they require deep compiler integration, and package managers can accelerate “dependency hell” by automating trust without verification. Jose and Gingerbill both argue that language ecosystems should encourage fewer, higher-quality dependencies and that developers should read dependency source code before adopting it.
Across the discussion, the central theme is practical: adoption depends less on labels and more on how language features interact with real-world debugging, concurrency, ergonomics, and dependency management.
Cornell Notes
Functional programming’s failure to “take off” is traced to two problems: the label is vague, and the mainstream world absorbed useful functional ideas without adopting functional programming as a unified identity. Jose Valim argues that many functional concepts—like lambdas, streams, and type inference—became mainstream, while newer languages increasingly avoid the functional/object-oriented branding. Gingerbill adds that many functional languages feel like research projects, and that “functional” can mean everything from purity to first-class functions and closures, making the term hard to market or apply consistently. The discussion also links design choices to adoption: Erlang’s immutable, message-passing concurrency supports fault tolerance, while Rust’s ownership/lifetimes and macro ecosystem create friction for some developers. Tooling and ecosystem design—debuggability, LSP integration cost, and dependency automation—shape whether languages thrive in practice.
Why does “functional programming” fail as a marketing label, even when functional ideas succeed?
What does Erlang’s concurrency model have to do with functional programming’s appeal?
How do immutability and clarity connect in Jose Valim’s view of language design?
Why does Gingerbill dislike Rust, beyond personal preference?
What’s the “no cheating rule” in Elixir’s macro philosophy?
Why do the guests criticize package managers and LSPs as ecosystem accelerants of pain?
Review Questions
- What specific reasons do Jose Valim and Gingerbill give for why the term “functional programming” doesn’t map cleanly to how people actually build software?
- How does Erlang’s message-passing plus immutability reduce fault-tolerance risks compared with shared mutable state?
- What trade-offs do the guests associate with macros and with package managers, and how do those trade-offs affect debugging and long-term maintenance?
Key Points
- 1
Functional programming’s mainstream impact came largely through individual ideas (like lambdas, streams, and type inference) rather than through adopting “functional programming” as a unified identity.
- 2
The term “functional programming” is technically ambiguous, ranging from purity/no side effects to broader styles like first-class functions and closures.
- 3
Erlang’s CSP-like concurrency and immutability by default are presented as practical tools for fault tolerance by avoiding shared-state corruption.
- 4
Rust is criticized for ergonomic friction: ownership and lifetime semantics plus macro-heavy syntax can shift developer effort from intent to type-level ceremony.
- 5
Elixir’s macro system is defended as part of a “small extensible language” design, with macros concentrated at key entry points (e.g., Phoenix routing) rather than pervasively in application logic.
- 6
Language tooling and ecosystem mechanics matter: LSPs require deep compiler integration, and package managers can accelerate dependency hell by automating trust and dependency graphs.
- 7
Adoption depends on debuggability and maintainability—especially for meta-programming—so language design must account for how developers inspect and troubleshoot code.