16:21 | <bendtherules> | Why does Math.pow not handle bigint type? |
16:28 | <bakkot_> | bendtherules: a general concern about overloading; see https://github.com/tc39/proposal-bigint/issues/197#issuecomment-467941106 |
16:40 | <bendtherules> | bakkot_: got it. |
18:14 | <devsnek> | it would be nice if super could be used in normal function expressions |
18:15 | <devsnek> | like when you're trying to override a method in a hacky way |
18:17 | <bakkot_> | I think that would make more sense if we didn't have the whole [[HomeObject]] thing |
18:17 | <bakkot_> | (a thing for which I've never entirely understood the motivation, tbh) |
18:17 | <devsnek> | more magic is always good right? |
18:17 | <bakkot_> | :( |
18:17 | <bakkot_> | I have a slide in an internal talk I've been writing which contains only the words "Magic Is Bad" |
18:18 | <devsnek> | lol |
18:18 | <devsnek> | maybe its time to overhaul classes |
18:18 | <devsnek> | *in a web compatible way* |
18:18 | <bakkot_> | super also works in object literals |
18:18 | <bakkot_> | well, super property access, anyway |
18:18 | <devsnek> | huh |
18:18 | <bakkot_> | this would be vastly more useful if `__proto__` weren't considered a bad pattern |
18:19 | <bakkot_> | maybe that's a problem with what is considered a bad pattern, though |
18:19 | <devsnek> | you can use super in method definitions |
18:19 | <devsnek> | in object literals |
18:20 | <bakkot_> | right, it's just that the super is going to be Object.prototype unless you've mutated the proto after the fact or have used `__proto__` in the initial literal |
18:21 | <bakkot_> | and both of the "unless" things are usually frowned upon |
18:21 | <bakkot_> | so having syntax which is only useful if you do frowned-upon things or for some reason want to access properties of Object.prototype is... weird |
18:23 | <devsnek> | i don't think people generally frown on __proto__ in literals |
18:24 | <bakkot_> | hm, maybe. I don't see it used much, certainly |
18:25 | <bakkot_> | we shouldn't've put it in annex b if we were expecting it to continue to be good practice |
18:34 | <devsnek> | `{ a: 1 } with null` |
19:44 | <bradleymeck> | bakkot_: thanks for the write up. I'm not sure I understand/agree with it still but it seems to give a clear idea. I do have some replies to each point though. |
19:44 | <bradleymeck> | per 1: Mainly it seems that the idea of "is-a" simply cannot be applied to classes that have null prototypes is a claim. So that would mean they are not describable in general? If they are not describable as being a thing that seems odd in its own. |
19:46 | <bradleymeck> | per 2: it starts with the claim extends `null` is the same as no heritage, which is partially the debate (missing heritage doesn't dynamic delegate / uses Object not `null`) so I'm unclear on why that is being treated as given. |
19:46 | <bradleymeck> | per 3: this explanation doesn't seem to be rooted in anything? |
19:47 | <bradleymeck> | 4 is derived from 2 and 3 which seems ok, but it doesn't seem to follow through. it relies on the model of 2 and 3 as being intuitive and given which both of them seem confusing to me at least on first few reads |
19:49 | <bradleymeck> | I think a key framing is "think of instances of this class as also being instances of any other, broader class." as being the pre-requisite for *allowing* the idea super to be considered |
19:49 | <bradleymeck> | to me, super() doesn't actual tie to a specific class / concrete thing to call and does some really magical stuff if taken in isolation |
19:50 | <bradleymeck> | it seems, to you super() is being tied to some concrete thing to call and that a class must exist but I'm not clear on why it is concrete nor why it must directly exist |
19:51 | <bradleymeck> | i think we can reason about what is sensical/non-sensical to frame our side whichever way in retrospective we want on a personal level |
19:51 | <bradleymeck> | but to me I'm unclear on why super() is being stated as inherently non-sensical |
19:52 | <bradleymeck> | i'd agree super.foo() is non-sensical, it is requesting a specific thing to be delegated, but it is unclear why super() is |
19:58 | <bakkot_> | bradleymeck: will write up responses so I can post them all at once, one sec |
20:00 | <bradleymeck> | bakkot_: i will state that to me this is seeming very much towards trying to make things fit with a mental model and not about learnability/debuggability/refactorability/consistency which the more i think on those the more i think even if it doesn't 100% a mental model it would be preferable to require it |
20:01 | <bradleymeck> | i'm just unclear on what the downside of requiring it is concretely besides the extra characters |
20:01 | <bradleymeck> | and that falls down to i'm unclear on why a "baseclass calling super() |
20:01 | <bradleymeck> | "baseclass" |
20:01 | <bradleymeck> | must mean errors |
20:09 | <bradleymeck> | i do see things like having a constructor body be usable for both a base and subclass as a boon, syntax does hint on if something is requires, matching every other heritage (including Object) requires calling super() even if it errors, etc. |
20:09 | <bradleymeck> | required* |
20:10 | <bradleymeck> | but the explanation is kind of heady so far |
20:10 | <ljharb> | oof, that was a long one |
20:11 | <ljharb> | bakkot_: how does “super installs calls fields” play into your gist? |
20:11 | <ljharb> | *class fields |
20:14 | <bradleymeck> | ljharb: ? what does that mean when there is no heritage? |
20:17 | <ljharb> | bradleymeck: `super()` first invokes the superclass, and then installs the *current class*’s public and private fields |
20:17 | <bakkot_> | bradleymeck: https://gist.github.com/bakkot/8ca6db3b995d55f3b6886a5be87d0f38 |
20:17 | <bakkot_> | ljharb I haven't said anything about fields? I'm not sure what you're asking. |
20:17 | <ljharb> | bradleymeck: so on a `class extends null`, either 1) `super()` would install that class’s fields, or 2) `this` would be automatically available and the fields would be installed prior to the constructor running |
20:17 | <ljharb> | bakkot_: right |
20:17 | <ljharb> | bakkot_: your gist says “this is what super *does*" |
20:18 | <ljharb> | bakkot_: but it doesn’t mention class fields |
20:18 | <ljharb> | bakkot_: so i’m asking you how your mental model adjusts to the other thing super does. |
20:18 | <ljharb> | ie, the thing that has nothing to do with a class hierarchy |
20:19 | <bakkot_> | I would not say that `super()` installs fields; I would say that the class constructor does this itself as soon as `super()` has provided the object onto which the fields should be installed |
20:19 | <rkirsling> | ^ |
20:21 | <ljharb> | i mean, i type `super()` and if i don’t, the class fields don’t get installed |
20:21 | <ljharb> | surely the class mechanics might be doing it, but that’s not the constructor. but thanks, i think that answers my mental model question |
20:21 | <bradleymeck> | bakkot_: I'd state c.) that your conclusions doesn't mesh with the terminology not that I reject either the terminology or conclusion itself. in particular i don't understand the terminology of super/sub class since not having a class above in the hierarchy seems to be confounded by things ` class X {} ` being treated as a base class but it does inherit from Object and that super() is tied to a concrete thing |
20:22 | <bradleymeck> | > Specifically, to me, super is a reification of the relationship between classes discussed above - hence the name - and does not make sense in the absence of such a relationship. |
20:22 | <bradleymeck> | this is interesting to me since it doubles down again on a concrete/direct relationship rather than what to me appears to be an indirect relationship |
20:23 | <bradleymeck> | > [Breaking this OOP mental] is a very significant cost. |
20:23 | <bradleymeck> | can you clarify this |
20:24 | <bradleymeck> | i think the mental model simply doesn't mesh with reality and thats causing me troubles |
20:24 | <bradleymeck> | since things with a superclass are being treated as non-subclasses in discussions |
20:26 | <bradleymeck> | and things with a heritage (or lack of in the case of null) are being asserted that the heritage cannot be considered an is-a relationship indirectly in the same way that `extends Foo` can while `extends Foo` doesn't actually assert things being a `Foo` |
20:26 | <bakkot_> | re: "`class X {} ` being treated as a base class but it does inherit from Object": the point is that I am talking only about how I mentally organize my code. It happens to be the case that every instance of `class {}` inherits from Object, in Javascript's mechanics (and Java's for that matter), but this is a mechanical fact about the implementation of `class` in the language rather than a reflection of a relationship I am |
20:26 | <bakkot_> | specifically intending or thinking about wrt the structure of my program. |
20:26 | <bradleymeck> | i think if we had used a different token than `class` this discussion would be less interesting |
20:26 | <bradleymeck> | bakkot_: right, and that is confusing to me |
20:27 | <bradleymeck> | because these claims are not matching reality nor claiming to enhance actual programs themselves |
20:27 | <bradleymeck> | so i'm not sure what is being argued for and why |
20:27 | <bakkot_> | um. |
20:27 | <bradleymeck> | i see the terms, but the terms are being given as if they are truths somehow and parts of those are confusing me |
20:28 | <bakkot_> | I guess I have not thus far explicitly made the claim that the ability to think about the structure of my programs and have that be reflected by the programs themselves is valuable, so let me explicitly say that now. |
20:28 | <bradleymeck> | bakkot_: sure, but now thats much more subjective |
20:28 | <bakkot_> | This is all subjective, yes. |
20:28 | <bradleymeck> | yes, but in degrees |
20:29 | <bakkot_> | I don't think this is very subjective, as these things go. |
20:29 | <rkirsling> | subjective except that the write-up above has gone to lengths to ensure that it reflects the most basic concepts of OOP |
20:29 | <rkirsling> | the ones from which it would be disingenuous to diverge and still use a keyword like `class` |
20:29 | <bradleymeck> | rkirsling: in my OOP courses in college/high school we didn't have these rigid models |
20:30 | <devsnek> | somewhat objectively, the default for `extends` is `Object` |
20:30 | <bradleymeck> | i did understand that a subclass inherits |
20:30 | <bradleymeck> | but the definition of a base class in these recent talks is all over the place |
20:31 | <bradleymeck> | i think there is a desire for omission to be treated like a base class and acknowledgement that it is not reality, but to treat an explicit value (null) as a base class even if it has a heritage |
20:32 | <bradleymeck> | i don't understand the actual benefit of the desire |
20:32 | <bakkot_> | I don't know what "that is not reality" means there |
20:32 | <bakkot_> | it is a base class |
20:32 | <bradleymeck> | bakkot_: it inherits |
20:32 | <bradleymeck> | you get .toString etc |
20:32 | <bakkot_> | that is not the definition I am using! |
20:32 | <bakkot_> | I was very careful with my definitions! |
20:33 | <bradleymeck> | bakkot_: i think your definitions are confusing to me as I've stated |
20:33 | <bakkot_> | hm |
20:33 | <bakkot_> | I don't know how to get past that |
20:33 | <ljharb> | i also think that if you’re arguing a more broad concept of class heritage, “a subclass inherits from a base class” is a part of it |
20:33 | <ljharb> | there’s no class hierarchy without inheritance |
20:33 | <bakkot_> | these are things which are, to me, extremely bedrock foundational principles of OOP |
20:34 | <ljharb> | and JS isn’t merely an OOP language, it’s multi-paradigm |
20:34 | <ljharb> | which is why there’s a number of language semantics that don’t mesh with those principles |
20:34 | <ljharb> | and obv it’s totally fine to pick and choose the semantics you care about for your own mental model |
20:34 | <bradleymeck> | bakkot_: i was explained OOP and we did state that base/sub/super classes as terms, but in languages where everything is a delegation (recursive object root type) you can't have a base class for example |
20:35 | <bradleymeck> | it seems there is a sub/super relationship mental model difference as part of the issue |
20:36 | <bradleymeck> | and the sub/super are the same for those? it simply doesn't make sense to try and force those terms there |
20:37 | <bakkot_> | `super` is the term the language already uses |
20:37 | <bakkot_> | we are debating the semantics of a token literally spelled `super()` |
20:38 | <bradleymeck> | bakkot_: sure, seems fine to call the language to perform super() steps even if there isn't a super to me? |
20:38 | <bradleymeck> | super() steps to me are indirect not a concrete/direct thing |
20:38 | <ljharb> | if we’re talking about literal spelling, then we can’t really ignore the presence of `extends` |
20:39 | <ljharb> | iow either the concrete syntax is important, or else it would be the same discussion of super was spelled `init()` |
20:39 | <ljharb> | *if |
20:39 | <bradleymeck> | super() is extremely confusing in general and I can't easily think of it as a generic function call |
20:39 | <bakkot_> | ljharb I read "extends null" as "extends nothing", i.e. "does not extend anything", i.e. "is a base class" |
20:39 | <bakkot_> | none of that seems inconsistent with anything I've said |
20:39 | <ljharb> | that is clear, which suggests that `class {}` is not a base class |
20:39 | <bradleymeck> | bakkot_: is the same true for extends undefined? |
20:39 | <ljharb> | because it doesn’t extend nothing |
20:40 | <bakkot_> | ljharb `class {}` also does not extend anything |
20:40 | <bakkot_> | so... no? |
20:40 | <ljharb> | and yet, it inherits from Object, which is the same thing |
20:40 | <bradleymeck> | bakkot_: I'd very strongly it does |
20:40 | <bradleymeck> | argue* |
20:40 | <ljharb> | “x extends y” to me is a statement both about the syntax and about the runtime behavior |
20:40 | <bradleymeck> | java/ruby classes extend object by default even if you omit the clause |
20:40 | <ljharb> | i suppose the weird part is that `class { }` doesn’t already have a null proto |
20:41 | <bakkot_> | ljharb as I said above, several times, it is an interesting mechanical fact that the resulting objects have `Object.prototype` in their prototype chain, but this has very little to do with the relationships between structures I am thinking about when organizing my program, which is the thing I actually care about |
20:41 | <rkirsling> | perhaps the oddity here is that `class`, `extends`, and `super` are all familiar from class inheritance but "null proto" is inherently prototypal |
20:42 | <ljharb> | bakkot_: i find it strange that you’d think about how your program is organized when defining classes but not when using them |
20:42 | <bakkot_> | ... what? |
20:42 | <ljharb> | rkirsling: yes, i 1000% agree that all the spellings in `class` are terrible because they evoke a classical inheritance mindset :-) but that ship has sailed |
20:42 | <rkirsling> | well I didn't mean that so much as like |
20:42 | <bakkot_> | ljharb I have no idea how you got that from anything I said |
20:42 | <ljharb> | bakkot_: “has Object.prototype in their prototype chain” is part of how your class instances are organized |
20:43 | <ljharb> | bakkot_: it’s not just a mechanical fact, it’s a core part of the organization of your instances. |
20:43 | <rkirsling> | we're having a hard time because the goal isn't to instantiate a non-Object |
20:44 | <bakkot_> | ljharb "is represented by electricity moving through silicons" is a part of how my classes are implemented, but that is still not an organizing principle which I keep in mind most of the the time when designing the implementation of a class |
20:44 | <ljharb> | lol ok fair |
20:44 | <rkirsling> | so like, `extends Object` might be default but even with null proto we're not trying to instantiate something that can't hold properties |
20:44 | <ljharb> | but i'd think the runtime behavior of your instances *is* something you keep in mind when designing the implementation of a class |
20:44 | <ljharb> | like “is this a prototype method or a static method" |
20:44 | <ljharb> | or “what instance methods will this have from its prototype chain" |
20:45 | <rkirsling> | hence maybe `extends null` could be called dangerous if that phrasing inherently mixes worlds |
20:45 | <bakkot_> | the fact that an object has Object.prototype in its prototype chain is virtually never relevant to the organization of my code |
20:45 | <bakkot_> | other prototypes which I have explicitly put in the proto chain are |
20:46 | <bradleymeck> | bakkot_: but that doesn't match reflection utilities in other languages either |
20:46 | <ljharb> | there’s a bunch of coding styles where that’s true, sure |
20:46 | <bradleymeck> | ruby // class A; end # A.superclass => Object |
20:46 | <ljharb> | but if you’re using your instance as a dictionary, or using `instanceof Object` anywhere, it matters |
20:46 | <bradleymeck> | pythong: class Foo: \n pass \n issubclass(object, Foo) => true |
20:47 | <bradleymeck> | same for java/etc. |
20:47 | <bakkot_> | ljharb I am not using my `class {}` instances as dictionaries |
20:47 | <ljharb> | bakkot_: i understand that, but that isn’t something universally true |
20:47 | <ljharb> | i’ve seen lots of (bad) code that does `Object.assign(this, opts)` or similar |
20:47 | <bradleymeck> | and you can still use super.toString even if you don't have an extends clause right? |
20:48 | <ljharb> | i don’t do it in my own code either, but i’m not *unaware* of the existing of Object.prototype; if i were, i wouldn’t want extends null in the first place |
20:48 | <ljharb> | *existence |
20:48 | <bradleymeck> | ljharb: i feel called out |
20:48 | <bakkot_> | yes, this is a claim about how people tend to reason about their code. it is about abstractions. obviously all abstractions can break down in some cases: `+ 1` does not actually "add one" in the mathematical sense, because of integer overflow, but I still claim that is how one typically thinks about what that code doeos |
20:48 | <ljharb> | bradleymeck: yes, `(new class { x() { return super.toString(); } }).toString()` works as expected |
20:49 | <ljharb> | bradleymeck: `(new class { constructor() { return Object.create(null); } x() { return super.toString(); } }).x()` throws tho |
20:49 | <ljharb> | (oops, s/.toString/.x` in my first example, same result) |
20:49 | <bradleymeck> | well yes because you replaced the result ;-p |
20:50 | <ljharb> | i'm pretty sure it'd work if i also installed the `x` method onto the null object |
21:02 | <bradleymeck> | ljharb: thats because super is tied to its scope not the the call though I thought |
21:10 | <ljharb> | bradleymeck: i believe that’s right |
22:03 | <devsnek> | ljharb: am i a member of the editors team on GH? every time you request a review from it I get a notification saying you requested a review from me |
22:03 | <ljharb> | um, not that i'm aware |
22:03 | <ljharb> | let me check |
22:04 | <devsnek> | https://usercontent.irccloud-cdn.com/file/Z5AMMh92/Screenshot_20200708-170413.jpg |
22:04 | <ljharb> | devsnek: you aren't; it might be a weird github bug since you've commented on the pr |
22:05 | <devsnek> | perhaps |
22:05 | <ljharb> | i request the editors team to review a *lot* of PRs |
22:05 | <devsnek> | I've noticed :D |