rust-lang / rust-lang/rfcs

Event indicators: Extended parametric labeled scope exit points

Open
#1,380 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

T-lang
Dominant language
Markdown
Stars
6.6k
Forks
1.7k
Avg merge
16h 14m
Merged PRs (30d)
1

Description

In his article "Structured Programming with go to Statements" Donald Knuth describes a syntactic pattern called "event indicators", which allow breaking out of a loop, while maintaining a value. They are similar in principles to exceptions, in roughly the same way that coroutines (Also suggested by Knuth) are similar to threads. From a modern perspective, there is also a parallel: A syntactic construct that creates a limited variant, while eliminating the need for run-time support.

The structure I suggest for this is as follows:

match {
  for (index, value) in haystack.iter().enumerate() {
    if (value == needle) {
      break 'found(index);
    }
  }
  println!("Not here");
} {
  'found(index:isize) => println!("Found at {}", index),
}

The syntax is clearly distinguishable from a regular match due to the use of a label as a pattern.

While the above can also be implemented using a closure with enumeration return type, things become less trivial when dealing with cascaded indicators:

match {
  //...
  match {
    if (something) {
      break 'something;
    }
    //...
    break 'somethingelse
  } {
    'something => {},//...
  }
  //...
} {
  'somethingelse => {},//...
}

The above cannot be cleanly wrapped into closures, since you can't "return twice" in a single statement.

I also suggest that duplicate labels are allowed in the cascaded case, with the innermost matching label applying. In this case "matching" can also include overloaded parameters:

match {
  for i in 1..10 {
    match {
      match {
        match i {
          1 => break 'common(i),
          2 => break 'common(" "),
          3 => break 'common,
          _ => {},
        }
        println!("!");
      } {
        'common(x:isize) => {println!("Hello"); continue},
        'common => break 'common("world"),
      }
      break 'common;
    } {
      'common(s:string) => println!("{}", s),
    }
  }
} {
  'common => 0,
}

The above should print Hello world!.

Note that unlike a regular match, a catch-all pattern (_) is not necessary, since every label must be defined by the match patterns block.

It could also be used to simulate exception handling:

macro_rules! tryb {
  ($expr:expr) => (match $expr {
    $crate::result::Result::Ok(val) => val,
    $crate::result::Result::Err(err) => {
      break 'catch($crate::convert::From::from(err))
    }
  })
}

//...

match {
  tryb!(foo());
  tryb!(bar());
} {
  'catch(e:io::Error) => println!("IO error happened!"),
  'catch(e:MyError) => println!("MyError happened!"),
  'catch(e:Error) => println!("Unknown Error happened!"),
}

In the above, the most appropriate 'catch block is chosen based on the support of the From trait in each case. Only compile-time information is used, however, to determine the type of error returned from each method.

It differs from regular exceptions in that it is method-local, so there's no unwinding of the call stack.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the proposal and its event-indicator, cascaded-label, and tryb! examples, then review the Rust RFC process for the requirements of a language-feature proposal. This issue does not name implementation files or tests; completion would require an accepted, sufficiently specified design before implementation work could be scoped.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.