Why Functional Simplicity Makes AI Shine - HuMpY tExT Edition

Friday, October 10, 2025

We’ve been talking about writing AI-friendly code, and one of the easiest ways to get there is through a lightweight functional approach.

AI tools like Cursor (and even ChatGPT) thrive when the code they see predictable, testable, and free of hidden side effects.

That doesn’t mean turning our apps into a math experiment — it means writing small, pure functions that can be composed together and tested in isolation.

To show what that looks like in its simplest form, here’s a tiny (and relatively useless) example I built close to 10 years ago — a little snippet that converts text into alternating upper/lower case: HuMpY tExT.

👉 CodePen: https://codepen.io/JDHorn/pen/MWWoPJK?editors=0010


🧩 The Full Code

1const text = "Enter some text";
2
3// arrow function version
4const pipe_ = (...fns) => (accumulator) =>
5  fns.reduce((fn, reducer) => reducer(fn), accumulator);
6
7// classic function
8function pipe(...fns) {
9  return function (result) {
10    fns.reduce(function (val, fn) {
11      return fn(val);
12    }, result);
13  };
14}
15
16const splitChars = (dirty) => [...dirty];
17const joinResult = (arr) => arr.join("");
18
19const modArray = (arr) => {
20  const result = [];
21  const toggler = function (toggle = false) {
22    return function () {
23      return (toggle = !toggle);
24    };
25  };
26
27  const toggle = toggler();
28  const isAlpha = (dirty) => !!dirty.match(/[a-zA-Z]/);
29  const pushToResult = (dirty) => result.push(dirty);
30
31  const switchCase = (dirty) =>
32    isAlpha(dirty)
33      ? toggle()
34        ? dirty.toUpperCase()
35        : dirty.toLowerCase()
36      : dirty;
37
38  const convertThenPush = pipe(switchCase, pushToResult);
39  arr.forEach(convertThenPush);
40
41  return result;
42};
43
44const updateOutput = (entry = text) => (target.innerText = entry);
45
46const convertArrayToHumpyCaseAndPrint = pipe(
47  splitChars,
48  modArray,
49  joinResult,
50  updateOutput
51);
52
53const el = document.getElementById("entry");
54const target = document.getElementById("target");
55
56el.addEventListener("focus", () => el.select());
57target.addEventListener("focus", () =>
58  window.getSelection().selectAllChildren(target)
59);
60
61const modifyText = (ev) => convertArrayToHumpyCaseAndPrint(ev.target.value);
62el.addEventListener("keyup", modifyText, false);
63
64updateOutput();

🤔 Why This Matters for AI-Driven Development

  • Predictability → Better AI suggestions

Pure functions behave deterministically, so Cursor can safely reason about them and build on top of them.

  • Isolation → Safer AI refactors

When side effects live at the edges, the AI can’t accidentally break something hidden.

  • Clarity → Smarter completions

Each step has a single responsibility, making the intent easy for both humans *and* AI to follow.


🪄 Functional at a Glance

Each small function does one thing:

  • splitChars → break input into data

  • modArray → transform that data

  • joinResult → reassemble it

  • updateOutput → perform the one side effect (DOM update)

Everything up to updateOutput is pure - no external dependencies, no mutation, fully testable.


💡 Keep It Stupid Simple (KISS-FP)

We’re not introducing monads or heavy FP libraries — just encouraging a small habit:

Write pure, composable functions.

Chain them together.

Keep side effects at the edges.

It keeps our code AI-ready, human-readable, and ridiculously easy to test 💪