Hi folks!

I'd like to propose a List.rotate/4 function (and maybe some convenience 
wrappers for it as well).

Rotate is one of those algorithms that, once I learned about it, I started 
seeing it everywhere. It's somewhat complicated to grasp (it takes 4 
parameters, after all), but in situations where you need it, it's still 
*much* simpler than the equivalent imperative version.

The classic use case is this: Suppose you have a list of to-do items, which 
the user has ordered by priority:

   1. Apply to college 
   2. Brush the dog 
   3. Change the car's oil 
   4. Deliver flowers 
   5. Exchange gifts

A "rotate" or "slide" occurs when the user selects some number of elements 
and drags them to a new place in the list. Let's say they selected items 3 
& 4 from the preceding and dragged them above item 2. When they release the 
mouse, the new order should be:

   1. Apply to college 
   2. Change the car's oil 
   3. Deliver flowers 
   4. Brush the dog 
   5. Exchange gifts

Doing this without the named algorithm requires 3 splits (one at the 
insertion point, one at the start of the selected range, and one at the end 
of the selected range). It's easy to get the index math wrong, and it's 
even harder for readers of your code to grasp what's going on. Adding this 
as a "vocabulary" algorithm would help a lot, I feel.

A number of other languages 
<https://twitter.com/code_report/status/1419900906062204939?s=20> have a 
rotate algorithm, though it's still somewhat uncommon. I found Dave 
Abrahams' comments 
<https://forums.swift.org/t/proposal-implement-a-rotate-algorithm-equivalent-to-std-rotate-in-c/491/2>
 
valuable when this was discussed for inclusion in Swift.

I've put together a first draft of an implementation 
<https://github.com/s3cur3/elixir-xutil/blob/main/lib/x_util/list.ex>, plus 
some 
basic tests 
<https://github.com/s3cur3/elixir-xutil/blob/main/test/list_test.exs>.

If this is something folks decide we want, it might also be worth 
considering a few variants (also implemented in the file linked above):

   - slide/4: Syntactic sugar over rotate, but it's useful in practice 
   because usages of rotate often need to be able to move a chunk of the list 
   either or backward. (Most usages I've seen in the wild end up doing an if 
   insertion_idx < range_start . . . else . . .) 
   - slide_one/3, where the second argument is the index of the single 
   element to move and the last argument the target index. This would just be 
   syntactic sugar over slide/4. (In my experience, about half the times I 
   use this algorithm, the conceptual requirements guarantee that it'll only 
   act on a single element.)

-- 
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/01c63660-6a11-4e69-bdcb-6659579ef683n%40googlegroups.com.

Reply via email to