liveBook · Manning

Expression

As explained in F# in Action: A Revised Edition of Get Programming with F#

An expression is a program construct that evaluates to a value.

An expression is code that evaluates to a value. In F#, expressions are the default building block: calculations, bindings, and even if/then branching produce results that can be named, passed onward, or returned. This shifts attention from executing a sequence of updates to transforming input values into output values. section 4.0 section 4.1.4

Table 4.1 Expressions vs. statements (view table figure)

 

Returns something?

Has side-effects?

Expressions

Always

Occasionally

Statements

Never

Always

Use the comparison to distinguish expressions, which always return something and may have side effects, from statements, which return nothing and always have side effects. section 4.1

Expression-oriented code keeps calculation separate from its use. Rather than initialize a variable and assign it in several branches, let the branches compute one result and assign it once. Each branch must produce the same type, so a missing fallback branch becomes a compiler error instead of an unnoticed default or null value. section 4.1.3 section 4.1.4

Classifying an age

A conditional can turn an age into "Child", "Adult", or "OAP", then bind that result to ageDescription. The surrounding function can return a greeting string rather than print it directly. The calculation is now independently reusable for console output, file output, or a test. section 4.1.4 section 4.1.5

Expressions compose naturally because one result can become another operation’s input. Extract a calculation such as calculateAgeDescription into a function, give it the values it needs as inputs, and replace the original nested code with a call. Lightweight syntax and type inference make this refactoring practical to repeat. section 4.1.5

Prefer expressions when code is primarily computing a result:

  • Make branching return the value needed by the next step instead of mutating a variable across branches. section 4.1.3
  • Separate result generation from output or other external actions so the calculation can be reused and unit tested. section 4.1.5
  • Pair expressions with immutable bindings to reduce bugs caused by changing state and to make chains of function calls easier to observe. section 4.4 section 14.1.1

Not every operation has a meaningful result. F# uses unit for functions with no useful input or output value, while still treating scopes as value-producing. For ordinary application logic, favor returned values where possible: they reveal behavior through inputs and outputs and make testing more direct. section 4.1.4 section 4.3

How F# in Action: A Revised Edition of Get Programming with F# covers it

How deep it goes
Explains conditional expressions, uniform branch types, compiler checks, and function extraction without treating advanced functional-programming theory.
Examples
Uses age classification and greeting generation, a gas-driving conditional, and email validation results.
What it assumes
Introduces expressions without assuming prior F# or .NET knowledge, while using basic functions and conditional logic.
What you can do after
Apply it by writing value-returning conditionals and extracting calculations from output-oriented code.
How it connects
Connects expressions with immutability, statements, functions, type inference, unit testing, and pure functions.

Also explained in

Compare how 11 books explain expression →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of F# in Action: A Revised Edition of Get Programming with F#. The section links point to the parts of the book it draws on.