You are previewing Real World OCaml.
O'Reilly logo
Real World OCaml

Book Description

This fast-moving tutorial introduces you to OCaml, an industrial-strength programming language designed for expressiveness, safety, and speed. Through the book’s many examples, you’ll quickly learn how OCaml stands out as a tool for writing fast, succinct, and readable systems code.

Table of Contents

  1. Dedication
  2. Special Upgrade Offer
  3. Prologue
    1. Why OCaml?
      1. A Brief History
      2. The Core Standard Library
      3. The OCaml Platform
    2. About This Book
      1. What to Expect
      2. Installation Instructions
      3. Code Examples
    3. Safari® Books Online
    4. How to Contact Us
    5. Contributors
  4. I. Language Concepts
    1. 1. A Guided Tour
      1. OCaml as a Calculator
      2. Functions and Type Inference
        1. Type Inference
        2. Inferring Generic Types
      3. Tuples, Lists, Options, and Pattern Matching
        1. Tuples
        2. Lists
          1. The List module
          2. Constructing lists with ::
          3. List patterns using match
          4. Recursive list functions
        3. Options
      4. Records and Variants
      5. Imperative Programming
        1. Arrays
        2. Mutable Record Fields
        3. Refs
        4. For and While Loops
      6. A Complete Program
        1. Compiling and Running
      7. Where to Go from Here
    2. 2. Variables and Functions
      1. Variables
        1. Pattern Matching and let
      2. Functions
        1. Anonymous Functions
        2. Multiargument functions
        3. Recursive Functions
        4. Prefix and Infix Operators
        5. Declaring Functions with Function
        6. Labeled Arguments
          1. Higher-order functions and labels
        7. Optional Arguments
          1. Explicit passing of an optional argument
          2. Inference of labeled and optional arguments
          3. Optional arguments and partial application
    3. 3. Lists and Patterns
      1. List Basics
      2. Using Patterns to Extract Data from a List
      3. Limitations (and Blessings) of Pattern Matching
        1. Performance
        2. Detecting Errors
      4. Using the List Module Effectively
        1. More Useful List Functions
          1. Combining list elements with List.reduce
          2. Filtering with List.filter and List.filter_map
          3. Partitioning with List.partition_tf
          4. Combining lists
      5. Tail Recursion
      6. Terser and Faster Patterns
    4. 4. Files, Modules, and Programs
      1. Single-File Programs
      2. Multifile Programs and Modules
      3. Signatures and Abstract Types
      4. Concrete Types in Signatures
      5. Nested Modules
      6. Opening Modules
      7. Including Modules
      8. Common Errors with Modules
        1. Type Mismatches
        2. Missing Definitions
        3. Type Definition Mismatches
        4. Cyclic Dependencies
      9. Designing with Modules
        1. Expose Concrete Types Rarely
        2. Design for the Call Site
        3. Create Uniform Interfaces
        4. Interfaces before implementations
    5. 5. Records
      1. Patterns and Exhaustiveness
      2. Field Punning
      3. Reusing Field Names
      4. Functional Updates
      5. Mutable Fields
      6. First-Class Fields
    6. 6. Variants
      1. Catch-All Cases and Refactoring
      2. Combining Records and Variants
      3. Variants and Recursive Data Structures
      4. Polymorphic Variants
        1. Example: Terminal Colors Redux
        2. When to Use Polymorphic Variants
    7. 7. Error Handling
      1. Error-Aware Return Types
        1. Encoding Errors with Result
        2. Error and Or_error
        3. bind and Other Error Handling Idioms
      2. Exceptions
        1. Helper Functions for Throwing Exceptions
        2. Exception Handlers
        3. Cleaning Up in the Presence of Exceptions
        4. Catching Specific Exceptions
        5. Backtraces
        6. From Exceptions to Error-Aware Types and Back Again
      3. Choosing an Error-Handling Strategy
    8. 8. Imperative Programming
      1. Example: Imperative Dictionaries
      2. Primitive Mutable Data
        1. Array-Like Data
          1. Ordinary arrays
          2. Strings
          3. Bigarrays
        2. Mutable Record and Object Fields and Ref Cells
          1. Ref cells
        3. Foreign Functions
      3. for and while Loops
      4. Example: Doubly Linked Lists
        1. Modifying the List
        2. Iteration Functions
      5. Laziness and Other Benign Effects
        1. Memoization and Dynamic Programming
      6. Input and Output
        1. Terminal I/O
        2. Formatted Output with printf
        3. File I/O
      7. Order of Evaluation
      8. Side Effects and Weak Polymorphism
        1. The Value Restriction
        2. Partial Application and the Value Restriction
        3. Relaxing the Value Restriction
      9. Summary
    9. 9. Functors
      1. A Trivial Example
      2. A Bigger Example: Computing with Intervals
        1. Making the Functor Abstract
        2. Sharing Constraints
        3. Destructive Substitution
        4. Using Multiple Interfaces
      3. Extending Modules
    10. 10. First-Class Modules
      1. Working with First-Class Modules
      2. Example: A Query-Handling Framework
        1. Implementing a Query Handler
        2. Dispatching to Multiple Query Handlers
        3. Loading and Unloading Query Handlers
      3. Living Without First-Class Modules
    11. 11. Objects
      1. OCaml Objects
      2. Object Polymorphism
      3. Immutable Objects
      4. When to Use Objects
      5. Subtyping
        1. Width Subtyping
        2. Depth Subtyping
        3. Variance
        4. Narrowing
        5. Subtyping Versus Row Polymorphism
    12. 12. Classes
      1. OCaml Classes
      2. Class Parameters and Polymorphism
      3. Object Types as Interfaces
        1. Functional Iterators
      4. Inheritance
      5. Class Types
      6. Open Recursion
      7. Private Methods
      8. Binary Methods
      9. Virtual Classes and Methods
        1. Create Some Simple Shapes
      10. Initializers
      11. Multiple Inheritance
        1. How Names Are Resolved
        2. Mixins
        3. Displaying the Animated Shapes
  5. II. Tools and Techniques
    1. 13. Maps and Hash Tables
      1. Maps
        1. Creating Maps with Comparators
        2. Trees
        3. The Polymorphic Comparator
        4. Sets
        5. Satisfying the Comparable.S Interface
      2. Hash Tables
        1. Satisfying the Hashable.S Interface
      3. Choosing Between Maps and Hash Tables
    2. 14. Command-Line Parsing
      1. Basic Command-Line Parsing
        1. Anonymous Arguments
        2. Defining Basic Commands
        3. Running Basic Commands
      2. Argument Types
        1. Defining Custom Argument Types
        2. Optional and Default Arguments
        3. Sequences of Arguments
      3. Adding Labeled Flags to the Command Line
      4. Grouping Subcommands Together
      5. Advanced Control over Parsing
        1. The Types Behind Command.Spec
        2. Composing Specification Fragments Together
        3. Prompting for Interactive Input
        4. Adding Labeled Arguments to Callbacks
      6. Command-Line Autocompletion with bash
        1. Generating Completion Fragments from Command
        2. Installing the Completion Fragment
      7. Alternative Command-Line Parsers
    3. 15. Handling JSON Data
      1. JSON Basics
      2. Parsing JSON with Yojson
      3. Selecting Values from JSON Structures
      4. Constructing JSON Values
      5. Using Nonstandard JSON Extensions
      6. Automatically Mapping JSON to OCaml Types
        1. ATD Basics
        2. ATD Annotations
        3. Compiling ATD Specifications to OCaml
        4. Example: Querying GitHub Organization Information
    4. 16. Parsing with OCamllex and Menhir
      1. Lexing and Parsing
      2. Defining a Parser
        1. Describing the Grammar
        2. Parsing Sequences
      3. Defining a Lexer
        1. OCaml Prelude
        2. Regular Expressions
        3. Lexing Rules
        4. Recursive Rules
      4. Bringing It All Together
    5. 17. Data Serialization with S-Expressions
      1. Basic Usage
        1. Generating S-Expressions from OCaml Types
      2. The Sexp Format
      3. Preserving Invariants
      4. Getting Good Error Messages
      5. Sexp-Conversion Directives
        1. sexp_opaque
        2. sexp_list
        3. sexp_option
        4. Specifying Defaults
    6. 18. Concurrent Programming with Async
      1. Async Basics
        1. Ivars and Upon
      2. Examples: An Echo Server
        1. Improving the Echo Server
      3. Example: Searching Definitions with DuckDuckGo
        1. URI Handling
        2. Parsing JSON Strings
        3. Executing an HTTP Client Query
      4. Exception Handling
        1. Monitors
        2. Example: Handling Exceptions with DuckDuckGo
      5. Timeouts, Cancellation, and Choices
      6. Working with System Threads
        1. Thread-Safety and Locking
  6. III. The Runtime System
    1. 19. Foreign Function Interface
      1. Example: A Terminal Interface
      2. Basic Scalar C Types
      3. Pointers and Arrays
        1. Allocating Typed Memory for Pointers
        2. Using Views to Map Complex Values
      4. Structs and Unions
        1. Defining a Structure
        2. Adding Fields to Structures
        3. Incomplete Structure Definitions
          1. Recap: A time-printing command
        4. Defining Arrays
      5. Passing Functions to C
        1. Example: A Command-Line Quicksort
      6. Learning More About C Bindings
        1. Struct Memory Layout
    2. 20. Memory Representation of Values
      1. OCaml Blocks and Values
        1. Distinguishing Integers and Pointers at Runtime
      2. Blocks and Values
        1. Integers, Characters, and Other Basic Types
      3. Tuples, Records, and Arrays
        1. Floating-Point Numbers and Arrays
      4. Variants and Lists
      5. Polymorphic Variants
      6. String Values
      7. Custom Heap Blocks
        1. Managing External Memory with Bigarray
    3. 21. Understanding the Garbage Collector
      1. Mark and Sweep Garbage Collection
      2. Generational Garbage Collection
      3. The Fast Minor Heap
        1. Allocating on the Minor Heap
      4. The Long-Lived Major Heap
        1. Allocating on the Major Heap
        2. Memory Allocation Strategies
          1. Next-fit allocation
          2. First-fit allocation
        3. Marking and Scanning the Heap
        4. Heap Compaction
        5. Intergenerational Pointers
          1. The mutable write barrier
      5. Attaching Finalizer Functions to Values
    4. 22. The Compiler Frontend: Parsing and Type Checking
      1. An Overview of the Toolchain
      2. Parsing Source Code
        1. Syntax Errors
        2. Automatically Indenting Source Code
        3. Generating Documentation from Interfaces
      3. Preprocessing Source Code
        1. Using Camlp4 Interactively
        2. Running Camlp4 from the Command Line
        3. Preprocessing Module Signatures
        4. Further Reading on Camlp4
      4. Static Type Checking
        1. Displaying Inferred Types from the Compiler
        2. Type Inference
          1. Adding type annotations to find errors
          2. Enforcing principal typing
        3. Modules and Separate Compilation
          1. The mapping between files and modules
          2. Defining a module search path
        4. Packing Modules Together
        5. Shorter Module Paths in Type Errors
      5. The Typed Syntax Tree
        1. Using ocp-index for Autocompletion
        2. Examining the Typed Syntax Tree Directly
    5. 23. The Compiler Backend: Bytecode and Native code
      1. The Untyped Lambda Form
        1. Pattern Matching Optimization
        2. Benchmarking Pattern Matching
      2. Generating Portable Bytecode
        1. Compiling and Linking Bytecode
        2. Executing Bytecode
        3. Embedding OCaml Bytecode in C
      3. Compiling Fast Native Code
        1. Inspecting Assembly Output
          1. The impact of polymorphic comparison
          2. Benchmarking polymorphic comparison
        2. Debugging Native Code Binaries
          1. Understanding name mangling
          2. Interactive breakpoints with the GNU debugger
        3. Profiling Native Code
          1. Gprof
          2. Perf
        4. Embedding Native Code in C
      4. Summarizing the File Extensions
  7. Index
  8. About the Authors
  9. Colophon
  10. Special Upgrade Offer
  11. Copyright