• 1 Post
  • 24 Comments
Joined 1 year ago
cake
Cake day: June 16th, 2023

help-circle

  • In applied CS, it’s common to talk about pure and impure functions instead of Turing machines.

    Pure functions are, broadly speaking, equivalent to Turing machines. A pure function may only depend on its inputs (like a Turing machine) and has no outputs besides the return value (like the end state of a Turing machine’s tape).

    Impure functions cover algorithms that aren’t Turing machines. For example, you might have a random number generator rand: 1 → N that outputs different natural numbers on every invocation rand() and is hence impure. Output functions are also impure, e.g., a function write: N → 1 that writes a number into a file can’t be a Turing machine, because Turing machines have no concept of files.

    Computer programs that consist entirely of pure functions aren’t very useful, because they can’t interact with the user or reality. The typical approach to solving this is to put the core program logic inside pure functions that interact with impure parts through a limited interface. That way, you can apply CS concepts to the important parts of the program and neatly separate out the impure parts.

    Edit: Changed ∅ to 1 (singleton set) in function definitions. A function can’t return ∅ and a function taking ∅ can’t be called.





  • I would call those language-specific. While they are useful in more than one language, they are also replaced by language features in many languages.

    • Builder pattern can be simplified with kwargs (Python, C#) or argument objects (JS, C++).
    • Factory pattern can be simplified with first-class types (Lisp, Haskell).
    • Visitor pattern is similarly simplified by first-class functions (supported by most languages nowadays).
    • Dependency injection of concept X is generally simplified by first-class X. I think the least widely supported is dependency injection of effects (Koka).

  • Design patterns are typically just workarounds for the limitations of the chosen programming language. What you might consider a pattern in C might just be a simple language feature in C++, and the patterns in C++ (as popularized by GoF) might just be language features in Lisp/Rust/whatever.

    So rather than thinking about patterns, you should first choose the right language for the task. If you’re working on a parser, you might prefer Haskell. If you need formal verification, there’s C and Idris and little inbetween. If you need to hire lots of developers, something widely-known like JS might be the choice.

    After you’ve chosen a language, you can identify the things that the language is bad at and apply the appropriate design patterns. Sometimes the patterns can be found in books (C++, Java) and sometimes it’s just tribal knowledge (D).