The Computing Series

What Is a Statement?

Introduction

Around 350 BCE, Aristotle drew a line that every programmer crosses every day without knowing it.

He was not writing about computers. He was writing about argumentation — how to distinguish valid reasoning from sophistry. But in doing so, he identified the atomic unit of all logical thought: a declarative sentence that is either true or false, never both, never neither.

He called it a proposition. We now call it a boolean.

Every if statement ever written — in C, Python, SQL, assembly — bottoms out at this idea. Before you can understand state machines, distributed consensus, or database transaction models, you have to understand what it means for a sentence to have a truth value. That is where this chapter begins.


Thread Activation

Thread 7 (State Machines) originates here.

A statement is the smallest possible unit of logical state. It can be True or False. Nothing else. This binary quality is not a limitation — it is a foundation. Every state machine you will encounter in this series, from a traffic light controller to a distributed database’s leader election protocol, is built from statements about the world that are either satisfied or not.

This is the mathematical root of a pattern that will appear at every level of the computing stack. By the time you finish this series, you will have seen it as a state machine, a database transaction model, and an architectural principle. Right now, it is just a sentence. Keep that in mind.


The Concept

A statement (also called a proposition) is a declarative sentence with a definite truth value: it is either True or False.

Three examples of statements:

  • “The integer 7 is prime.” — True.
  • “Python lists are zero-indexed.” — True.
  • “Every HTTP request returns within 100ms.” — False (in general).

Three examples of non-statements:

  • “Is the server running?” — A question. No truth value.
  • “Restart the service.” — A command. No truth value.
  • “x is greater than 5.” — An open statement. Truth value unknown until x is assigned.

The distinction matters. Logic, and therefore programming, operates only on things that can be evaluated. Questions and commands cannot be evaluated as true or false. Open statements defer evaluation until a value is substituted.

The Robot Metaphor

Imagine a robot that can only respond to sentences by evaluating them as True or False. Hand it a command and it stalls. Hand it a question and it stalls. Hand it a statement and it evaluates immediately.

A programming language interpreter is that robot. The expression len(items) > 0 is a statement. The interpreter evaluates it. It produces True or False. It does not ask “what do you mean by items?” — that would be an error, not a hesitation. Either items is in scope or the program crashes.

This robot model exposes something important: statements are contracts. When you write if user.is_active:, you are telling the interpreter that user.is_active will resolve to a truth value. If it resolves to None in a language without implicit boolean coercion, the contract is violated. The robot stalls.

Variables and Open Statements

An open statement contains one or more free variables. It is not a statement until those variables are bound to values.

x > 10

This is not True or False. It is a predicate — a function from a domain to {True, False}. When you substitute x = 15, the predicate becomes the statement “15 > 10”, which is True. When you substitute x = 3, it becomes “3 > 10”, which is False.

Open statements are covered in depth in Chapter 5. For now, the key distinction is: a statement has a fixed truth value; a predicate produces a truth value when given inputs.


How It Works

Truth Values

A statement’s truth value is not an opinion. It is a property of the statement under a given interpretation.

“The integer 4 is prime” is False. Not “probably false” or “false for most people.” False. No exceptions.

“This HTTP endpoint is idempotent” — this can be True or False depending on the implementation. But for any specific, fully-specified implementation, one answer is correct.

In classical logic (which is the foundation of programming), truth values are bivalent: exactly two values, True and False, with no middle ground. This is the Law of Excluded Middle: for any statement P, either P is True or P is False. There is no third option.

This sounds obvious until you encounter three-valued logic in databases. SQL uses NULL as a third truth value. NULL = NULL does not return True in SQL — it returns NULL. This is a deliberate deviation from classical logic. It causes significant confusion. Chapter 5 returns to this.

Atomic vs. Compound Statements

An atomic statement cannot be broken into smaller statements. “The cache is warm” is atomic. You cannot decompose it further while preserving logical structure.

A compound statement is built from atomic statements using logical operators. “The cache is warm AND the database is reachable” is compound. It is the conjunction of two atomic statements. Logical operators are Chapter 2’s subject.

For now: every compound statement bottoms out at atomic statements. Atomic statements are the leaves of the logical expression tree.

