Event indicators: Extended parametric labeled scope exit points
Nobody has claimed this yet.
- 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
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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