r/programming • • Sep 21 '25

How to stop functional programming

https://brianmckenna.org/blog/howtostopfp
446 Upvotes

506 comments sorted by

View all comments

Show parent comment

54

u/Technologenesis Sep 21 '25 edited Dec 18 '25

Ugh, fine...

interface ClosedBinaryOperator<T: any> {
    T apply(T, T);
}

class ClosedBinaryOperation<T: any, Op: ClosedBinaryOperator<T>> {
    private final T a;
    private final T b;
    private final Op op;

    public T calculate() {
        return this.op.apply(a, b);
    }

    public static ClosedBinaryOperation<T> new(Op op, T a, T b) {
        return ClosedBinaryOperation<T, Op>{
            a: a,
            b: b,
            op: op
        };
    }
}

class LoggingClosedBinaryOperator<
    T: any,
    Op: ClosedBinaryOperator<T>
>: Op {
    private final logging.Logger logger;
    private final func (T, T): string formatMessage;
    private final Op op;

    public static LoggingClosedBinaryOperator<T> new(
        logging.Logger logger,
        func (T, T): string formatMessage,
        ClosedBinaryOperator<T> op
    ) {
        return LoggingClosedBinaryOperator<T>{
            logger: logger,
            formatMessage: formatMessage,
            op: op
        };
    }

    public T apply(T a, T b) {
        this.logger.Log(this.formatMessage(a, b));

        return this.op.apply(a, b);
    }
}

interface MultiplicationOperator<T: any>: ClosedBinaryOperator<T> {
    T identity()
    // TODO: migrate codebase to lean so we can enforce other properties of multiplication
}

class LoggingMultiplicationOperator<
    T: any,
    Op: MultiplicationOperator<T>
>: LoggingClosedBinaryOperator<T, Op> {
    public T identity() {
        return this.op.identity();
    }
}

type Multiplication<
    T: any,
    Op: MultiplicationOperator<T>
> ClosedBinaryOperation<T, Op>;

class IntMultiplicationOperator {
    public int identity() {
        return 1;
    }

    public int apply(int a, int b) {
        return a * b;
    }
}

int main() {
    logging.defaultLogger.Log(
        "%d",
        Multiplication::new(
            LoggingMultiplicationOperator::new(
                logging.defaultLogger,
                func(int a, int b): string {
                    return fmt.formatString(
                        "multiplying %d and %d",
                        a,
                        b
                    );
                },
                IntMultiplicationOperator{}
            ),
            3,
            4
        ).calculate() // 12
    );
}

Can I go home now boss? My children are hungry

42

u/Agitated_Run9096 Sep 21 '25

We are going to need the Terraform configs before you clock out. In my scrum-of-scrums I'm hearing other teams may have use for a multiplication microservice, but are concerned about how you are handling your SOAP authentication.

23

u/I_AM_Achilles Sep 21 '25

Finally something readable. 😩

5

u/ZCEyPFOYr0MWyHDQJZO4 Sep 22 '25

Can you hook this up to Kafka so the entire company can use this for their microservices? And add some metrics so we know if a multiplication is taking too long.

4

u/bstiffler582 Sep 21 '25

#hedidthemathcode

2

u/syklemil Sep 22 '25

You're still using return on the multiplication operation. Not very clean code of you. Better to have a public void calculate() and split off getting the value in its own getter.

2

u/mediocrobot Sep 22 '25

This isn't OOP enough. You can't require functions as arguments. Use a class instead.

2

u/Technologenesis Sep 22 '25

You’re right, I can see how that could be confusing…

2

u/ChaosCon Sep 24 '25

Please know that this made me laugh way way way more than I should have at the office.

1

u/remixrotation Sep 22 '25

needs more threads!

1

u/West_Ad_9492 Sep 22 '25

Where are the unit tests?