Programming with AI
ENRU
3.12

Technique — input → output examples

two examples instead of a paragraph of description

What it is

Instead of describing in words what a function should do, show a pair of "what came in → what should come out". Two examples remove more ambiguity than a paragraph of explanation, and they are checked instantly.

The technique is strongest where words are slow and imprecise: parsing text, formats, data transformations, edge cases.

What it looks like in code

In words

Don't
Write a function that normalises a phone number
into international format

What does "normalise" mean? Which input formats? What about spaces and brackets? What about a number with no country code? The AI will close all of those forks itself.

With examples

Better
Function normalize_phone(raw: str) -> str | None.
Examples:

"+47 912 34 567"   -> "+4791234567"
"47-912-34-567"    -> "+4791234567"
"912 34 567"       -> "+4791234567"   (no code — assume Norwegian)
"+7 999 123-45-67" -> "+79991234567"
"not a phone"      -> None
""                 -> None

The default country code comes in as an argument, default_cc="47".

Six lines close everything: the output format, what to do with separators, the behaviour without a country code, handling garbage. In words the same would have taken half a page, and something would still have been left unsaid.

The examples double as tests

Prompt
Turn these examples into a parameterised pytest test.

One prompt and the check is ready. The examples you explained the task with become the thing that verifies it. This is the cheapest way to get the tests from article 3.9.

What to tell the AI

How many examples are needed

Three to five. One shows the happy case and says nothing about boundaries. Ten are too many and start contradicting each other.

Be sure to include:

  • the ordinary case — the thing it is all for;
  • a boundary case — an empty string, zero, a single record, the maximum length;
  • a failing case — garbage input, and what should happen then.

The third is skipped most often and decides the most: it is what tells the AI whether to return None, raise an exception, or substitute a default.

The notation

An arrow and alignment read better than prose:

measured
input             -> output

If the output is complex, show it as it is, with its structure:

Prompt
Input:  {"cod": "404", "message": "city not found"}
Output: None

Input:  {"main": {"temp": 4.2}, "weather": [{"main": "Rain"}]}
Output: ("Rain", 4.2)

Where the technique doesn't fit

Anywhere the result cannot be written as a string: interfaces, architecture, "make it look good". For those, the plan (3.10) and the questions (3.11) are what work.

What to look for

Code fitted to the examples. The most insidious failure: the function contains if raw == "+47 912 34 567": return .... It looks like it works, passes all your examples and falls apart on the seventh input. Read the code, not only the result.

Examples that contradict each other. This happens when there are many and they were written in haste. The AI will quietly pick one reading. If you spot a contradiction in the answer, fix the examples, not the code.

Edge cases decided for you. If you didn't say what to do with an empty string, the code will contain a decision you never made. Check which one.

Cheat sheet

  • Two or three "input → output" examples instead of a paragraph.

  • Required: the ordinary case, a boundary case, a failing case.

  • The failing case decides what happens on garbage input.

  • Examples turn into a test with one prompt.

  • Check that the code solves the task rather than fitting the examples.

  • For tasks with no string-shaped result the technique doesn't apply.