RE: Proposal: Default object method

2019-01-27 Thread Ron Buckton
There’s nothing in that proposal says that an object with a `Symbol.apply` has 
to have a different `typeof`. It *would* mean that any Call might require 
additional dispatch which could have performance implications. It could also be 
an approach to support “callable” classes:

```js
class Foo {
  constructor() { /* constructor behavior */ }
  static [Symbol.apply]() { /* call behavior */ }
}
```

From: es-discuss  On Behalf Of Jordan Harband
Sent: Sunday, January 27, 2019 9:35 PM
To: Brasten Sager 
Cc: es-discuss 
Subject: Re: Proposal: Default object method

Something that can be invoked has a `[[Call]]` slot, and is `typeof` "function".

Adding a Symbol that makes something callable would have a number of effects - 
it would make `typeof` (one of the most robust operations in the language) 
unsafe, because it would have to access the Symbol method, which could be a 
throwing getter (or even one that just logs how many typeofs are called on it). 
Additionally, it would mean any object could become callable, and any function 
could be made *un* callable.

This seems like a pretty large change, solely to avoid "classes with a single 
method", which arguably should just be a function in the first place.

On Sun, Jan 27, 2019 at 4:05 PM Brasten Sager 
mailto:bras...@brasten.me>> wrote:
Apologies if this has been raised before. I was unable to locate anything 
similar.

Any thoughts or ideas on this proposal would be appreciated!

Original: 
https://gist.github.com/brasten/f87b9bb470973dd5ee9de0760f1c81c7

-Brasten

—

# Proposal: Default object method #

Objects w/ default method can be invoked like a function.

## Problem ##

Objects that are well constrained (single responsibility)
can tend to end up with a single method, or at least a single method
that is important to most consumers. These methods tend to be named
by either verbing the class name (eg. `UserCreator.create()`) or with
some generic `handle` / `perform` / `doTheObviousThing`.

Whatever the name, downstream consumers of the object end up coupled to
two implementation details:

   1) this thing-doer is an object and not a function
   2) this thing-doer's doing method is called `X`

### Example ###

Here we are going to create an object that can be used to
create a user later. Note that downstream consumers will only
care that this object does one thing: create a user. While it
make have other methods eventually for use in some limited
contexts, creating a user is its primary (and often sole-)
responsibility.

```js
class UserCreator {
  constructor(repository) {
this.repository = repository;
  }

  create(name) {
 return this.repository.createUser(name);
  }
}

const userCreator = new UserCreator(userRepository);
```

At this point, the `userCreator` is just a single-method object.
It is useful for injecting into other objects that may need to
create a user. But the fact that the `userCreator` is an object
with a single useful method is an implementation detail to which
consumers become coupled.

```js

// Consumer of `userCreator`. Although this could itself be a
// good example of a "UserCreator"-like object (due to `.handle()`).
//
class UserSignupHandler {
  constructor(userCreator) {
this.userCreator = userCreator;
  }

  handle(userName) {
// UserSignupHandler is aware of ".create" when it really doesn't have to 
be.
//
return this.userCreator.create(userName);
  }
}

const handler = new UserSignupHandler(userCreator);
```

Notably, if we were to change the implementation of UserCreator later to be
a pure function, we would have to change all consumers of UserCreator when
conceptually it shouldn't be needed. There is still a thing-doer that has
the same input/output.


## Proposed Solution ##

An object instance can have a default method. This would allow an
object to be "invoked" exactly like a function, hiding the implementation
detail from consumers.

Note that there are several ways to define how the default method is
determined, and this proposal is less concerned with this aspect than with
what it looks like to invoke the object. We will demonstrate an option here,
but alternatives are welcome.

