Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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:
    • def for values (functions, constants)
    • decl/dcl for type-level constructs (structs, enums, etc.)
    • let for local values (variables)
  • Noun keywords:
    • fn/func
    • type/struct/enum
    • var/val
    • cst/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
}