A large collection of rough ideas that may or may not appear in the language.
let a = Vec2::new(3, 2);
let b = Vec2::new(1, 4);
let c = a.add(b); -- Vec2::add(a, b);
const (~+) = Vec2::add;
const (~.) = fn(a : Vec2, b : Vec2) : i32 {
a.x * b.x + a.y * b.y
};
let c' = a ~+ b;
const math = import "core/math";
const M = math.Matrix2;
const (%*%) = M::mul;
let q = M::identity();
let r = M::identity();
let s = q %*% r;
liking the idea of having abstract data types
liking the idea of structural typing
liking the idea of a panic..catch syntax for exceptions (make it hard to recover)
liking the idea of extension functions
def Abstract = package int as T {
def zero = 0 : T;
def one = 1 : T;
def add = fun(a : T, b : T) : T {
a + b
};
};
def two = unpack Abstract as T {
T::one T::add T::one
};
def Player = struct {
x : f32;
y : f32;
name : str;
};
let player : Player = struct.{
x = 0;
y = 0;
name = "frank";
};
player.{
x += 4.0;
y += 9.5;
};
player::hi()::hello()::what()
def Id = [a : type] => (x : a) => a;
def (-) = [a : type] => (x : a) => match x {
n : i32, m : i32 = #minus(n, m);
n : i32 = #neg(n);
_ = #compiler_error();
};
-- (-) : [a : type] -> a -> a
-- NEW
-- i don't like this v
-- identifiers depend on whitespace to determine precedence
let $ = 3;
let $$ = 300;
if $$ > 100 and $ < 40 {
-- parses perfectly fine! >, <, and "and" are *weak* binary operators
-- (and (> ($$) 100) (< ($) 40))
}
if $$>100and $< 40 {
-- also parses fine, but differently
-- $$> is a unary prefix operator
-- and is a unary postfix operator
-- $< is a weak binary operator
}
-- pointers:
let a = `3;
let b : i8 = a`; -- deref
let c = !(@(condition));
const fmt = import "fmt";
const printf = fmt.printf;
const (++) = fmt.(++);
-- what i like
-- go interfaces
-- c++ templates
-- zig zen
-- rust move semantics
-- haskell operators
def Set = type; -- Set : type#2
-- i would love to be able to implement thunks like ruby does
let a = 3;
core::each[i32](array) |x| {
io::print(a); -- this would reference the `a` from the outer scope
-- without needing to have closures
};
-- possible syntax
def core::each = [a]fn(arr : List[a]) |a| nothing : nothing {
-- implementation
};
-- c++ templates
def fact = [n : usize]match n {
0, 1 => 1,
m => m * fact[m - 1]
}; -- fact : [usize] -> usize
-- function types
-- core::each : [a : type] -> fn(List[a]) |a| nothing -> nothing
-- existential types
type Show = interface {
show : fn(self) -> String;
};
-- parametric polymorphism
let id = [T]fn(x : T) : T { x };
perhaps have it so that functions can be used unary e.g.
let print_int = fn(x : i32) : () {
...
}
print_int 3 -- equivalent to print_int(3)
type digit = uint where _ < 10;
let hundred : uint = 100;
let mut nine : digit = 9;
nine = hundred as digit; -- a runtime check is performed
for m {
-- while loop
}
for m in [1, 2, 3] {
-- iterator
}
for {
-- infinite loop
}
if m {
}
{
-- block
}
typename alias = TypeName::A
typename PositiveInt = i32 where it > 0
typename Pos = [T subtype Numeric](x : T, y : T)
typename Digit = u8 where {
it >= 0 and it <= 9
}
let pos : Pos[T] = (1, 2)
typename Arg1 = (a : int, b : int)
typename Arg2 = (int, int, int)
def function = fn(arg : Arg1 | Arg2) : unit {
match arg {
(a, b) : Arg1 => {
...
},
(a, b, c) : Arg2 => {
...
}
}
return ()
}
function(a = 3, b = 4);
function(6, 7, 8);
def `-` = fn(arg : (int, int) | int) : int {
match arg {
n : int, m : int = #int_subtract(n, m)
n : int = #int_negate(n)
}
}
def `+` = [T : Add]fn(a : T, b : T) {
a.add(b)
}