```js
// This particular implementataion would use a Symbol.
//

class UserCreator {
  constructor(repository) {
this.repository = repository;
  }

  [Symbol.apply](name) {
 return this.repository.createUser(name);
  }
}

const userCreator = new UserCreator(userRepository);

class UserSignupHandler {
  constructor(userCreator) {
// NOTE: at the consumer, it almost makes more sense to
// name these with action verbs, as is done here.
//
this.createUser = userCreator;
  }

  

Re: Proposal: Default object method

2019-01-27 Thread Ranando King
Jordan's right. This one is best handled by a function. But if there is
some reason you need to create callable objects, it's still doable, even
with ES as-is. Just extend your classes from something like this:

```js
class Callable {
   constructor(defaultFn) {
  return (...args) => { return defaultFn.call(this, ...args); };
   }
}
```
Any class extending this will have instances that are functions. So using
your UserCreator class...

```js
class UserCreator extends Callable {
  constructor(repository) {
super(this.create);
this.repository = repository;
  }

  create(name) {
 return this.repository.createUser(name);
  }
}
```

Now `new UserCreator(someRepo)(someName)` is the same as `new
UserCreator(someRepo).create(someName)`.

On Sun, Jan 27, 2019 at 11:35 PM Jordan Harband  wrote:

> Something that can be invoked has a `[[Call]]` slot, and is `typeof`
> "function".
>
> Adding a Symbol that makes something callable would have a number of
> effects - it would make `typeof` (one of the most robust operations in the
> language) unsafe, because it would have to access the Symbol method, which
> could be a throwing getter (or even one that just logs how many typeofs are
> called on it). Additionally, it would mean any object could become
> callable, and any function could be made *un* callable.
>
> This seems like a pretty large change, solely to avoid "classes with a
> single method", which arguably should just be a function in the first place.
>
> On Sun, Jan 27, 2019 at 4:05 PM Brasten Sager  wrote:
>
>> Apologies if this has been raised before. I was unable to locate anything
>> similar.
>>
>> Any thoughts or ideas on this proposal would be appreciated!
>>
>> Original:
>> https://gist.github.com/brasten/f87b9bb470973dd5ee9de0760f1c81c7
>>
>> -Brasten
>>
>> —
>>
>> # Proposal: Default object method #
>>
>> Objects w/ default method can be invoked like a function.
>>
>> ## Problem ##
>>
>> Objects that are well constrained (single responsibility)
>> can tend to end up with a single method, or at least a single method
>> that is important to most consumers. These methods tend to be named
>> by either verbing the class name (eg. `UserCreator.create()`) or with
>> some generic `handle` / `perform` / `doTheObviousThing`.
>>
>> Whatever the name, downstream consumers of the object end up coupled to
>> two implementation details:
>>
>>1) this thing-doer is an object and not a function
>>2) this thing-doer's doing method is called `X`
>>
>> ### Example ###
>>
>> Here we are going to create an object that can be used to
>> create a user later. Note that downstream consumers will only
>> care that this object does one thing: create a user. While it
>> make have other methods eventually for use in some limited
>> contexts, creating a user is its primary (and often sole-)
>> responsibility.
>>
>> ```js
>> class UserCreator {
>>   constructor(repository) {
>> this.repository = repository;
>>   }
>>
>>   create(name) {
>>  return this.repository.createUser(name);
>>   }
>> }
>>
>> const userCreator = new UserCreator(userRepository);
>> ```
>>
>> At this point, the `userCreator` is just a single-method object.
>> It is useful for injecting into other objects that may need to
>> create a user. But the fact that the `userCreator` is an object
>> with a single useful method is an implementation detail to which
>> consumers become coupled.
>>
>> ```js
>>
>> // Consumer of `userCreator`. Although this could itself be a
>> // good example of a "UserCreator"-like object (due to `.handle()`).
>> //
>> class UserSignupHandler {
>>   constructor(userCreator) {
>> this.userCreator = userCreator;
>>   }
>>
>>   handle(userName) {
>> // UserSignupHandler is aware of ".create" when it really doesn't
>> have to be.
>> //
>> return this.userCreator.create(userName);
>>   }
>> }
>>
>> const handler = new UserSignupHandler(userCreator);
>> ```
>>
>> Notably, if we were to change the implementation of UserCreator later to
>> be
>> a pure function, we would have to change all consumers of UserCreator when
>> conceptually it shouldn't be needed. There is still a thing-doer that has
>> the same input/output.
>>
>>
>> ## Proposed Solution ##
>>
>> An object instance can have a default method. This would allow an
>> object to be "invoked" exactly like a function, hiding the implementation
>> detail from consumers.
>>
>> Note that there are several ways to define how the default method is
>> determined, and this proposal is less concerned with this aspect than with
>> what it looks like to invoke the object. We will demonstrate an option
>> here,
>> but alternatives are welcome.
>>
>> ```js
>> // This particular implementataion would use a Symbol.
>> //
>>
>> class UserCreator {
>>   constructor(repository) {
>> this.repository = repository;
>>   }
>>
>>   [Symbol.apply](name) {
>>  return this.repository.createUser(name);
>>   }
>> }
>>
>> const userCreator = new 