Booleans in Programming

Every boolean value in every programming language is the evaluation of a statement. When Python evaluates 5 > 3, it evaluates the statement “5 is greater than 3” and returns True.

# These are statements — each evaluates to True or False
is_connected = server_status == "running"   # statement: server_status equals "running"
has_capacity = queue_depth < MAX_QUEUE      # statement: queue_depth is less than MAX_QUEUE
is_valid_request = content_length > 0       # statement: content_length is positive

# This is a conditional — it branches on the truth value of a statement
if is_connected and has_capacity:
    process_request()

The variable is_connected holds the truth value of a statement. It is not the statement itself. It is the result of evaluating the statement at a specific moment. This distinction matters when the underlying facts change. The statement “the server is running” might be True at 14:00:00 and False at 14:00:01. The variable is_connected does not update automatically. It holds a snapshot.

This is the first hint of a deeper problem: state. A statement evaluated over a mutable system produces a truth value that can become stale. This will reappear as a major theme in Chapter 5 (quantifiers over mutable sets) and throughout Book 3 (distributed systems).

The if-Statement as Logical Evaluation

def can_process(request_size: int, queue_depth: int, max_queue: int) -> bool:
    # Statement: the queue has room for this request
    queue_has_room = queue_depth < max_queue

    # Statement: the request is within the size limit
    request_is_valid = request_size > 0 and request_size <= MAX_REQUEST_SIZE

    # Compound statement: both conditions hold
    return queue_has_room and request_is_valid

Every boolean expression in this function is evaluated as a statement. The function itself is a statement-valued function: given inputs, it returns a truth value. In mathematics, this is a predicate. In programming, it is a boolean function. Same concept, different notation.


Tradeoffs

AT3 — Simplicity vs. Flexibility

Classical logic uses exactly two truth values. This is maximally simple. It enables efficient hardware implementation — a single bit. It enables exhaustive testing — there are exactly two cases. It enables formal verification — proofs reduce to symbolic manipulation of True and False.

The cost is expressiveness. Real systems have states that do not reduce cleanly to binary. “Is this service healthy?” might be “yes”, “no”, “degraded”, “unknown”, or “recovering.” Forcing this into a binary produces false precision.

The engineering resolution is not to abandon binary logic but to be explicit about the mapping. Define a ServiceStatus enum. Write a function is_healthy(status: ServiceStatus) -> bool. The boolean interface preserves the simplicity guarantee. The enum preserves the expressiveness. The explicit mapping makes the tradeoff visible.

from enum import Enum

class ServiceStatus(Enum):
    HEALTHY = "healthy"
    DEGRADED = "degraded"
    UNHEALTHY = "unhealthy"
    UNKNOWN = "unknown"

def is_healthy(status: ServiceStatus) -> bool:
    # Explicit mapping from multi-valued state to binary statement
    # This is a design decision: DEGRADED maps to True here
    # A different caller might map DEGRADED to False
    return status in (ServiceStatus.HEALTHY, ServiceStatus.DEGRADED)

This is AT3 in practice: the boolean interface is simple; the enum is flexible; the mapping function is the explicit tradeoff point.


Where It Fails

FM8 — Schema/Contract Violation

A statement is a contract between the writer and the evaluator. The writer claims: “this expression will resolve to True or False.” The evaluator trusts that claim. When the claim is wrong, the contract is violated.

Three ways this happens in practice:

1. Type coercion masks non-boolean values.

Python treats many non-boolean values as truthy or falsy. This is convenient and dangerous.

# Apparent statement: "the response has a body"
if response.body:
    process(response.body)

If response.body is an empty list, this is False — correct. If response.body is 0, this is False — possibly incorrect if 0 is a valid body. If response.body is None, this is False — correct. The problem: the code does not distinguish between “body is empty” and “body is absent.” They are different facts. The statement conflates them.

2. Stale truth values.

# Evaluated once, held forever
cache_is_warm = precheck_cache()

# ... 500 milliseconds of network calls later ...

if cache_is_warm:           # was true 500ms ago; may now be false
    read_from_cache()       # cache could have been evicted

