Game Instructions

Tap a tile to toggle its color. When a tile changes nearby tiles may change as well. Each move affect multiple tiles. The target is to turn all tiles into yellow in the fewest steps possible.

Press 'j' to show/hide the game. Press 'i' to show/hide the instructions. Press 't' to show/hide the top score table.

Steps: 0

Top Scores

Name Steps
Press J to toggle the game, I to toggle instructions, and T to toggle the top scores

Congratulations!

You solved the puzzle in 0 steps!

Success!

Score submitted successfully!

Error

Failed to submit score. Please try again.

Reflections from My Combinator Pattern Talk at PyCon AT 2026

banner for talk about combinators in pycon austria 2026
Designing flexible systems with combinators: clean composition over hardcoded logic.

During PyCon Austria 2026, I presented the combinator design pattern and showed how to structure logic as composable units rather than hard-coded flows.

The Programming Problem

When sophisticated logic is embedded within entities, it violates the Single Responsible Principle and makes systems harder to evolve. Every new requirement forces a modification rather than an extension. The core issue is modeling the logic as control flow rather than as composable units. This leads to rigid systems that resist change.

The Combinator Pattern Solution

By treating the logic rules as first-class objects, we can compose them like LEGO blocks into richer behavior. This enables flexible, extensible validation and logic pipelines. 

combinator talk audience

I was lucky to meet highly talented professionals who were curious to learn about the Combinator design pattern and chose to attend my talk. 

Slides from the Talk

The presentation of my talk is available for download at shareslides.net. It includes conceptual framing and concrete Python examples.

The Code Samples

You can find below the code samples I was using in my talk. I strongly recommend that you execute the code. It will assist you with improving your understanding of this specific topic. 

				
					from __future__ import annotations

from dataclasses import dataclass
from typing import Callable, List


@dataclass(frozen=True)
class ValidationResult:
    valid: bool
    errors: List[str]

    @staticmethod
    def success() -> ValidationResult:
        return ValidationResult(True, [])
    @staticmethod
    def failure(message: str) -> ValidationResult:
        return ValidationResult(False, [message])

    def merge(self, other: ValidationResult) -> ValidationResult:
        return ValidationResult(
            valid=self.valid and other.valid,
            errors=self.errors + other.errors,
        )


class PasswordRule:
    def __init__(self, validator: Callable[[str], ValidationResult]):
        self._validator = validator

    def validate(self, password: str) -> ValidationResult:
        return self._validator(password)

    def __call__(self, password: str) -> ValidationResult:
        return self.validate(password)

    def and_(self, other: PasswordRule) -> PasswordRule:
        def combined(password: str) -> ValidationResult:
            return self.validate(password).merge(other.validate(password))
        return PasswordRule(combined)

    def or_(self, other: PasswordRule) -> PasswordRule:
        def at_least_one(password: str) -> ValidationResult:
            result = self.validate(password).valid or other.validate(password).valid
            return ValidationResult.success() if result else ValidationResult.failure("Password must match at least one rule.")
        return PasswordRule(at_least_one)


def min_length(length: int) -> PasswordRule:
    return PasswordRule(
        lambda password: (
            ValidationResult.success()
            if len(password) >= length
            else ValidationResult.failure(
                f"Password must be at least {length} characters long."
            )
        )
    )


def has_uppercase() -> PasswordRule:
    return PasswordRule(
        lambda password: (
            ValidationResult.success()
            if any(ch.isupper() for ch in password)
            else ValidationResult.failure(
                "Password must contain at least one uppercase letter."
            )
        )
    )


def has_lowercase() -> PasswordRule:
    return PasswordRule(
        lambda password: (
            ValidationResult.success()
            if any(ch.islower() for ch in password)
            else ValidationResult.failure(
                "Password must contain at least one lowercase letter."
            )
        )
    )


def has_digit() -> PasswordRule:
    return PasswordRule(
        lambda password: (
            ValidationResult.success()
            if any(ch.isdigit() for ch in password)
            else ValidationResult.failure(
                "Password must contain at least one digit."
            )
        )
    )


def has_special_char() -> PasswordRule:
    special_chars = set("!@#$%^&*()-_=+[]{};:,.<>?/|\\")
    return PasswordRule(
        lambda password: (
            ValidationResult.success()
            if any(ch in special_chars for ch in password)
            else ValidationResult.failure(
                "Password must contain at least one special character."
            )
        )
    )


def no_whitespace() -> PasswordRule:
    return PasswordRule(
        lambda password: (
            ValidationResult.success()
            if not any(ch.isspace() for ch in password)
            else ValidationResult.failure(
                "Password must not contain whitespace."
            )
        )
    )


if __name__ == "__main__":
    password_policy = (
        min_length(8)
        .and_(has_uppercase())
        .and_(has_lowercase())
        .and_(has_digit())
        .and_(has_special_char())
        .and_(no_whitespace())
    )

    passwords = [
        "abc",
        "password123",
        "Password123",
        "Password123!",
        "Password 123!",
    ]

    for password in passwords:
        result = password_policy.validate(password)

        print(f"Checking password: {password!r}")
        if result.valid:
            print("  Valid password")
        else:
            print("  Invalid password")
            for error in result.errors:
                print(f"   - {error}")
        print()

    #password = "abC"
    #policy = min_length(8).or_(has_uppercase())
    #print(policy.validate(password).valid)
				
			

Functional Programming

The functional programming paradigm is my favorite one. I have been teaching functional programming for many years. I usually use the Scala programming language. This talk was a great opportunity to combine the beauty of Python with the power of functional programming. 

The combinator pattern encourages a shift in how we think about software design. Instead of embedding logic into structures, we compose it. This small conceptual change can lead to systems that are significantly more flexible, testable, and aligned with fundamental design principles.

Share:

keyboard image

Programming Thinking Over Syntax

Prioritizing learning programming concepts over the syntax of programming languages becomes essential in an ERA where AI generates code effortlessly.

The Beauty of Code

Coding is Art! Developing Code That Works is Simple. Develop Code with Style is a Challenge!

Update cookies preferences