Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto-recursive loop #1633

Open
bbrk24 opened this issue Dec 3, 2024 · 1 comment
Open

Auto-recursive loop #1633

bbrk24 opened this issue Dec 3, 2024 · 1 comment
Labels
proposal Proposal or discussion about a significant language feature

Comments

@bbrk24
Copy link
Contributor

bbrk24 commented Dec 3, 2024

TL;DR: My suggestion is a loop like:

y := recur x = 0 while condition
  f x
  g x
// vvv
let results = 0;
while (condition) {
  results = ((x) => {
    f(x);
    return g(x);
  })(results);
}
const y = results;

Based on my answer for part 2 of today's Advent of code challenge

Just a complete answer for Advent of Code 2024 day 3 part 2
#!/usr/bin/env civet

from fs import { readFileSync }

StateType ::= Readonly
  value: number
  enabled: boolean

instructions: [RegExp, (args: RegExpExecArray, state: StateType) => StateType][] :=
  . . /^mul\((\d+),(\d+)\)/
    . (args, state) =>
        amount := Number(args.1) * Number(args.2)
        {
            ...state
            value: state.value + (state.enabled ? amount : 0)
        }
  . . /^do\(\)/
    . (_, state) => { ...state, +enabled }
  . . /^don't\(\)/
    . (_, state) => { ...state, -enabled }

input := readFileSync 'input.txt', encoding: 'utf-8'
state: StateType .=
  value: 0
  enabled: true

i .= 0
:outer while i < input#
  for [regex, callback] of instructions
    if match? := regex.exec input[i...]
      state |>= callback match, .
      i += match.0#
      continue outer
  ++i

console.log state.value

If the recur loop existed (and we also had for/else, #1247), I could write the loop at the end of this program like

Less spoilery, but uses some code from above
recur state = { value: 0, +enabled } while i < input#
  for [regex, callback] of instructions
    if match? := regex.exec input[i...]
      i += match.0#
      break with callback match, state
  else
    ++i
    state

... now that I have that code in front of me, I'm less compelled by this particular example, but I'm still submitting this as it seems useful.

@edemaine edemaine added the proposal Proposal or discussion about a significant language feature label Dec 4, 2024
@edemaine
Copy link
Collaborator

edemaine commented Dec 4, 2024

Interesting. This is like Array.prototype.reduce. Our current for reductions don't let you access the currently accumulated value (x in the first example). I could imagine using for.value for this, something like this:

y := for reduce[0] (;condition;)
  f for.value
  g for.value

Granted that's uglier, and for.value isn't a thing yet. Maybe we could introduce a general syntax for naming the for loop value (similar to the |x> proposal for pipes with a named argument). For example:

y := for[x] reduce[0] (;condition;)
  f x
  g x

Note that I'm using (;condition;) because we don't support reductions in while loops, only for loops; for (;condition;) is the functional equivalent of while condition. Someday I'd hope we can use reductions directly in while loops, but we'd need a syntax that ideally doesn't take away from existing loops.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal Proposal or discussion about a significant language feature
Projects
None yet
Development

No branches or pull requests

2 participants