Programming Language Theory

Language Extensibility

Kotlin extension functions and Swift protocols are not just syntactic sugar. They are a fundamentally new way to extend other people's code without inheritance. LSP changed how languages are built. IDE support no longer requires a dedicated IDE engineering team.

  • **rust-analyzer**: an LSP server for Rust. One server powers VS Code, IntelliJ, Neovim, Emacs, Helix. 5M+ users.
  • **Arrow (Kotlin FP library)**: uses extension functions to add functional operators to standard types. monoid(), traverse() directly on List<T>.
  • **TypeScript language server**: used in VS Code, plus Vim, Emacs, Sublime. Microsoft open-sourced LSP, and competing editors now run their server.

Operator Overloading

Operator overloading lets you define the behavior of standard operators (+, -, *, ==, <) for user-defined types. It makes code mathematically intuitive for numeric types, vectors, and matrices. Python uses dunder methods (__add__, __mul__).

Abusing overloading produces unreadable code. Python datetime + timedelta is intuitive. C++ Matrix << Vector is not. Rule of thumb: overload only when the operator is semantically obvious for the type.

When is operator overloading justified, and when not?

Protocols and Type Classes

Protocols (Swift, Elixir) and Type Classes (Haskell) let you define an interface without inheritance. Any type can implement a protocol retroactively, including built-ins. More powerful than OOP interfaces.

What is retroactive conformance, and why is it more powerful than OOP inheritance?

Extension Methods

Extension methods (C#, Swift, Kotlin) let you add methods to existing types without inheritance and without changing the original code. A form of retroactive extension without a full protocol system.

How do Kotlin extension functions differ from really adding a method to a class?

Language Server Protocol

LSP (Language Server Protocol) is a standard for communication between an IDE and language-specific servers. Microsoft built it for VS Code in 2016. Now any language with an LSP implementation gets IDE support in 100+ editors.

Adding IDE support for a new language is years of work

With LSP: implementing a language server is enough to support VS Code, Neovim, Emacs, IntelliJ, and Sublime. That is months, not years.

Gleam (a new functional language) shipped with LSP support from its first stable release. That used to be unthinkable for a young language.

What problem does LSP solve?

Summary

  • **Operator overloading**: intuitive for mathematical types. Avoid operators whose meaning is unclear.
  • **Protocols and type classes**: retroactive conformance without inheritance. Any type can become Describable / Show.
  • **Extension methods**: static methods with syntactic sugar. No access to private members. Static dispatch.
  • **LSP**: eliminates the n*m IDE integration problem. One language server supports 100+ editors.

Related topics

Extensibility ties into types and metaprogramming:

  • OOP theory — Protocols versus inheritance: two different approaches to polymorphism.
  • Type-safe API — Phantom types and branded types extend a language via the type system.

Вопросы для размышления

  • Rust traits, Haskell type classes, and Swift protocols solve the same problem in different ways. How do they differ in expressiveness, and when does it matter?
  • LSP changed the economics of building languages. Once, a new language's success hinged on the quality of its IDE plugin. Now it hinges on the quality of its language server. How has this affected the appearance of new languages?
  • Kotlin extension methods are syntactic sugar over static functions. Haskell type classes generate dictionary passing at runtime. Which approach is better and why?

Связанные уроки

  • fl-03-grammars
Language Extensibility

0

1

Sign In