Beautiful! On Sun, Oct 24, 2021 at 8:59 PM Tyler Young <s3c...@gmail.com> wrote:
> > Oh, okay, works for me! 😄 > > I'll put together an implementation. > > On Sunday, October 24, 2021 at 1:59:00 PM UTC-5 José Valim wrote: > >> > Re: an Enum version, I'm of the opinion this isn't desirable. It'd be >> useful for ranges, but downright dangerous for other Enumerable types that >> don't have a concept of ordering. E.g., if you wrote some code to do a >> rotate on a map or set, and by some miracle it does what you wanted, you're >> implicitly depending on the exact hashing algorithm used under the hood, >> and the next release could very well break your code. >> >> Yes but this has never stopped us from adding functions to Enum. See >> take/drop, that all assume order. So that should not be a blocker for >> adding rotate. :) >> >> On Sun, Oct 24, 2021 at 8:57 PM Tyler Young <s3c...@gmail.com> wrote: >> >>> I went ahead and pushed a change to make it only accept a step size of 1 >>> (raising an ArgumentError like Enum.slice/2 otherwise). 👍 >>> >>> Re: an Enum version, I'm of the opinion this isn't desirable. It'd be >>> useful for ranges, but downright dangerous for other Enumerable types that >>> don't have a concept of ordering. E.g., if you wrote some code to do a >>> rotate on a map or set, and by some miracle it does what you wanted, you're >>> implicitly depending on the exact hashing algorithm used under the hood, >>> and the next release could very well break your code. >>> >>> It'd be useful if we had a protocol that could express "I'm an *ordered* >>> enumerable," but failing that, I think the potential confusion of rotating >>> on unordered enumerables is worse than the added value of supporting ranges >>> via the Enum module. >>> >>> -- >>> Tyler Young >>> >>> On Wednesday, October 20, 2021 at 10:37:31 AM UTC-5 José Valim wrote: >>> >>>> Great job! >>>> >>>> I think you can simplify this to require ranges to always have a step >>>> of 1. So decreasing ranges will need an explicit //1. We want to do this >>>> for slice, but we can't yet because of backwards compatibility. >>>> >>>> If we have a plan to add this to Enum, then we should add it to Enum >>>> now, to avoid a deprecation down the road. We can postpone a Stream >>>> implementation though (which would be far from trivial). We can however use >>>> the current list implementation to optimize lists rotate. >>>> >>>> For enums, I think it can be done with a single reduce? >>>> >>>> On Wed, Oct 20, 2021 at 5:02 PM Tyler Young <s3c...@gmail.com> wrote: >>>> >>>>> My draft implementation >>>>> <https://github.com/s3cur3/elixir-xutil/blob/main/lib/x_util/list.ex> (and >>>>> the associated @doc and test suite >>>>> <https://github.com/s3cur3/elixir-xutil/blob/main/test/list_test.exs>) >>>>> has been updated to match the range semantics of Enum.slice/2. Among other >>>>> things, that means it has support for negative indices. >>>>> >>>>> I thiiiiiiiink this represents a minimal shippable version of a >>>>> list-only implementation (assuming we're okay with the name, and we're >>>>> okay >>>>> with making it list-only for the time being). >>>>> >>>>> I'd love to get some feedback on what the next steps should be. 🙏 >>>>> >>>>> -- >>>>> Tyler Young >>>>> >>>>> On Sunday, September 5, 2021 at 7:38:19 PM UTC-6 Tyler Young wrote: >>>>> >>>>>> In the draft implementation on my GitHub >>>>>> <https://github.com/s3cur3/elixir-xutil/blob/main/lib/x_util/list.ex>, >>>>>> I've: >>>>>> >>>>>> 1. Changed the implementation to the recursive version >>>>>> (thanks José!). After a bunch of benchmarking and tweaking, this is >>>>>> the >>>>>> fastest version I could come up with on a range of sizes from 16 to >>>>>> 16,384. >>>>>> The recursive one is between 2 and 6% faster at worst; it's something >>>>>> like >>>>>> 40% faster at best. (Happy to supply the benchmarking code if folks >>>>>> are >>>>>> interested.) >>>>>> 2. Implemented the single-element move suggested by Zach Daniel >>>>>> >>>>>> >>>>>> I've not yet added support for negative indices, but it's on my list. >>>>>> >>>>>> Re: naming, I think I agree that slide is a more intuitive name; the >>>>>> only thing I'd say in favor of rotate is that it appears to be the more >>>>>> common name for algorithms that look vaguely like this in other >>>>>> languages. >>>>>> In terms of prior art, I haven't been able to find any languages that >>>>>> call >>>>>> it slide. (That could be a failing of my search skills, though!) >>>>>> >>>>>> Re: supporting any enumerable, my reasoning for proposing it on List >>>>>> rather Enum was specifically to avoid folks confusedly trying to index >>>>>> into >>>>>> Map and MapSet. It'd be easy enough to provide one (ever-so-slightly >>>>>> faster) specialization for lists and one for other enumerables, though. >>>>>> >>>>>> Re: streams, I don't know much about streams in Elixir, but I could >>>>>> take a crack at implementing it. >>>>>> >>>>>> -- >>>>>> Tyler Young >>>>>> >>>>>> >>>>>> On Sat, Sep 4, 2021 at 6:22 PM Zach Daniel <zachary....@gmail.com> >>>>>> wrote: >>>>>> >>>>>>> >>>>>>> Fwiw, “slide” sounds like a much more intuitive name than rotate, to >>>>>>> me. Rotate sounds like a 2d matrix operation (often commonly done on >>>>>>> lists). Additionally, we should probably support a range *or* an index >>>>>>> as >>>>>>> the second argument, since moving one thing is still useful, and would >>>>>>> be a >>>>>>> good first example in the docs. >>>>>>> On Saturday, September 4, 2021 at 2:04:31 PM UTC-4 José Valim wrote: >>>>>>> >>>>>>>> Well, for a stream you are still traversing everything, then I >>>>>>>> guess it makes sense to be linear. I guess the benefit is not having to >>>>>>>> allocate a new data structure. Once again we will need two algorithms, >>>>>>>> depending if the end is before or after start. If before, you need to >>>>>>>> accumulate until you find the slice, then you emit the slice, emit the >>>>>>>> accumulator, and then continue as usual. If after, you need to emit >>>>>>>> everything, until start, then accumulate the slice, and emit >>>>>>>> everything as >>>>>>>> necessary. So both operations will require you to buffer, the amount of >>>>>>>> buffered content depends on the end position. >>>>>>>> >>>>>>>> On Sat, Sep 4, 2021 at 7:34 PM w...@resilia.nl <w...@resilia.nl> >>>>>>>> wrote: >>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> On Saturday, September 4, 2021 at 7:21:45 PM UTC+2 José Valim >>>>>>>>> wrote: >>>>>>>>> >>>>>>>>>> It could definitely be implemented as a Enum or a Stream >>>>>>>>>> function, but the level of complexity is definitely much higher, and >>>>>>>>>> reduce >>>>>>>>>> would force the implementation to be linear anyway. So I am honestly >>>>>>>>>> not >>>>>>>>>> sure if it is worth it. >>>>>>>>>> >>>>>>>>> >>>>>>>>> The main part of the algorithm could be written using a couple of >>>>>>>>> calls to `Enum(erable).slice`. In this case, at least as long as the >>>>>>>>> number >>>>>>>>> of elements to be moved is small, the implementation is faster than >>>>>>>>> linear >>>>>>>>> (for types that support faster than linear slicing). >>>>>>>>> >>>>>>>>> That is, until we concatenate the results at the end to form the >>>>>>>>> rotated list. So at most it is an efficiency improvement of a constant >>>>>>>>> factor, but the result will still be linear. >>>>>>>>> Hmm... >>>>>>>>> >>>>>>>>> -- >>>>>>>>> >>>>>>>> You received this message because you are subscribed to the Google >>>>>>>>> Groups "elixir-lang-core" group. >>>>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>>>> send an email to elixir-lang-co...@googlegroups.com. >>>>>>>>> >>>>>>>> To view this discussion on the web visit >>>>>>>>> https://groups.google.com/d/msgid/elixir-lang-core/d54e1e48-a32c-4d9c-8307-d5cb7926050cn%40googlegroups.com >>>>>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/d54e1e48-a32c-4d9c-8307-d5cb7926050cn%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>>> . >>>>>>>>> >>>>>>>> -- >>>>>>> >>>>>> You received this message because you are subscribed to a topic in >>>>>>> the Google Groups "elixir-lang-core" group. >>>>>>> To unsubscribe from this topic, visit >>>>>>> https://groups.google.com/d/topic/elixir-lang-core/LYmkUopaWN4/unsubscribe >>>>>>> . >>>>>>> To unsubscribe from this group and all its topics, send an email to >>>>>>> elixir-lang-co...@googlegroups.com. >>>>>>> To view this discussion on the web visit >>>>>>> https://groups.google.com/d/msgid/elixir-lang-core/8903e169-dadc-48bf-98ea-f860f1bc0891n%40googlegroups.com >>>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/8903e169-dadc-48bf-98ea-f860f1bc0891n%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>> . >>>>>>> >>>>>> -- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "elixir-lang-core" group. >>>>> To unsubscribe from this group and stop receiving emails from it, send >>>>> an email to elixir-lang-co...@googlegroups.com. >>>>> >>>> To view this discussion on the web visit >>>>> https://groups.google.com/d/msgid/elixir-lang-core/dff0982d-3d24-4279-a013-e7f08fb2e5cdn%40googlegroups.com >>>>> <https://groups.google.com/d/msgid/elixir-lang-core/dff0982d-3d24-4279-a013-e7f08fb2e5cdn%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>> . >>>>> >>>> -- >>> You received this message because you are subscribed to the Google >>> Groups "elixir-lang-core" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to elixir-lang-co...@googlegroups.com. >>> >> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/elixir-lang-core/cce43976-8c96-4098-b926-06133be5ec24n%40googlegroups.com >>> <https://groups.google.com/d/msgid/elixir-lang-core/cce43976-8c96-4098-b926-06133be5ec24n%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- > You received this message because you are subscribed to the Google Groups > "elixir-lang-core" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to elixir-lang-core+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/ab1d8450-7a6d-4c9b-a6f0-e839fa9bcc00n%40googlegroups.com > <https://groups.google.com/d/msgid/elixir-lang-core/ab1d8450-7a6d-4c9b-a6f0-e839fa9bcc00n%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "elixir-lang-core" group. To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4KRqMVh4xev84mV9PughE2ShsdL66cvw4pWWu9fpTx1og%40mail.gmail.com.