JSFiddle - React, Tailwind, and code Playground

JavaScript

const mutualRecursion = (...fs) => fs.map(f => f(...fs));

const makeCounterBase = () => {
    let counter = 0;
    return {
        get: (g, s, i) => () => counter,
        set: (g, s, i) => value => counter = value,
        inc: (g, s, i) => () => s(g, s, i)(g(g, s, i)()+1)
    };
};

const makeCounter = () => {
    const base = makeCounterBase();
    const [get, set, inc] = mutualRecursion(base.get, base.set, base.inc);
    return {
        get,
        set,
        inc
    };
};

const makeLoggingCounter = () => {
    const base = makeCounterBase();
    const [get, set, inc] = mutualRecursion(
        (g, s, i) => () => { console.log('get!'); return base.get(g, s, i)(); },
        (g, s, i) => value => { console.log('set!'); return base.set(g, s, i)(value); },
        (g, s, i) => () => { console.log('inc!'); return base.inc(g, s, i)(); }
    );
    return {
        get,
        set,
        inc
    };
}


const counter1 = makeCounter();

console.log('Calling get()');
console.log(counter1.get());

console.log('Calling set(2)');
counter1.set(2);

console.log('Calling get()');
console.log(counter1.get());

console.log('Calling inc()');
counter1.inc();

console.log('Calling get()');
console.log(counter1.get());


const counter2 = makeLoggingCounter();
console.log('Calling get()');
console.log(counter2.get());

console.log('Calling set(2)');
counter2.set(2);

console.log('Calling get()');
console.log(counter2.get());

console.log('Calling inc()');
counter2.inc();

console.log('Calling get()');
console.log(counter2.get());