Batu Lab NotesPractical developer guides

Compose two pure transformations explicitly

By Batu ยท English technical notes

Also published in our Blogger archive.

Compose two pure transformations explicitly

Composition is easiest to audit when its order is written in the helper signature. compose(after, before) builds composed, which sends one input value to before and sends that returned value to after. Here, trim_and_casefold receives the string " Admin.Users " and returns "admin.users". dotted_to_path then receives that value and returns "admin/users".

Both transformations are pure for this input: they return new strings and do not mutate the original string. Naming them also exposes a useful semantic choice. casefold() is stronger than simple lowercasing for Unicode text, while replace(".", "/") treats every dot as a separator. The assertion on raw shows the pipeline has not changed the input binding, and the intermediate assertion documents which stage produced which value.

This compact helper deliberately handles one argument and one return value per stage. Adapt functions that need configuration with a closure or functools.partial; do not obscure a two-input operation by silently dropping an argument. Composition itself cannot make an impure stage pure, and exceptions from either function propagate to the caller. It also does not validate whether the resulting slash-separated text is a valid path for any filesystem.

def trim_and_casefold(text):
    return text.strip().casefold()


def dotted_to_path(text):
    return text.replace(".", "/")


def compose(after, before):
    def composed(value):
        return after(before(value))

    return composed


normalize_module_path = compose(dotted_to_path, trim_and_casefold)
raw = "  Admin.Users  "
intermediate = trim_and_casefold(raw)
result = normalize_module_path(raw)

assert raw == "  Admin.Users  "
assert intermediate == "admin.users"
assert result == "admin/users"
print(result)

Expected stdout:

admin/users

By Batu. AI assistance was used to prepare this article.

Source: Python string casefold documentation.