09:02 | <Jack Works> |
Is it missing a [+UnicodeSetsMode] version of those 2 production? otherwise I cannot find a way to parse |
10:26 | <jmdyck> | In the spec, +UnicodeSetsMode only occurs in conjunction with +UnicodeMode . (i.e., roughly, +USM implies +UM , or +USM is a subset of +UM ), so any RHS guarded by [+UM] 'succeeds' for all cases of +USM . |
10:26 | <jmdyck> | I think. |
11:08 | <Jack Works> | oh, I checked all Pattern, all Pattern[+USM] is also marked as [+UM] |
11:29 | <jmdyck> | yup |
17:25 | <bakkot> | I want to make a proposal for a method for finding the item in an iterable which has the largest value according to some function, for example "find the person with the largest age" or whatever. This comes up a lot IME, enough to be worth having in the standard library even though it's like a four or five lines to do with a loop or There's two natural ways to do this: either take a function from input items to a number, or take a comparator. both work, first is often more convenient, second is strictly more general. Thoughts? We could in principle support both. (Even in the same function, just by switching on |
17:28 | <bakkot> | I suppose one way to solve the dilemma is to have a function which lifts a T -> number mapper to a (T, T) -> { -1, 0, 1 } comparator, and expect people to use that, as in people.maxByComparator(Compare.by(person -> person.age)) . |
17:28 | <bakkot> | (java calls the latter operation Comparator.comparing ) |
17:35 | <Michael Ficarra> | Isn't this the same API design question we had with uniqueBy ? You can either give a mapper or a comparator, and we probably just want both. |
17:36 | <Michael Ficarra> | wouldn't this be less efficient? |
17:36 | <bakkot> | Pretty similar, yeah, although the "comparator" for uniqueBy is not a comparator in the sense of "a function which can be passed to .sort ", whereas it is here |
17:37 | <bakkot> | same big-O, but requires computing 2x as many calls of the T -> number function, yes |
17:39 | <bakkot> | I actually am kind of coming around to the idea of switching on the .length of the callback |
18:07 | <Ashley Claymore> | A comparator for unique has to compare against all previous unique values. O(N^2) A comparator for largest only has to compare against the current winner. O(N) |
18:08 | <Ashley Claymore> | This does sound useful. I currently reach for `.sort(c).at(-1)` when in a pinch |
18:10 | <eemeli> | Effectively, this would be sugar for something like this, yes?
|
18:17 | <eemeli> | Isn't that good enough for this use case? |
18:23 | <bakkot> | I mean, isn't a for loop good enough for this use case? |
18:23 | <Ashley Claymore> | Reduce has the "empty list" exception which is annoying IMO |
18:23 | <Ashley Claymore> | for a winner like method I'd rather an empty set returns undefined as the winner |
18:25 | <bakkot> | reduce is basically the same kind of hammer as a for loop. Personally I like it when the language provides common, simple operations even when they're already achievable with the language's existing general purpose tools. |
18:25 | <bakkot> | ehhhhh no I was definitely planning on proposing this where it's an exception if you call it on an empty list |
18:25 | <Ashley Claymore> | https://es.discourse.group/t/array-prototype-winner/1015/ |
18:26 | <bakkot> | ("winner" is a terrible name) |
18:27 | <Ashley Claymore> | Only a weakly held opinion. I'd be curious what other languages do (the ones that can't return a fancy maybe type) |
18:28 | <Ashley Claymore> | Passing an initial value to reduce to avoid the throw is annoying because you can't easily pass `undefined` as that will get passed as an argument, so now need to handle that extra case on the comparator |
18:29 | <eemeli> | You can avoid this by passing a sentinel value as the second argument, e.g. { age: -Infinity } in the example case. |
18:29 | <Ashley Claymore> | Sure, now do that with a complex type with more than one prop :) |
18:31 | <Ashley Claymore> | Returning undefined I can always `?? error()` to get back to the exception behavior. Going from exception to undefined is more work |
18:32 | <eemeli> |
|
18:32 | <bakkot> | python's max has an optional default argument to use in case of empty list, and throws if the list is empty and no default is provided |
18:32 | <bakkot> | which seems pretty reasonable |
18:33 | <bakkot> | other languages return fancy maybe types |
18:33 | <bakkot> | https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#max-java.util.Comparator- |
18:34 | <bakkot> | https://docs.rs/itertools/latest/itertools/fn.max.html |
18:34 | <Ashley Claymore> | a default that is only used for empty sounds good, that isn't passed to the comparator |
18:35 | <Michael Ficarra> | god this language could've been so much better if we had a built-in Maybe in the early days |
18:35 | <eemeli> | Or allowed any breaking changes ever. |
18:35 | <Ashley Claymore> | And monoid protocols |
20:05 | <JaseW> | So Rust has both In Rust’s case they return an Option type then None if the list is empty, so https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.max_by That being said, Option is a fancy return type, so doesn’t help here. But I do like the max and max_by names better. |
20:09 | <Ashley Claymore> | Maybe empty vs unary arrays are the true JS option type, as you can't `null.map`. I tried that in a codebase once when I was in my wild youth phase |
20:23 | <bakkot> | max and max_by are the right names but rust has them exactly backwards :( |
20:24 | <bakkot> | sort takes a comparator, sortBy would take a T -> number |
20:24 | <bakkot> | ditto max and maxBy |
20:25 | <bakkot> | I guess the T -> number one is called max_by_key in rust |
20:26 | <bakkot> | but yeah I think the natural naming is max taking an optional comparator and maxBy taking a mandatory T -> number |
22:41 | <TabAtkins> | This is it, yes. Both variants are needed, and this is the right naming/assignment. |
22:46 | <Michael Ficarra> | @bakkot throwing or returning a special value for empty iterators? |
23:02 | <bakkot> | Michael Ficarra throwing but with an optional second default argument to return in that case, like python does |
23:03 | <bakkot> | though I guess that's annoying in the specific case that you want to use the default comparator but provide a default |
23:03 | <bakkot> | oh well I guess |
23:03 | <Michael Ficarra> | yeah I think that's what I would do as well |
23:03 | <Michael Ficarra> | still not 100% convinced it's needed, but if we do have it, that's how I would do it |
23:06 | <Michael Ficarra> | I definitely want unique /uniqueBy more |
23:07 | <bakkot> | I forget: given that we have no array prototype methods, how would those work? on iterator.prototype but returning array? |
23:08 | <bakkot> | I guess they could return an iterator, ok |
23:09 | <bakkot> | just kind of weird to have an iterator that uses O(all previous items) memory |
23:31 | <Michael Ficarra> | yeah that was the feedback I got at the last presentation |
23:31 | <Michael Ficarra> | it's weird but I don't think it's surprising if you consider for even a second what it's doing |
23:32 | <Michael Ficarra> | and I don't think that's fatal to the proposal |