loading...

re: Function vs Object VIEW POST

FULL DISCUSSION
 

Well, the FP example looks the same because it is, actually, almost the same. The function returns an object. "bark" is a function with a side effect. In FP world this kind of function would be executed in some IO structure. At least it should return something, e.g.:

const bark = name => {
  console.log(`${name} is a good dog!`); // Dirty side effect
  return name;
}

Bark in DogFunction becomes a map function:

const DogFunction = name => {
  return {
    map: f => {
      return DogFunction(f(name));
    }
  }
}

Then we call it like this:

const dog = DogFunction("good boy");
const dogAfterBark = dog.map(bark);
// logs "good boy is a good dog!" and return a new dog

This is how I see the example with a dog.

Edit: added code parsing

 

The function returns an object.

This is JS specifics, I don't have other key-value data structure

Note: function returns record data structure (which in JS confusingly named "Object", but we don't use any "objecty" feature we use it as a simple key-value data structure). Variable name privately stored in the scope of a closure, there is no way to access it outside.


"bark" is a function with a side effect

This was for the demo purpose, changed it to return.

 

It is better now w/o a side effect, however, the difference comes with adding more logic, e.g. changing an attribute of it.
Classic OOP way:

class DogClass {
  #color = 'white';
  #needToWash = false;
  walk(isRaining = false) {
    this.#color = isRaining || this.#color === 'dirty' ? 'dirty' : this.#color;
    this.#needToWash = this.#needToWash || isRaining;
  }
}
const belka = new DogClass();
belka.walk(); // "belka" mutated: { color: 'white', needToWash: false }
belka.walk(true); // "belka" mutated: { color: 'dirty', needToWash: true }
belka.walk(); // "belka" mutated: { color: 'dirty', needToWash: true }

FP way based on the example:

const DogFunction = dog => ({
  map: f => DogFunction(f(dog));
});
const walk = isRaining => dog => ({
  ...dog, // if there are some other fields
  color: isRaining || dog.color === 'dirty' ? 'dirty' : dog.color,
  needToWash: dog.needToWash || isRaining,
});
const belka = DogFunction({ color: 'white', needToWash: false });
const belkaAfterWalking = belka
  .map(walk())
  .map(walk(true))
  .map(walk());
// belka didn't mutate: { color: 'white', needToWash: false }
// belkaAfterWalking: { color: 'dirty', needToWash: true }

DogFunction can have a "walk" method but it is more OOP way. Compare how different it is comparing to the previous more abstract example:

const DogFunction = dog => ({
  walk: isRaining => DogFunction({
    ...dog, // if there are some other fields
    color: isRaining || dog.color === 'dirty' ? 'dirty' : dog.color,
    needToWash: dog.needToWash || isRaining,
  }),
const belkaAfterWalking = belka
  .walk()
  .walk(true)
  .walk();
// belka didn't mutate: { color: 'white', needToWash: false }
// belkaAfterWalking: { color: 'dirty', needToWash: true }
});

Still no mutations in between. FP and OOP can be similar only in very simple examples when mutations haven't joined the game.

Yes I mentioned this in the post as well

The question which we haven't touched is a mutation.

Code of Conduct Report abuse