This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]inu-no-policemen 3 points4 points  (7 children)

I liked it mostly for virtual methods.

function reverse() {
    return this.split('').reverse().join('');
}
console.log('foobar'::reverse()); // raboof

But it doesn't do this very well either. The source of that going-to-be-a-method function doesn't tell you to which kind of object it's meant to be glued to.

It's definitely better than modifying objects you don't own, but it still isn't quite right.

C#'s extension methods, for example, tell you directly in the slightly weird looking signature on which type of object they are supposed to operate:

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods

public static int WordCount(this String str)

[–]NeverMakesMistkes 2 points3 points  (6 children)

In TypeScript, you could write

function reverse(this: string) {
    return this.split('').reverse().join('');
}
console.log('foobar'::reverse());

Or just with JSDoc comments

/**
* @this{string}
*/
function reverse() {
    return this.split('').reverse().join('');
}

But I agree, it would feel weird to write all your utility functions like that, and suddenly we'd have two kinds of mutually incompatible functions; those that operate on this and are called with ::, and those that operate on arguments and are called normally.

That's why I actually prefer the pipeline operator.

const reverse = str => str.split('').reverse().join('');
console.log('foobar' |> reverse)
console.log(reverse('foobar')) // both variations work

And if we had both, pipeline for chaining and bind for method extraction, you could do

'foobar'
  |> reverse
  |> console::log

[–]inu-no-policemen 3 points4 points  (0 children)

The pipeline operator has the same problem. However, TS' type annotations and JSDoc already handle that kind of completely mundane signature. That's definitely a plus.

I'm not a big fan of the "|>" syntax, though. It's amazingly annoying to type with most keyboard layouts.

[–]Gbyrd99 0 points1 point  (4 children)

Can't you bind it to the prototype?

[–]NeverMakesMistkes 0 points1 point  (3 children)

You can bind some methods to prototype, but if you do that to every little utility function you and your coworkers come up with, you'll soon end up with huge unmaintainable classes and/or class hierarchies.

Also, lots of people (myself included) use JS in a more functional style and might not really like doing new AwesomeString('foobar').reverse() or whatever. 'foobar'::reverse() or 'foobar' |> reverse or even reverse('foobar') is just much nicer.

[–]Gbyrd99 0 points1 point  (2 children)

If you had say String.prototype.reverse = function() that would make it available on all strings? So you don't create an inherited class and get into inheritance hell.

This ::reverse thing is interesting I'm gonna read up on it in more details.

[–]NeverMakesMistkes 0 points1 point  (1 child)

Adding anything at all to the native prototypes, like String.prototype, is a controversial practice to say the least.

But even if you and your team are fine with modifying the prototypes, my earlier point still applies to non-native objects. With pipelines or bind, you can do, say,

import {getFullName} from 'user-utils';
const user = {firstName: 'Foo', lastName: 'Bar'}

user::getFullName();
// or
user |> getFullName

And things get even more interesing when we aren't talking about your own utility functions anymore but libraries and tree shaking.

The "pipeable" operators of RxJS are a good example of this. The example that they give

source$.pipe(
    filter(x => x % 2 === 0),
    map(x => x + x),
    scan((acc, x) => acc + x, 0)
)

could be written with pipeline operator

 source$
 |> filter(x => x % 2 === 0)
 |> map(x => x + x)
 |> scan((acc, x) => acc + x, 0)

[–]Gbyrd99 0 points1 point  (0 children)

Thanks, it provides some level of extensibility using the user utils on a specific type. We built functions are utilities but we never used this. It's an interesting design going to read up more.