I've been doing some thinking after about syntax modifications for a language near identical to rust, with automatic memory management. I would love feedback about what seems like a good idea and what seems like a horrible idea.
The 'ref' keyword
In Rust, values are always moved by default. In higher-level languages, to simplify things, there's a split between primitive values and reference values, the former is always copied and the latter is always passed by reference.
With this hypothetical language, every value is cloned by default. References would always be handled using the 'ref' keyword. Rust already has the ref keyword for pattern matching - I want to keep that syntax the same and extend its functionality similar to how C# uses 'ref'.
let x = 5
let x_ptr = ref x // References are created using the 'ref' keyword
let y = x_ptr // Automatically dereferenced; y is a normal value.
y += 5 // x is still 5, y is 10
x_ptr += 5 // x is now 10
'ref' also may be used in the following context to create things called 'ref structs', which are structs that ALWAYS will be referred to (essentially making them identical to C# classes). This would work with enums and type aliases too (ref enum = ... ref type = ...).
ref struct Node<T> {
pub data: T
pub next: Option<Node<T>>
pub fn new(data: T, next: Option<Node<T>>) {
Self { data, next }
}
}
fn main() {
let a = Node::new(5, None)
let b = Node::new(5, Some(a))
a.next = Some(b)
a.next.data += 1 // b's data is 6
b.next.data += 1 // a's data is 6
}
A Higher Kinded Self
Most high-level languages don't have fixed-size arrays. Therefore this language doesn't really need to ever use numbers where generics usually go. So, I propose the following rule for trait creation:
when defining a trait, rather than put type variables within the "<>" brackets, instead you can put a number 'n'. This tells us that this trait expects to be implemented by a type constructor with at least 'n' generic arguments:
enum Option<T> {
None,
Some(T)
}
// Trait for something with at least 1 generic
trait Functor<1> {
// 'self' and 'Self' may now take 1 generic argument
fn map<A,B>(self<A>, f: fn(A) -> B) -> Self<B>
}
// Despite 'Option' requiring a generic 'T', Functor doesn't require it.
impl Functor for Option {
fn map<A,B>(self<A>, f: fn(A) -> B) -> Self<B> {
match self {
Some(x) => Some(f(x)),
None => None
}
}
}
Other Stuff
-
Optional semicolons like Go? (I didnt' use them for the pseudocode above)
-
Due to everything being cloned as default, and 'ref' being used like it is, maybe that can replace the 'immutable by default, add the 'mut' keyword' design Rust has?