-1

One of the paradigms of functional programming is object composition which should be favoured over class inheritance.

When acting on an object you often need to know if a certain method is available on the object. While a class uses the is a approach, object composition has the can do approach.

With class inheritance you would do a simple obj instanceof class check to satisfy the is a approach.

However, my question is how to do a proper can do?

Of course I can check if something is present on the object with if(obj.method != null) but what do you do, when you get handed objects were you cannot be sure, that someone added their own stuff to it (maybe accidentially adding a method with the same name)?.

Mulan
  • 129,518
  • 31
  • 228
  • 259
Fuzzyma
  • 7,619
  • 6
  • 28
  • 60
  • "When acting on an object you often need to know if a certain method is available on the object." Not often. Usually you know the (base) type of object so you already know that the method in question is available. Of course there are always exceptions, but in general I'd say this is a design smell. – Thomas May 28 '18 at 17:33
  • Nothing you can do if some other code overwrites a property other than fix whatever allows such a thing to happen. This whole question seems far too abstract – charlietfl May 28 '18 at 17:33
  • To what extent or strictness are you trying to verify the method? If you always want to call a particular method, you don't necessarily have to trust the object – [`.call()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call). On the other hand, allowing the object to provide its own can be rather effective – [duck typing](https://stackoverflow.com/questions/4205130/what-is-duck-typing), e.g. [thenables and Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve). – Jonathan Lonowski May 28 '18 at 17:38
  • In my case a method accepts multiple types of objects. I think thats where the "smell" begins. However, in my case its a case of comfort for the user of the library – Fuzzyma May 28 '18 at 17:41
  • 3
    You're asking about functional programming but everything you describe comes from OOP... – Mulan May 28 '18 at 17:58
  • "One of the paradigms of functional programming is object composition" Functional programming doesn't really have much a concept of objects. – sepp2k May 28 '18 at 18:12

2 Answers2

1

I'll say it again here in my answer: you're asking about functional programming but everything you describe comes from OOP.

In general, you don't ask what objects can do in functional programming. Instead, you have known functions that are capable of operating on known input types and return known output types.

Some first order functions

const add = (x, y) =>
  x + y

const mult = (x, y) => 
  x * y

First order data abstraction, a rational number module

const rational = (numer, denom) =>
  [ numer, denom ]

const numerator = r =>
  r [0]

const denominator = r =>
  r [1]

We can add functions to the module

const string_of_rational = r =>
  `(${numerator (r)} / ${denominator (r)})` 

const add_rational = (r1, r2) =>
  rational
    ( add ( mult ( numerator (r1)
                 , denominator (r2)
                 )
          , mult ( numerator (r2)
                 , denominator (r1)
                 )
          )
    , mult ( denominator (r1)
           , denominator (r2)
           )
    )

An example program using our module

const a = rational (1, 2)
const b = rational (1, 4)
const c = add_rational (a, b)
console.log (string_of_rational (c))
// (1 / 2) + (1 / 4) = 
//=> (6 / 8)

Data abstraction is important because it preserves our program's functionality even if the underlying representation of data changes.

Above, we used a simple array [] to store the two values for our rational numbers. We can use a different implementation if we wanted

const rational = (numer, denom) =>
  ({ numer, denom })

const numerator = r =>
  r.numer

const denominator = r =>
  r.denom

And our program still works

const a = rational (1, 2)
const b = rational (1, 4)
const c = add_rational (a, b)
console.log (string_of_rational (c))
// (1 / 2) + (1 / 4) = 
//=> (6 / 8)

It's up to you how to package and implement your modules. In this example, we have all the functions related to our rational numbers in a file called rational.js

// import whatever you need from your module,
// and make sure the module exports it!
const { make, add, string_of } = require ('./rational')

// our program works the same
const a = make (1, 2)
const b = make (1, 4)
const c = add (a, b)
console.log (string_of (c))
// (1 / 2) + (1 / 4) = 
//=> (6 / 8)

I recommend Structure and Interpretation of Computer Programs, 2nd edition by Gerald Jay Sussman and Harold Abelson. It will teach you what is most important about functional programming, the function. This book will give you a strong foundation to work your way through the more advanced concepts in any functional language.

Mulan
  • 129,518
  • 31
  • 228
  • 259
-1

Interesting question. Simple solution would be to add __composedOf__ property (simirlarly to __proto__ property) that would store array of functions that took part in object creation. Something like this

https://codepen.io/grebre0/pen/MXgXYP?editors=0010

disstruct
  • 673
  • 3
  • 8