Re: Proposal: Default object method

2019-01-27 Thread Jordan Harband
Something that can be invoked has a `[[Call]]` slot, and is `typeof`
"function".

Adding a Symbol that makes something callable would have a number of
effects - it would make `typeof` (one of the most robust operations in the
language) unsafe, because it would have to access the Symbol method, which
could be a throwing getter (or even one that just logs how many typeofs are
called on it). Additionally, it would mean any object could become
callable, and any function could be made *un* callable.

This seems like a pretty large change, solely to avoid "classes with a
single method", which arguably should just be a function in the first place.

On Sun, Jan 27, 2019 at 4:05 PM Brasten Sager  wrote:

> Apologies if this has been raised before. I was unable to locate anything
> similar.
>
> Any thoughts or ideas on this proposal would be appreciated!
>
> Original: https://gist.github.com/brasten/f87b9bb470973dd5ee9de0760f1c81c7
>
> -Brasten
>
> —
>
> # Proposal: Default object method #
>
> Objects w/ default method can be invoked like a function.
>
> ## Problem ##
>
> Objects that are well constrained (single responsibility)
> can tend to end up with a single method, or at least a single method
> that is important to most consumers. These methods tend to be named
> by either verbing the class name (eg. `UserCreator.create()`) or with
> some generic `handle` / `perform` / `doTheObviousThing`.
>
> Whatever the name, downstream consumers of the object end up coupled to
> two implementation details:
>
>1) this thing-doer is an object and not a function
>2) this thing-doer's doing method is called `X`
>
> ### Example ###
>
> Here we are going to create an object that can be used to
> create a user later. Note that downstream consumers will only
> care that this object does one thing: create a user. While it
> make have other methods eventually for use in some limited
> contexts, creating a user is its primary (and often sole-)
> responsibility.
>
> ```js
> class UserCreator {
>   constructor(repository) {
> this.repository = repository;
>   }
>
>   create(name) {
>  return this.repository.createUser(name);
>   }
> }
>
> const userCreator = new UserCreator(userRepository);
> ```
>
> At this point, the `userCreator` is just a single-method object.
> It is useful for injecting into other objects that may need to
> create a user. But the fact that the `userCreator` is an object
> with a single useful method is an implementation detail to which
> consumers become coupled.
>
> ```js
>
> // Consumer of `userCreator`. Although this could itself be a
> // good example of a "UserCreator"-like object (due to `.handle()`).
> //
> class UserSignupHandler {
>   constructor(userCreator) {
> this.userCreator = userCreator;
>   }
>
>   handle(userName) {
> // UserSignupHandler is aware of ".create" when it really doesn't have
> to be.
> //
> return this.userCreator.create(userName);
>   }
> }
>
> const handler = new UserSignupHandler(userCreator);
> ```
>
> Notably, if we were to change the implementation of UserCreator later to
> be
> a pure function, we would have to change all consumers of UserCreator when
> conceptually it shouldn't be needed. There is still a thing-doer that has
> the same input/output.
>
>
> ## Proposed Solution ##
>
> An object instance can have a default method. This would allow an
> object to be "invoked" exactly like a function, hiding the implementation
> detail from consumers.
>
> Note that there are several ways to define how the default method is
> determined, and this proposal is less concerned with this aspect than with
> what it looks like to invoke the object. We will demonstrate an option
> here,
> but alternatives are welcome.
>
> ```js
> // This particular implementataion would use a Symbol.
> //
>
> class UserCreator {
>   constructor(repository) {
> this.repository = repository;
>   }
>
>   [Symbol.apply](name) {
>  return this.repository.createUser(name);
>   }
> }
>
> const userCreator = new UserCreator(userRepository);
>
> class UserSignupHandler {
>   constructor(userCreator) {
> // NOTE: at the consumer, it almost makes more sense to
> // name these with action verbs, as is done here.
> //
> this.createUser = userCreator;
>   }
>
>   handle(userName) {
> // UserSignupHandler is no longer coupled to the implementation
> details it doesn't need.
> //
> return this.createUser(userName);
>   }
> }
>
> const handler = new UserSignupHandler(userCreator);
> ```
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Proposal: Default object method

2019-01-27 Thread Brasten Sager
Apologies if this has been raised before. I was unable to locate anything 
similar.

Any thoughts or ideas on this proposal would be appreciated!

Original: https://gist.github.com/brasten/f87b9bb470973dd5ee9de0760f1c81c7 


-Brasten

—

# Proposal: Default object method #

Objects w/ default method can be invoked like a function.

## Problem ##

Objects that are well constrained (single responsibility)
can tend to end up with a single method, or at least a single method
that is important to most consumers. These methods tend to be named
by either verbing the class name (eg. `UserCreator.create()`) or with
some generic `handle` / `perform` / `doTheObviousThing`.

Whatever the name, downstream consumers of the object end up coupled to
two implementation details: 

   1) this thing-doer is an object and not a function
   2) this thing-doer's doing method is called `X`

### Example ###

Here we are going to create an object that can be used to
create a user later. Note that downstream consumers will only
care that this object does one thing: create a user. While it
make have other methods eventually for use in some limited
contexts, creating a user is its primary (and often sole-)
responsibility.

```js
class UserCreator {
  constructor(repository) {
this.repository = repository; 
  }

  create(name) {
 return this.repository.createUser(name);
  }  
}

const userCreator = new UserCreator(userRepository);
```

At this point, the `userCreator` is just a single-method object.
It is useful for injecting into other objects that may need to 
create a user. But the fact that the `userCreator` is an object
with a single useful method is an implementation detail to which
consumers become coupled.

```js

// Consumer of `userCreator`. Although this could itself be a
// good example of a "UserCreator"-like object (due to `.handle()`).
//
class UserSignupHandler {
  constructor(userCreator) {
this.userCreator = userCreator;
  }
  
  handle(userName) {
// UserSignupHandler is aware of ".create" when it really doesn't have to 
be.
//
return this.userCreator.create(userName);
  }
}

const handler = new UserSignupHandler(userCreator);
```

Notably, if we were to change the implementation of UserCreator later to be 
a pure function, we would have to change all consumers of UserCreator when
conceptually it shouldn't be needed. There is still a thing-doer that has
the same input/output.


## Proposed Solution ##

An object instance can have a default method. This would allow an
object to be "invoked" exactly like a function, hiding the implementation
detail from consumers.

Note that there are several ways to define how the default method is
determined, and this proposal is less concerned with this aspect than with
what it looks like to invoke the object. We will demonstrate an option here,
but alternatives are welcome.