The statement was True when evaluated. The fact changed. The stored truth value did not. This is not a logic error. It is a temporal contract violation. The statement implicitly claims “the cache is warm right now.” Storing the result breaks that claim.

3. Ambiguous natural language statements mapped to code.

“The user is authorized” — authorized to do what? At what privilege level? From which IP range? In which context?

A natural language statement that sounds definite often has hidden parameters. When mapped to a boolean, those parameters become invisible. The code evaluates the statement for one specific interpretation. Callers assume their interpretation. The contract is violated silently.

# Bad: "is_authorized" — authorized for what?
def is_authorized(user: User) -> bool:
    return user.role == "admin"

# Better: explicit about what the statement means
def is_authorized_for_deletion(user: User, resource: Resource) -> bool:
    return user.role == "admin" and resource.owner_id == user.id

The second version is a statement with explicit parameters. Its contract is clear.


Real Systems

Authorization systems are built from statements. AWS IAM policies are logical expressions over statements like “this principal has this action on this resource.” When a policy evaluates to True, access is granted. The entire access control model is statement evaluation.

Health checks in Kubernetes are statements. livenessProbe evaluates: “is this container alive?” The probe returns a binary result. Kubernetes branches on it. The complexity is in defining what “alive” means precisely enough that the statement evaluates correctly.

Database constraints are statements about data. NOT NULL, UNIQUE, CHECK (age > 0) — each is a statement that must hold True for every row. The database evaluates these statements at write time. A constraint violation is a statement that evaluated to False when it was required to be True. This is FM8: a schema/contract violation.

Compiler type systems evaluate statements about programs before the programs run. “This variable is always an integer” is a statement. The type checker proves it True or False at compile time. A type error is a statement the type checker cannot prove True — a contract violation caught early.


Concept: Statement (Proposition)

Core Idea: A statement is a declarative sentence with a definite truth value — True or False, never both, never neither. It is the atomic unit of logical reasoning and the foundation of every boolean operation in computing.

Tradeoff: AT3 — Simplicity vs. Flexibility (binary truth values are simple but force explicit mappings from multi-valued real-world states)

Failure Mode: FM8 — Schema/Contract Violation (a statement is a contract; ambiguous or stale statements break the evaluator’s assumptions)

Signal: When an if-condition evaluates unexpectedly, or when authorization logic produces wrong results — re-examine what statement is actually being evaluated and whether it matches what you intend.


Exercises

Level 1 — Understand

  1. Classify each of the following as: (a) a statement, (b) an open statement / predicate, (c) not a statement. Explain your reasoning.

    • “The number 17 is divisible by 3.”
    • “Delete all rows where status = ‘expired’.”
    • “n is a power of 2.”
    • “Is the server reachable?”
    • “The empty string is falsy in Python.”
  2. What is the difference between a statement and an open statement? Give a programming example of each.

  3. State the Law of Excluded Middle. Name one common computing context where it does not hold, and explain why that context deviates from classical logic.

Level 2 — Apply

Consider this Python function:

def should_retry(attempt: int, error_code: int, is_idempotent: bool) -> bool:
    return attempt < 3 and error_code >= 500 and is_idempotent
  1. Identify the three atomic statements that compose the return expression.

  2. The function is called as should_retry(2, 503, True). Evaluate each atomic statement and the compound statement. Show your work.

  3. A new requirement arrives: “also retry on error code 429, but only if the attempt count is less than 5.” Rewrite the function. Identify what new atomic statements you introduced.

Level 3 — Design

A monitoring system stores the result of health checks as boolean variables: db_healthy, cache_healthy, api_healthy. These are evaluated once per minute and cached.

  1. Identify at least two ways the boolean storage model creates contract violations (FM8).

  2. Propose a design that preserves the simplicity of boolean evaluation at the decision point (the if statement) while making the temporal assumptions explicit. Name the tradeoff you are making (AT3).

  3. A teammate proposes replacing the three booleans with a single SystemHealth enum with values HEALTHY, DEGRADED, PARTIAL, UNHEALTHY. What does this solve? What does it cost? Name the tradeoff explicitly using AT framework notation.

A complete answer will: state the governing tradeoff by code, name the failure mode the design exposes, and justify the chosen design against at least one alternative.

Read in the book →