# Where this becomes a real pattern

Phase 1 established the rule. Here's where it stops being trivia and starts being something you lean on every day, usually without stopping to name it.

## The guard pattern

Say you have a `user` variable that might be `None`/`null`, and you want to print their name - but only if a user actually exists. Without short-circuiting, `user.name` would need `user` to be checked separately first, or it crashes trying to look up `.name` on nothing.

```python runnable
user = None

# without a guard, this line would crash:
# print(user.name)   -> AttributeError: 'NoneType' object has no attribute 'name'

# with the guard pattern:
print(user and user.name)
```

*What just happened:* `user` is `None`, which is falsy, so `and` already knows the whole expression is falsy - it stops right there and never touches `user.name`. Nothing crashes. If `user` had actually been an object with a `name` attribute, `and` would have needed to check the right side, evaluated `user.name`, and returned that instead.

This is the same shape as the "optional chaining" you may have seen as dedicated syntax in some languages (`user?.name` in JavaScript, for instance) - that syntax exists precisely to express this guard pattern more directly, but the underlying idea, checking that something exists before reaching into it, is exactly what `&&` was already doing.

```text
user && user.name
  |          |
  |          +-- only reached if user is truthy
  +-- checked first; if falsy, stops here
```

You'll see this chained further in real code too - `settings && settings.theme && settings.theme.color` - each `&&` guarding the next step from running on something that might not exist.

## Default values with OR

The mirror-image pattern uses `||` to supply a fallback when a value is missing.

```python runnable
def greet(name):
    display_name = name or "friend"
    print(f"Hello, {display_name}!")

greet("Amara")
greet(None)
greet("")
```

*What just happened:* when `name` is `"Amara"` - truthy - `or` already knows the result is truthy after checking the left side, so it short-circuits and returns `"Amara"` without even looking at `"friend"`. When `name` is `None`, the left side is falsy, so `or` has to check the right side, and returns `"friend"`. That's the pattern: `value or fallback` returns `value` if it's truthy, otherwise falls back.

Look closely at the third call, though - `greet("")`. An empty string is falsy too, so `or` falls back to `"friend"` even though the caller *did* provide a name; it just happened to be empty. That's not a bug in this particular example, but it's worth noticing now, because it's exactly the shape of problem Phase 3 digs into.

## Why both patterns are the same trick

Notice that the guard pattern and the default-value pattern are not two different features - they're the identical short-circuiting rule from Phase 1, aimed at two different problems. `&&` short-circuits on the first falsy value, which is useful when falsy means "stop, nothing more to check." `||` short-circuits on the first truthy value, which is useful when truthy means "good enough, use this." Once you see them as the same mechanism, you'll start noticing this rule everywhere - configuration loading, default arguments, permission checks - not just in the two examples above.
