Syntax
Structs
Design
enum Option<T> {
Some(uint),
None,
}
enum Toto {
Foo,
Bar(uint),
Baz { tata: uint }
}
struct Baz {
content: uint,
}
// struct NamedTuple<T, U> {
// foo: T,
// bar: U,
// }
fn foo(option: Option) { }
/*
enum Option { Foo, Bar }
fn main() {
var maybe = .Some(10);
match maybe {
.Some()
.None => {}
else => {}
}
var baz = Baz { content: 10 };
var inner = baz.content;
var _ { content } = &baz;
foo(.Foo);
}
Traits
Rust-like traits.
Design
Definition
trait Foo {
fn bar() uint;
fn baz() {
// snip
}
}
Implementation
struct MyType;
impl Foo for MyType {
// notice how there is no type in impl block
fn bar() {
// chosen by a fair roll of dice
4
}
}
Match
Design
Invocation
(find name)
match variable { <arms> }
match foo.method() { <arms> }
Postfix
let variable = Some(42);
variable.match { <arms> }
foo.method().match { <arms> }
foo.method().match { <arms> }.continue()
Arms
Small arrow syntax (languages)
<match> {
123 -> {}
else -> {}
}
Rust large arrow syntax
<match> {
123 => {}
_ => {}
}
no arrows
<match> {
123 { 456 }
_ {
// -snip-
}
}
Future
Sandbox Sample
Many of the tests shown here are usual constructs in programming but tried in a left-to-right syntax. I would like to explore the LTR space
is Operator
var option = Some(42);
if option is Some(num) { }
if option.is Some(num) { }
not Operator
var cond = true;
while cond.! // or cond.not() (e.g. `vec.is_empty().not()`)
and cond is true
{
// snip
}
Loop Constructs
var stmts = [];
var stmts_iter = stmts.iter();
while stmts_iter.next() is Some(stmt) { }
in stmts for stmt { }
in stmts the stmt { }
for stmts each stmt { }
for stmts be stmt { }
all stmts be stmt { }
loop stmts for stmt { }
stmts.for |stmt| { }
stmts.iter().enumerate().for |i, stmt| { }
Left-to-Right Trait implementation
for Struct impl Trait { }
Struct::impl Trait { }
Struct.impl Trait { }
Struct.impl { }
Postfix deref operator
cst og_num = 10;
var myref = &og_num;
var mynum = myref.*;
fn deref(bar: T) {
bar.mac_call().*;
bar.field.*;
bar.field.mac_call().*;
bar.mac_call().field.*;
}
Postfix try control-flow operator
var res = Ok(98);
var num = res.?;
Type ascription
// annotate functions as such
var myexpr = f() : uint;
var myvec = (
(1..=100)
.into_iter()
.collect() : Vec<_>
)
.into_iter()
.map((|x| x+1):fn(uint) -> uint);
Generics
fn forget[T](v: T) void;
fn substring['a](s: &'a str) &'a str;
fn substring(s: &str) &str;
fn foo<T>(arg: T) T {
arg
}
Alternative keywords
My rationale for using verbs instead of nouns for keywords is that they are less likely to conflict with user variable names.
- Verb keywords:
deffor values (functions, constants)decl/dclfor type-level constructs (structs, enums, etc.)letfor local values (variables)
- Noun keywords:
fn/functype/struct/enumvar/valcst/const
def func() { }
def constant = 42;
trait Add {
// dcl → declare instead of `fn`
dcl Output;
// def → define instead of `type/struct/enum`
def add(self, other: Self) Self::Output;
}
Effects
Reference:
Sample 1
effect Resolve {
fn resolve(name: Sym) &ref Ty;
}
fn main() {
let items = <..>;
let map = Map<Sym, Ty>;
// I don't like the try/catch-like syntax for effects
handle {
items.for |item| {
'resolve(item);
}
} with {
// no type in effect handling
fn resolve(name) {
map.entry(name).match {
// not long arrows
.Occupied |ty| effect_continue &ty
.Vaccant || {
// it's not in the handle ctx anymore???
let ty = resolve_item(name);
map.insert(name, ty);
effect_continue &ty;
}
}
}
}
}
fn resolve_item(item: hir::Item) Ty \ Resolve {
// translate hir to ty
// ...
let ty = 'resolve(item.subtype);
// ...
ty
}