Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Binding new? #25

Closed
dead-claudia opened this issue Sep 17, 2015 · 9 comments
Closed

Binding new? #25

dead-claudia opened this issue Sep 17, 2015 · 9 comments

Comments

@dead-claudia
Copy link
Contributor

The current syntax seems like it would work well with auto-binding constructors as well. Java also has a version for this, with its Class::new shorthand. The same thing could be very useful for JavaScript as well, since classes can't be instantiated without new.

class Foo {
  constructor(value) { this.value = value }
}

const foos = args.map(Foo::new)
const foos = args.map(value => new Foo(value))

Only incidentally, I'm suggesting a very similar syntax. Since new is a keyword in all contexts, it couldn't possibly be an identifier for a bound function, so it would work very well.

As for the suggested semantics, expr::new should function identically to the following when called:

function exprCreate() {
  return Reflect.construct(expr, arguments)
}

More specific semantics:

Syntax:

BindExpression[Yield] :
    LeftHandSideExpression[?Yield] :: `new`

Runtime Semantics: BoundConstructorCreate(target, boundArgs)

  1. Assert: Type(target) is Object.
  2. Assert: IsConstructible(target) is true.
  3. Let proto be target.[GetPrototypeOf].
  4. ReturnIfAbrupt(proto).
  5. Let obj be a newly created object.
  6. Set obj’s essential internal methods to the default ordinary object definitions specified in 9.1.
  7. Set the [[Call]] internal method of obj to the [[Construct]] internal method implementation as described in 9.4.1.2.
  8. Set the [[Construct]] internal method of obj as described in 9.4.1.2.
  9. Set the [[Prototype]] internal slot of obj to proto.
  10. Set the [[Extensible]] internal slot of obj to true.
  11. Set the [[BoundTargetFunction]] internal slot of obj to targetFunction.
  12. Set the [[BoundThis]] internal slot of obj to null.
  13. Set the [[BoundArguments]] internal slot of obj to an empty List.
  14. Return obj.

Note: This is equivalent BoundFunctionCreate(target, null, empty List) where target is always a constructor, but with the exception that [[Call]] and [[Construct]] have the same implementation.

Runtime Semantics:

BindExpression :
    LeftHandSideExpression :: `new`
  1. Let targetReference be the result of evaluating LeftHandSideExpression.
  2. Let target be GetValue(targetReference).
  3. ReturnIfAbrupt(target).
  4. If IsConstructor(target) is false, throw a TypeError exception.
  5. Return BoundConstructorCreate(target, boundArgs).
@dead-claudia dead-claudia changed the title Binding constructors? Binding new? Sep 17, 2015
@benjamingr
Copy link

This could be a sweet addition. Being able to new things is useful (and is useful in Java 8 too).

@zenparsing
Copy link
Member

Thanks @IMPinball !

After @dtinth brought up Java method references over in #18, I considered this as well.

I think it would make a lot of sense provided that we split up this proposal into separate "method extraction" and "pipelining" operators. This would fit right in with a method extraction operator.

console::log; // => (...args) => console.log(...args) // or something like that
Array::new; // =>  (...args) => new Array(...args) // or something like that

@ssube
Copy link

ssube commented Sep 17, 2015

👍 Referencing new (and methods) like this is super useful and pairs well with classes, especially when deserializing.

@zenparsing
Copy link
Member

@ssube "deserializing"? Can you explain?

@ssube
Copy link

ssube commented Sep 17, 2015

@zenparsing Instantiating classes with data, like xhr.get('example.com/books').then(JSON::parse).then(books => books.map(Book::new)).

@zenparsing
Copy link
Member

@ssube Gotcha.

@dead-claudia
Copy link
Contributor Author

See #26.

@Fenzland
Copy link

Rather than request to new syntax, we can just implement it under current frame.

class Foo {}

Foo.new( 'foo' );
array.map( Foo.new );
'foo' |> Foo.new;

Before proposal goes, we can just only do prototype modification to implement it.

Reflect.defineProperty( Function.prototype, 'new', {
	get(){
		const newer= ( ...args )=> new this( ...args, );
		
		Reflect.defineProperty( newer, 'length', { value:this.length, }, );
		Reflect.defineProperty( newer, 'name', { value:`${this.name}.new`, }, );
		
		return newer;
	},
}, );

@dead-claudia
Copy link
Contributor Author

Could you please not resurrect an issue closed 4 years ago for this? It's not helpful and I'd rather not deal with any more notification spam than I have to.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants