On Sun, Jan 27, 2019 at 10:46 PM Ranando King <[email protected]> wrote:
> 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);
> }
> }
> ```
>
Can't you just use a function object?
function UserCreator(repository) {
if( !(this instanceof UserCreator ) ) return new
UserCreator(repostiory);
var creator = function xyz(name) {
return { repo: repository, user: name }
}:
creator.repository = repository;
creator.create = creator
return creator;
}
>
> Now `new UserCreator(someRepo)(someName)` is the same as `new
> UserCreator(someRepo).create(someName)`.
>
both of the above also work that way.
>
> On Sun, Jan 27, 2019 at 11:35 PM Jordan Harband <[email protected]> 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 <[email protected]> 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
>>> [email protected]
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>> _______________________________________________
>> es-discuss mailing list
>> [email protected]
>> https://mail.mozilla.org/listinfo/es-discuss
>>
> _______________________________________________
> es-discuss mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/es-discuss
>
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss