Stream: ideas

Topic: List.walkBackwardsFromUntil


view this post on Zulip Petri Jääskeläinen (Dec 21 2022 at 11:49):

Hello. I think a function List.walkBackwardsFromUntil would make sense (I searched the Roc documentation and didn't find such a function). The function, if implemented, would walk a list backwards but in addition to what List.walkBackwardsUntil offers, the function would be given an index to specify where to start the walk from. Any opinions?

view this post on Zulip Anton (Dec 21 2022 at 12:00):

Hi @Petri Jääskeläinen, my first impression is that does feel like a very specific scenario. We plan on implementing highly efficient slices of lists. Taking a slice first and then doing walkBackwardsUntil would be my preferred approach.

view this post on Zulip Kevin Gillette (Dec 21 2022 at 14:37):

We could also consider a walk function which accepts a List.range style record as its first argument, allowing more cases (including configurable backwards, forwards, and stepped walking).

While this generally wouldn't be meaningfully more efficient than walking a slice of the original list, in the case where someone wants to walk on a step other than 1, this would be more efficient/convenient, unless we supported lists with a strided view on the backing data (which could be useful for directly supporting multi-dimensional lists and zero-cost reshaping, but would be somewhat less efficient for the single-dimension contiguous list case)

view this post on Zulip Anton (Dec 21 2022 at 14:44):

Interesting, I would keep the current walk and walkBackwards to not make common cases tedious but I can see value in adding another more configurable function like walkSpecific or something.

view this post on Zulip Kevin Gillette (Dec 21 2022 at 14:50):

Or make some more of record fields optional in this case compared to range, since the endpoints can be inferred (as well as some shorthand fields)? iow walk list {} \... is equivalent to a present forwards walk, and walk list {dir: Backwards} \... is equivalent to a present walkBackwards

view this post on Zulip Kevin Gillette (Dec 21 2022 at 14:52):

dir: Rev (paired with Fwd) might be a convenient abbreviation

view this post on Zulip Anton (Dec 21 2022 at 15:04):

I still would keep the current walk as is, but for another function I'd like optional record fields.

view this post on Zulip Richard Feldman (Dec 21 2022 at 18:43):

I like the idea of having a configurable walk!

view this post on Zulip Richard Feldman (Dec 21 2022 at 18:44):

regarding naming, here's an interesting idea: what if we did this?

view this post on Zulip Richard Feldman (Dec 21 2022 at 18:46):

so basically walk becomes the most flexible configurable one, and fold becomes a shorthand for a common case: you want to walk forwards, one element at a time, starting from index 0, and never stop early

view this post on Zulip Richard Feldman (Dec 21 2022 at 18:51):

so for example it could become:

List.walk :
    List elem,
    {
        start : state,
        step : (state, elem -> state),
        until ? (state -> Bool),
        direction ? [Forward, Backward],
        startIndex ? Nat
    }
    -> state

view this post on Zulip Richard Feldman (Dec 21 2022 at 18:53):

I think you can implement all the existing functions using this (e.g. every combination of "backwards", "until", "from", "withIndex") and I suspect LLVM would optimize them down to the same thing too

view this post on Zulip Richard Feldman (Dec 21 2022 at 18:55):

I actually originally wanted to have a function like this that takes a record for learning purposes, e.g. I suspect that, for a beginner, having the labels here might be helpful:

List.walk numbers { start: 0, step: \num -> num + 1 }

view this post on Zulip Kevin Gillette (Dec 22 2022 at 03:17):

step's naming could perhaps be clarified... each perhaps?

view this post on Zulip Folkert de Vries (Dec 22 2022 at 12:56):

"walk" and "step" seem related concepts?

view this post on Zulip Kevin Gillette (Dec 22 2022 at 15:52):

I just mean that step in range refers to the counting/selection interval, and in Richard's proposal it refers to the function that is called for each elem

view this post on Zulip Kevin Gillette (Dec 22 2022 at 15:57):

A range-style step concept could be applied here, as well as start and end, to just walk some of the elements. While slicing could take care of the range-style start and end concepts, slicing could not take care of the step concept, and in any case, I believe those could all be conveniences we could add, thus we should reserve the range-style naming for the identical range-style comments.

From the Advent of Code problems, there were a couple times I used range and walk (and get and Result.withDefault), or sublist and walk together just because walk could not itself do what I needed

view this post on Zulip Kevin Gillette (Dec 22 2022 at 16:18):

Thus for the record fields, I'd propose:

  1. start, end, and step are accepted and optional, but when present have identical semantics to range (in selecting the range of indexes to walk)
  2. start and end perhaps can additionally accept First and Last tags, which are equivalent to omitting those fields (there will be cases where a program needs to have configurable walk endpoints, but in cases where either is the start or end of the list, these tags may be more convenient than arranging for field omission, and more descriptive than At 0 and Before (List.len list)
  3. {start: Last, end: First} would be equivalent to Backwards ?
  4. direction could get added to List.range if present in List.walk.
  5. Either state or initial would be replacement naming for the start field from Richard's proposal.
  6. apply would take the place of both step and until from Richard's proposal, and have the type: (state, Nat) -> [Stop state, More state] -- the Nat would be the index, since alongside start, step, etc, that's tedious and error prone math to make the programmer deal with via state.
  7. Break and Continue could be familiar naming instead of Stop/More.

view this post on Zulip Brendan Hansknecht (Dec 22 2022 at 16:33):

I think we can omit direction and just follow list.range. use start, end, and step to define the direction.

view this post on Zulip Brendan Hansknecht (Dec 22 2022 at 16:34):

Also, i am not sure about the more complex function by default. It is wanted in some cases, but forcing use of break and continue for simple function may be verbose and a tad confusing for beginners.

view this post on Zulip Brendan Hansknecht (Dec 22 2022 at 16:35):

I think splitting into more pieces so that a user can learn it one record field at a time may be more learnable

view this post on Zulip Brendan Hansknecht (Dec 22 2022 at 16:35):

I like the idea of First and Last as defaults.


Last updated: Jun 16 2026 at 16:19 UTC