```js
// This particular implementataion would use a Symbol.
//

class UserCreator {
  constructor(repository) {
this.repository = repository; 
  }

  [Symbol.apply](name) {
 return this.repository.createUser(name);
  }  
}

const userCreator = new UserCreator(userRepository);

class UserSignupHandler {
  constructor(userCreator) {
// NOTE: at the consumer, it almost makes more sense to
// name these with action verbs, as is done here.
//
this.createUser = userCreator;
  }
  
  handle(userName) {
// UserSignupHandler is no longer coupled to the implementation details it 
doesn't need.
//
return this.createUser(userName);
  }
}

const handler = new UserSignupHandler(userCreator);
```

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Native Assertions

2019-01-27 Thread Michael Haufe
Good to know that has moved forward, but it is still minimally relevant due
to the other points raised.

Also as an FYI the following paper from OOPSLA 2018:

Collapsible Contracts: Fixing a Pathology of Gradual Typing

https://www.eecs.northwestern.edu/~robby/pubs/papers/oopsla2018-fgsfs.pdf



On Sun, Jan 27, 2019 at 6:50 AM Sebastian Zartner <
sebastianzart...@gmail.com> wrote:

> console.assert is standardized by the WHATWG at
> https://console.spec.whatwg.org/#assert.
>
> Sebastian
>
> On Mon, 14 Jan 2019 at 12:39, Michael Haufe 
> wrote:
>
>> console.assert is not standardized at this point, nor is it part of the
>> language. Additionally, the semantics are inappropriate for the required
>> use cases.
>>
>> To requote the relevant part from the linked thread:
>>
>> 1. AssertionError <: Error
>> 2. assert(x === 12); // throws an AssertionError with a default error
>> message
>> 3. assert(x === 12, "twelve, supposedly") // throws an AssertionError
>> with the given error message
>>
>> console.assert does not throw and its intent is not the same. The assert
>> I'm referring to is related to Code Contracts. Therefore your reference is
>> seemingly orthogonal.
>>
>> /Michael
>>
>> On Sun, Jan 13, 2019, 12:49 Cyril Auburtin > wrote:
>>
>>> There's `console.assert`
>>>
>>> also check
>>> https://github.com/michaelficarra/proposal-first-class-protocols/issues/27#issuecomment-386975099
>>>
>>>
>>> On Sun, Dec 16, 2018 at 10:01 PM Michael Haufe 
>>> wrote:
>>>
 Seven years ago there was discussion around standardizing "assert". Has
 there been any movement on this since then?

 https://esdiscuss.org/topic/native-assertion-module


 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

>>> ___
>>> es-discuss mailing list
>>> es-discuss@mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>> ___
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Native Assertions

2019-01-27 Thread Sebastian Zartner
console.assert is standardized by the WHATWG at
https://console.spec.whatwg.org/#assert.

Sebastian

On Mon, 14 Jan 2019 at 12:39, Michael Haufe  wrote:

> console.assert is not standardized at this point, nor is it part of the
> language. Additionally, the semantics are inappropriate for the required
> use cases.
>
> To requote the relevant part from the linked thread:
>
> 1. AssertionError <: Error
> 2. assert(x === 12); // throws an AssertionError with a default error
> message
> 3. assert(x === 12, "twelve, supposedly") // throws an AssertionError with
> the given error message
>
> console.assert does not throw and its intent is not the same. The assert
> I'm referring to is related to Code Contracts. Therefore your reference is
> seemingly orthogonal.
>
> /Michael
>
> On Sun, Jan 13, 2019, 12:49 Cyril Auburtin  wrote:
>
>> There's `console.assert`
>>
>> also check
>> https://github.com/michaelficarra/proposal-first-class-protocols/issues/27#issuecomment-386975099
>>
>>
>> On Sun, Dec 16, 2018 at 10:01 PM Michael Haufe 
>> wrote:
>>
>>> Seven years ago there was discussion around standardizing "assert". Has
>>> there been any movement on this since then?
>>>
>>> https://esdiscuss.org/topic/native-assertion-module
>>>
>>>
>>> ___
>>> es-discuss mailing list
>>> es-discuss@mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>> ___
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss