extends null

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

extends null

Axel Rauschmayer
If I’m reading the latest spec draft correctly then

```js
class C extends null {
}
```

produces the following result:

1. Constructor kind: derived
2. Prototype of `C`: `Function.prototype`
3. Prototype of `C.prototype`: `null`

Neither #2 nor #3 seems very useful:

* #2 means that a super-constructor call is allowed but throws an exception, because `Function.prototype` is not constructible. The default constructor will perform a super-constructor call. As a result, you are forced to explicitly return an object from the constructor if you don’t want an exception to be thrown.

* #3 means that the constructor doesn’t even create objects whose prototype is `null`, but objects whose prototype is an object whose prototype is `null`.

Therefore my question: is this useful for anything? Can’t `extends null` be turned into something useful? Even treating `extends null` as equivalent to a missing `extends` clause seems preferable.

Thanks!

Axel

-- 
Dr. Axel Rauschmayer
[hidden email]
rauschma.de




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: extends null

Mark S. Miller-2
No, the problem is that 

class C extends X {

when X turns out to be null must be an error along exactly these lines. Everywhere else in the language where X is accepted as an expression evaluated to a value, if X evaluates to null, this is the same thing as placing null in that position. Consider:


const NULL = null; // C nostalgia

class C extends NULL {


It would be awful for this to be different than

class C extends null {


If you really want to write a class whose prototype.__proto__ is null, imperatively make it so after the class declaration. We don't need to compromise the consistency of the language to make this rare case less ugly.




On Sat, Feb 14, 2015 at 12:52 PM, Axel Rauschmayer <[hidden email]> wrote:
If I’m reading the latest spec draft correctly then

```js
class C extends null {
}
```

produces the following result:

1. Constructor kind: derived
2. Prototype of `C`: `Function.prototype`
3. Prototype of `C.prototype`: `null`

Neither #2 nor #3 seems very useful:

* #2 means that a super-constructor call is allowed but throws an exception, because `Function.prototype` is not constructible. The default constructor will perform a super-constructor call. As a result, you are forced to explicitly return an object from the constructor if you don’t want an exception to be thrown.

* #3 means that the constructor doesn’t even create objects whose prototype is `null`, but objects whose prototype is an object whose prototype is `null`.

Therefore my question: is this useful for anything? Can’t `extends null` be turned into something useful? Even treating `extends null` as equivalent to a missing `extends` clause seems preferable.

Thanks!

Axel

-- 
Dr. Axel Rauschmayer
[hidden email]
rauschma.de




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss




--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: extends null

Axel Rauschmayer
But it’s not an error! Either of the following two classes fail later, when you instantiate them, but not right away.

```js
const X = null;
class C extends X {}

class D extends null {}
```

I’m arguing that both produce weird constructors. I’d much prefer an early error. Or dynamically switching from "derived" to "base" (but you seem to be saying that doing this dynamically is not a good idea).


On 14 Feb 2015, at 22:05, Mark S. Miller <[hidden email]> wrote:

No, the problem is that 

class C extends X {

when X turns out to be null must be an error along exactly these lines. Everywhere else in the language where X is accepted as an expression evaluated to a value, if X evaluates to null, this is the same thing as placing null in that position. Consider:


const NULL = null; // C nostalgia

class C extends NULL {


It would be awful for this to be different than

class C extends null {


If you really want to write a class whose prototype.__proto__ is null, imperatively make it so after the class declaration. We don't need to compromise the consistency of the language to make this rare case less ugly.




On Sat, Feb 14, 2015 at 12:52 PM, Axel Rauschmayer <[hidden email]> wrote:
If I’m reading the latest spec draft correctly then

```js
class C extends null {
}
```

produces the following result:

1. Constructor kind: derived
2. Prototype of `C`: `Function.prototype`
3. Prototype of `C.prototype`: `null`

Neither #2 nor #3 seems very useful:

* #2 means that a super-constructor call is allowed but throws an exception, because `Function.prototype` is not constructible. The default constructor will perform a super-constructor call. As a result, you are forced to explicitly return an object from the constructor if you don’t want an exception to be thrown.

* #3 means that the constructor doesn’t even create objects whose prototype is `null`, but objects whose prototype is an object whose prototype is `null`.

Therefore my question: is this useful for anything? Can’t `extends null` be turned into something useful? Even treating `extends null` as equivalent to a missing `extends` clause seems preferable.

Thanks!

Axel

-- 
Dr. Axel Rauschmayer
[hidden email]
rauschma.de




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: extends null

Mark S. Miller-2
On Sat, Feb 14, 2015 at 1:21 PM, Axel Rauschmayer <[hidden email]> wrote:
But it’s not an error! Either of the following two classes fail later, when you instantiate them, but not right away.

```js
const X = null;
class C extends X {}

class D extends null {}
```

I didn't mean to imply an early error. The "extends X" can only produce a dynamic error, so I'm arguing that "extends null" should do the same.

 

I’m arguing that both produce weird constructors. I’d much prefer an early error.

You can't know early that X is null.

 
Or dynamically switching from "derived" to "base" (but you seem to be saying that doing this dynamically is not a good idea).

Dynamically switching from derived to base does not work, because our super semantics depends statically on the difference.


 


On 14 Feb 2015, at 22:05, Mark S. Miller <[hidden email]> wrote:

No, the problem is that 

class C extends X {

when X turns out to be null must be an error along exactly these lines. Everywhere else in the language where X is accepted as an expression evaluated to a value, if X evaluates to null, this is the same thing as placing null in that position. Consider:


const NULL = null; // C nostalgia

class C extends NULL {


It would be awful for this to be different than

class C extends null {


If you really want to write a class whose prototype.__proto__ is null, imperatively make it so after the class declaration. We don't need to compromise the consistency of the language to make this rare case less ugly.




On Sat, Feb 14, 2015 at 12:52 PM, Axel Rauschmayer <[hidden email]> wrote:
If I’m reading the latest spec draft correctly then

```js
class C extends null {
}
```

produces the following result:

1. Constructor kind: derived
2. Prototype of `C`: `Function.prototype`
3. Prototype of `C.prototype`: `null`

Neither #2 nor #3 seems very useful:

* #2 means that a super-constructor call is allowed but throws an exception, because `Function.prototype` is not constructible. The default constructor will perform a super-constructor call. As a result, you are forced to explicitly return an object from the constructor if you don’t want an exception to be thrown.

* #3 means that the constructor doesn’t even create objects whose prototype is `null`, but objects whose prototype is an object whose prototype is `null`.

Therefore my question: is this useful for anything? Can’t `extends null` be turned into something useful? Even treating `extends null` as equivalent to a missing `extends` clause seems preferable.

Thanks!

Axel

-- 
Dr. Axel Rauschmayer
[hidden email]
rauschma.de






--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: extends null

Axel Rauschmayer

On 14 Feb 2015, at 22:26, Mark S. Miller <[hidden email]> wrote:

On Sat, Feb 14, 2015 at 1:21 PM, Axel Rauschmayer <[hidden email]> wrote:
But it’s not an error! Either of the following two classes fail later, when you instantiate them, but not right away.

```js
const X = null;
class C extends X {}

class D extends null {}
```

I didn't mean to imply an early error. The "extends X" can only produce a dynamic error, so I'm arguing that "extends null" should do the same.

When I say “early”, I don’t mean “static”, I mean: dynamically, when the class definition is evaluated, not later when the class is instantiated via `new`.

I’m not seeing a dynamic error in the spec when the `extends` clause is null (step 6e): https://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-classdefinitionevaluation



Or dynamically switching from "derived" to "base" (but you seem to be saying that doing this dynamically is not a good idea).

Dynamically switching from derived to base does not work, because our super semantics depends statically on the difference.

Ah, checked statically, I wasn’t aware! Hadn’t found the check beforehand. Searched some more and it is indeed there, in 14.5.1.

-- 
Dr. Axel Rauschmayer
[hidden email]
rauschma.de




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: extends null

Mark S. Miller-2
On Sat, Feb 14, 2015 at 1:45 PM, Axel Rauschmayer <[hidden email]> wrote:

On 14 Feb 2015, at 22:26, Mark S. Miller <[hidden email]> wrote:

On Sat, Feb 14, 2015 at 1:21 PM, Axel Rauschmayer <[hidden email]> wrote:
But it’s not an error! Either of the following two classes fail later, when you instantiate them, but not right away.

```js
const X = null;
class C extends X {}

class D extends null {}
```

I didn't mean to imply an early error. The "extends X" can only produce a dynamic error, so I'm arguing that "extends null" should do the same.

When I say “early”, I don’t mean “static”, I mean: dynamically, when the class definition is evaluated, not later when the class is instantiated via `new`.

I’m not seeing a dynamic error in the spec when the `extends` clause is null (step 6e): https://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-classdefinitionevaluation


That's a good suggestion. AFAICT, it would be an improvement. I don't see any downside. 

Allen?

 


Or dynamically switching from "derived" to "base" (but you seem to be saying that doing this dynamically is not a good idea).

Dynamically switching from derived to base does not work, because our super semantics depends statically on the difference.

Ah, checked statically, I wasn’t aware! Hadn’t found the check beforehand. Searched some more and it is indeed there, in 14.5.1.

-- 
Dr. Axel Rauschmayer
[hidden email]
rauschma.de






--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: extends null

Erik Arvidsson
Making it a dynamic error at class definition time to extend null would work but the motivation for not doing that was that someone might want to create a class that has a {__proto__: null} prototype. Personally, I would be fine with saying that this case is so rare that it would be better to have that dynamic error at class definition time.

On Sat Feb 14 2015 at 4:52:40 PM Mark S. Miller <[hidden email]> wrote:
On Sat, Feb 14, 2015 at 1:45 PM, Axel Rauschmayer <[hidden email]> wrote:

On 14 Feb 2015, at 22:26, Mark S. Miller <[hidden email]> wrote:

On Sat, Feb 14, 2015 at 1:21 PM, Axel Rauschmayer <[hidden email]> wrote:
But it’s not an error! Either of the following two classes fail later, when you instantiate them, but not right away.

```js
const X = null;
class C extends X {}

class D extends null {}
```

I didn't mean to imply an early error. The "extends X" can only produce a dynamic error, so I'm arguing that "extends null" should do the same.

When I say “early”, I don’t mean “static”, I mean: dynamically, when the class definition is evaluated, not later when the class is instantiated via `new`.

I’m not seeing a dynamic error in the spec when the `extends` clause is null (step 6e): https://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-classdefinitionevaluation


That's a good suggestion. AFAICT, it would be an improvement. I don't see any downside. 

Allen?

 


Or dynamically switching from "derived" to "base" (but you seem to be saying that doing this dynamically is not a good idea).

Dynamically switching from derived to base does not work, because our super semantics depends statically on the difference.

Ah, checked statically, I wasn’t aware! Hadn’t found the check beforehand. Searched some more and it is indeed there, in 14.5.1.

-- 
Dr. Axel Rauschmayer
[hidden email]
rauschma.de






--
    Cheers,
    --MarkM
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: extends null

Axel Rauschmayer
Making it a dynamic error at class definition time to extend null would work but the motivation for not doing that was that someone might want to create a class that has a {__proto__: null} prototype. Personally, I would be fine with saying that this case is so rare that it would be better to have that dynamic error at class definition time.

Interesting. I have never seen this pattern and don’t see what it could be good for. Thus, a dynamic error at class definition time sounds good to me.

-- 
Dr. Axel Rauschmayer
[hidden email]
rauschma.de




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: extends null

Kevin Smith

Interesting. I have never seen this pattern and don’t see what it could be good for. Thus, a dynamic error at class definition time sounds good to me.

The purpose would be defining a class whose instances don't have Object.prototype on their prototype chain.  If "extends null" doesn't work, then I think you'd have to do something like this to achieve the same?

