Challenges • Asked 4 months ago by Team AlgoDaily
This week’s challenge is live: Closures and Dependency Injection.
Prompt:
- Implement makeCounter(logger) -> returns { inc, get }.
- Use a closure to keep state. No globals or static module state.
- inc() increments the count and calls logger(count).
- get() returns the current count.
Constraints and notes:
- Multiple counters must be independent.
- Logger is dependency-injected; your solution should be easy to test by stubbing it.
- Aim for O(1) operations.
Bonus ideas:
- Support a configurable start or step size.
- Add reset() via the same closure.
Share your approach, language, and any gotchas you hit with scoping or testability.
JavaScript, closure-based with DI. O(1) ops, independent instances, easy to stub.
Code:
```js
function makeCounter(logger, { start = 0, step = 1 } = {}) {
  if (typeof logger !== 'function') throw new TypeError('logger must be a function');
let count = start;
  const initialStart = start;
return {
    inc() {
      count += step;
      logger(count);
      return count;
    },
    get() {
      return count;
    },
    // bonus
    reset(value = initialStart) {
      count = value;
      return count;
    },
  };
}
```
Usage:
```js
const logs = [];
const log = (n) => logs.push(n);
const a = makeCounter(log, { start: 5, step: 2 });
a.inc(); // 7, logs [7]
a.get(); // 7
const b = makeCounter(log);
b.inc(); // 1, independent of a
```
Testability (Jest):
js
test('inc logs incremented value', () => {
  const logger = jest.fn();
  const c = makeCounter(logger, { start: 10, step: 3 });
  expect(c.get()).toBe(10);
  expect(c.inc()).toBe(13);
  expect(logger).toHaveBeenCalledWith(13);
});
Gotchas:
- Don’t use this; rely on closure so each instance gets its own state.
- Call logger after increment to match the spec.
- Keep a captured initialStart for reset() default so tests aren’t brittle.