Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

If there is state then it makes sense for it to be a class

But the parent comment applies



Using init/a constructor implies state, does it not?


I think that depends on what we understand by 'state'. Do we count immutable data? Consider faking a 'bind' with something like:

    var quadrupler = new ConstantMultiplier(4);
    var output = quadrupler.applyTo(42);
The 'quadrupler' instance is stateless in that it's immutable, but it presumably has a (constant) member to store the value 4.


After ES6, I jumped at the opportunity to write classes in javascript, but lately I've realised I barely write classes anymore, but I write a lot of functions that return functions. And this example is perfect for that.

For example, I recently wrote this:

  const labelizeElement = ((element) => element.type.replace(/\s+/g, ''));
  const labelizeRelation = ((relation) => relation.type.toUpperCase().replace(/\s+/g, '_'));

  const groupByLabels = (labelizer) => (set, element) => (
    set[labelizer(element)]
      ? { ...set, [labelizer(element)]: [element, ...set[labelizer(element)]] }
      : { ...set, [labelizer(element)]: [element] }
  );
  const groupByElement = groupByLabels(labelizeElement);
  const groupByRelation = groupByLabels(labelizeRelation);
I needed two functions that did almost the same thing, but not quite. I don't want to write a ton of nearly-duplicate code, so instead I extract the bits that are different, and write a function that I actually need.

So yes, I'm inclined to say that only mutable state needs a class. And the more you get used to working with constants and immutables, the less mutable state you're going to find.

I used to be a big fan of OO, but somehow experience seems to have landed me in the functional programming camp.


Personally I'd avoid currying and go with a function with three params, like:

    const labelizeElement = ...
    const labelizeRelation = ...
    
    const groupByLabels = (labelizer, set, element) => ....
    
    const groupByElement = (set, element) => groupByLabels(labelizeElement, set, element);
    const groupByRelation = (set, element) => groupByLabels(labelizeRelation, set, element);
This makes it slightly simpler to create a binding function around groupByLabels which fixes, say, the middle argument. I also think that avoiding the chained use of the => operator makes the code more readable to the average JavaScript dev.

C++ has (strange looking) support for the bind pattern in its standard-library now [0], and Python3 has functools.partial but it only supports left-to-right binding [1] (not that there's any particular reason to avoid lambdas).

[0] https://en.cppreference.com/w/cpp/utility/functional/bind

[1] https://docs.python.org/3/library/functools.html


Yes. If nothing else, the calculation of that immutable data may be costly enough to motivate not calculating it multiple times. Hence you want to treat it as state. But that doesn't mean you want to expose it to the user of the class which may have a nice simple interface of cheap operations after the init is done.


    def __init__(self):
        pass

Not necessarily. Or the constructor is just setting some values that are later used by the calculation but are not modified and used later




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: