00:15 | <jschoi> | In the spec, is there a way to split an abstract List into a first element and another List of the other elements? |
00:16 | <jschoi> | “Let «first, ...rest» be list”… |
00:16 | <bakkot> | Nope |
00:18 | <jschoi> | I’ll just say, “Let rest be the List of all elements of list except its first.” |
00:20 | <bakkot> | If you own the list, you could just mutate it |
00:21 | <jschoi> | Well, how would I express that in spec language? |
00:21 | <jschoi> | It’d still be prose, right? |
00:21 | <bakkot> | i. Let r be the first element of remaining. ii. Remove the first element from remaining. |
00:21 | <jschoi> | Ah… |
00:21 | <bakkot> | or |
00:21 | <bakkot> | ii. Let kValue be the first element of values and remove that element from values. |
00:21 | <jschoi> | Nice. Thank you! |
00:22 | <bakkot> | Which thing are you writing that needs this? For bigint math I'd think you could just copy the Number ones |
00:23 | <jschoi> | Math.hypot . Killing Math.bigHypot and merging its behavior into hypot . |
00:23 | <jschoi> | Dispatching on the type of the first argument. |
00:24 | <bakkot> | Math.hypot just iterates over the list; that seems better than splitting it |
00:24 | <jschoi> | Well, it needs to coerce the rest of the arguments based on the first argument’s type, though. |
00:28 | <jschoi> | https://github.com/js-choi/proposal-bigint-math/commit/b5ece4e1543c35375f13f02653c0a7119ed0c495 |
00:29 | <bakkot> | Yeah but you don't need to take the tail of the list for that. I'd do something like
etc |
00:29 | <bakkot> | there's other ways you can write it but none of them obviously require you to construct the list-except-head |
00:29 | <bakkot> | just to peek at the head to determine which coercer to use |
00:31 | <jschoi> | Wouldn’t that cause an unnecessary call to ToBigInt or ToNumber for the first element? |
00:31 | <bakkot> | Type() does not perform coercion, no |
00:32 | <bakkot> | Though, I guess you probably want ToNumeric? |
00:32 | <jschoi> | I mean ToBigInt, though. It’s calling ToBigInt on args[0] unnecessarily. |
00:32 | <bakkot> | Yeah but that's unobservable |
00:32 | <jschoi> | Oh, yeah, right, ugh, I forgot that I need to call ToNumeric on the first. |
00:32 | <jschoi> | If we’re fine with unobservable redundant calls the spec, I can change it. |
00:33 | <bakkot> | If that makes the algorithm easier to read, absolutely. |
00:40 | <jschoi> | https://github.com/js-choi/proposal-bigint-math/commit/32152ba671e6b94e9912139db5b3a31e35ad9021 |
00:40 | <jschoi> | Thanks for the help, bakkot! |
00:42 | <jschoi> | …Though would it work with Math.hypot(Object(4n)) ? |
00:42 | <jschoi> | Wouldn’t the Type(args[0]) return Object? |
00:43 | <bakkot> | Right, that's why I suggested ToNumeric |
00:43 | <jschoi> | Ah, ah. |
00:45 | <jschoi> | So we’re fine with just replacing it with Type(ToNumeric(args[0])), because the extra coercion is invisible to the user. |
00:45 | <bakkot> | Well, no, that ends up being visible, unfortunately |
00:45 | <jschoi> | Ah… |
00:46 | <bakkot> | So you do probably want to pop the list after all, I'm afraid |
00:46 | <bakkot> | I hadn't thought through the fact that you'd want to ToNumeric before doing the Type |
00:46 | <jschoi> | Thanks for the big help anyway, though. 👍️ |
00:54 | <jschoi> | I wonder if ToPrimitive would work… |
14:36 | <jschoi> | Could someone familiar with TypeScript type inference explain the problem being described in https://github.com/js-choi/proposal-hack-pipes/issues/18 ? I’m not sure why the type of userOption |> map(user => user.name)(^) cannot be inferred from userOption and map . |
14:37 | <jschoi> | It’s just the same as map(user => user.name)(userOption) , after all… |
14:53 | <devsnek> | does anyone else keep getting surprised that optional chaining doesn't work with assignment |
14:58 | <devsnek> | jschoi: i think they mean this https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABAWwIYAcA8AVANIgVQD4AKYALkRIDdLsBKRAXiMPspNToG0BdRloT6IA3gChEkxACcAplBDSkNVABsQsgM49+zVtTUbNAOjToy9ANxiAvmLEQEmqIlTTpqAJ7NE3EQCNKAEYbXmszEk4BVlRjf3pOdy8rIA |
14:58 | <devsnek> | i'd say that's just a dumb limitation of TS though, and you can manually annotate it, so i don't think it matters |
15:04 | <jschoi> | Huh, I see. So the problem is that TypeScript cannot infer the type of even map(user => user.name)(userOption) …but, apparently, somehow it can infer the types in pipe(userOption, map(user => user.name)) ? 🤔 |
15:05 | <devsnek> | yeah for some reason it doesn't unify the types in the former case |
15:05 | <devsnek> | personally i'd say its probably just better for microsoft to fix that |
15:08 | <jschoi> | I wonder if the TypeScript team has tried adding that inference but there’s a fundamental reason why they can’t, hmm. Anyways, thanks for help! |
15:09 | <devsnek> | its weird cuz its not really even an inference, it's just unifying unknown and {b: number} :/ |
15:16 | <jschoi> | jschoi: i think they mean this https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABAWwIYAcA8AVANIgVQD4AKYALkRIDdLsBKRAXiMPspNToG0BdRloT6IA3gChEkxACcAplBDSkNVABsQsgM49+zVtTUbNAOjToy9ANxiAvmLEQEmqIlTTpqAJ7NE3EQCNKAEYbXmszEk4BVlRjf3pOdy8rIA |
15:16 | <devsnek> | sure |
15:19 | <jschoi> | Hm, maybe it’s a fundamental limitation of how TypeScript’s “type inference works left to right”. |
15:21 | <jschoi> | Perhaps in map(user => user.name)(userOption) it can’t unify the types of user and userOption because…I don’t know, maybe it’s somehow unidirectional, it expects a type right away in that arrow function, and it eagerly throws an error right there before moving onto (userOption) ? I wonder how solvable this would be for the TypeScript team, but having to use pipe functions seems like a pretty brittle way to work around it. |
15:41 | <jschoi> | Hmmm. https://github.com/microsoft/TypeScript/issues/15680 https://github.com/microsoft/TypeScript/issues/25826 https://github.com/microsoft/TypeScript/issues/30134 |
17:09 | <TabAtkins> | Okay yeah sounds like it's just "we don't actually unify types, just do some inference tricks that fail in a lot of cases", but I'm still confused why pipe(val, map(user=>user.name)) infers properly. |
17:19 | <devsnek> | tsc continues to befuddle me |
17:20 | <devsnek> | TabAtkins: it seems to just be the order in which the graph is visited, one of those issues has an example of changing the order of arguments breaking inference |
17:23 | <TabAtkins> | Yeah, seems like there's some special-casing thrown around to address some cases. If this becomes a big issue, I suspect TypeScript can special-case "trailing (^) in a pipe body" and make it work like we'd expect, even without full inference. |
17:33 | <devsnek> | apparently the swc person is writing a new typescript type checker |
17:33 | <devsnek> | maybe it can handle this properly |
18:56 | <bakkot> | we should make let { #x: a } = foo work, to mean let a = foo.#x : y/n? |
18:57 | <bakkot> | I have seeded the emoji reacts so you can more easily just click on the appropriate one to express your opinion |
18:57 | <TabAtkins> | Tho let {#x} = foo; would still not work, right? |
18:59 | <bakkot> | yup |
18:59 | <bakkot> | or at least I am not proposing to allow it, and I think it should not work |
19:47 | <Domenic> | My personal opinion is that renaming while destructuring is generally distasteful, so I am not voting. (I.e. I think let x = y.z is clearer than let { z: x } = y .) |
19:53 | <devsnek> | i vote for whatever increases the number of productions in the spec |