    function NullBase() {}
    NullBase.prototype = Object.create(null);

    class C extends NullBase {}


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: extends null

Mark S. Miller-2


On Sun, Feb 15, 2015 at 11:01 AM, Kevin Smith <[hidden email]> wrote:

Interesting. I have never seen this pattern and don’t see what it could be good for. Thus, a dynamic error at class definition time sounds good to me.

The purpose would be defining a class whose instances don't have Object.prototype on their prototype chain.  If "extends null" doesn't work, then I think you'd have to do something like this to achieve the same?

    function NullBase() {}
    NullBase.prototype = Object.create(null);

    class C extends NullBase {}


That still wouldn't work at runtime because of the super semantics of C as a derived class. Instead


class C {....}

C.prototype.__proto__ = null;

Yes, it is ugly, but it is an odd case, so still obeys Kay's dictum:


"Simple things should be simple. Complex things should be possible"
    --Alan Kay





--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: extends null

Jordan Harband
Rather than making "extends null" alone a runtime error at class evaluation time, is there a reason not to instead, make only a reference to "super" in the constructor of a class that extends null be a runtime error at class evaluation time?

On Sun, Feb 15, 2015 at 11:12 AM, Mark S. Miller <[hidden email]> wrote:


On Sun, Feb 15, 2015 at 11:01 AM, Kevin Smith <[hidden email]> wrote:

Interesting. I have never seen this pattern and don’t see what it could be good for. Thus, a dynamic error at class definition time sounds good to me.

The purpose would be defining a class whose instances don't have Object.prototype on their prototype chain.  If "extends null" doesn't work, then I think you'd have to do something like this to achieve the same?

    function NullBase() {}
    NullBase.prototype = Object.create(null);

    class C extends NullBase {}


That still wouldn't work at runtime because of the super semantics of C as a derived class. Instead


class C {....}

C.prototype.__proto__ = null;

Yes, it is ugly, but it is an odd case, so still obeys Kay's dictum:


"Simple things should be simple. Complex things should be possible"
    --Alan Kay





--
    Cheers,
    --MarkM

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: extends null

Marius Gundersen

>>> The purpose would be defining a class whose instances don't have Object.prototype on their prototype chain.  If "extends null" doesn't work, then I think you'd have to do something like this to achieve the same?
>>>
>>>     function NullBase() {}
>>>     NullBase.prototype = Object.create(null);
>>>
>>>     class C extends NullBase {}
>>>

Can't this be solved by returning a null object from the constructor?

```js
class Null{
  constructor() {
    return Object.create(null);
}
}

class MyClass extends Null{
 
}
let foo = new MyClass();
foo.toString() //ReferenceError
```

Marius Gundersen


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: extends null

Erik Arvidsson
In reply to this post by Axel Rauschmayer

No that would not work either. You want an object that has its [[Prototype]] set to MyClass.prototype.


On Mon, Feb 16, 2015, 02:55 Marius Gundersen <[hidden email]> wrote:

>>> The purpose would be defining a class whose instances don't have Object.prototype on their prototype chain.  If "extends null" doesn't work, then I think you'd have to do something like this to achieve the same?
>>>
>>>     function NullBase() {}
>>>     NullBase.prototype = Object.create(null);
>>>
>>>     class C extends NullBase {}
>>>

Can't this be solved by returning a null object from the constructor?

```js
class Null{
  constructor() {
    return Object.create(null);
}
}

class MyClass extends Null{
 
}
let foo = new MyClass();
foo.toString() //ReferenceError
```

Marius Gundersen


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: extends null

Isiah Meadows
In reply to this post by Axel Rauschmayer

Couldn't one of these be enough?

```js
var Null = {prototype: {__proto__: null}};
var Null = {prototype: Object.create(null)};

class Foo extends Null {}
```


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss