Cascade annotation or Chaining methods

Abstract

A useful and clean way to wrap functions that return void, allowing to chain multiple operations.

Current implementation

Often we find ourselves having to call multiple void methods on the same object and consider the state changes between the steps.
In other cases an operation may return a value other than the underlying object, disallowing chaining operations, or assigning the changed value to a variable.

I will use the Array prototype to demonstrate the functionality, but it can be more pronounce in custom objects (especially in data analysis and fintech).
Consider the following example:

const plants = ['broccoli', 'cauliflower', 'cabbage','tomato'];

plants.push('kale'); // returned value is the length of the array

plants.shift(); // returns the removed element ( or undefined) 

plants.sort(); // will return the sorted array

plants.pop(); // like `shift` - it will returned the removed element

Proposal

Borrowing the operator from Dart, I propose using a new double-dot operator (..) to wrap a method and return an instance of the underlying object rather than the return from the function.

Transforming our code above to :

const plants = ['broccoli', 'cauliflower', 'cabbage','tomato'];

plants
  ..push('kale')
  ..shift()
  ..sort()
  ..pop()

Chaining or cascading annotation will result in a more readable code, and will tightly couple sequential operations.

2 Likes

Same as:

['broccoli', 'cauliflower', 'cabbage','tomato']
    .concat('kale')
    .slice(1)
    .sort()
    .pop();

your code will return "tomato" (pop returns the popped element).
But it doesn't matter, my example is not strong enough but the logic still stands.

It will be mostly useful for custom built classes / functions.
We often find ourselves having to work with existing code with functions that mutate data and return an object other than the underlying object (see pop() above)

Here's an example (silly one, I will try to come up with a better one when it's not so late ):

class myClass { 
  counter =0 ;
  func() { 
     counter ++ ;
  }

    func2 () {
        counter -- ;
    }
}

const obj = new myClass() ;

const result = obj..func()..func2()..func()..func();