Some of these are would be nice but not really needed, most are a requirement.
- Braces! Why wouldn't I want this?
- Classes, I think multiple inheritance would be a wonderful thing, such as Mixins but not really needed.
- Metaprogramming. D has a really nice way of handling compile time code, which I think is a much better method than Lisp's macros.
- Type system, but also with type inference (such as auto/var from D, C#, etc…) - I guess that is the same as let.
- Operator overloading. I still don't understand why this doesn't exist in Java.
- I see you have Lambda/Closures.
- Dynamic code generation - Both bytecode generation and maybe something like Linq's Expression Trees
From a VM point of view, I wonder if
tailcall should be a JIT optimisation rather than a compile time optimisation, it just means mucking around with bytecode at runtime or in external tools would be easier.
GravityScore wrote something for his Hydrogen language on
memory management, I thought it was quite cool, but I can't see it working for some elements.
I would be interested in working on this, but if you don't want me to that's fine!
Compulsory xkcd because you mentioned Haskell:
Spoiler
GravityScore's just looks like
automatic reference counting, am I wrong? For memory management, I was thinking of having an instruction for each of my allocation techniques. The garbage collector will work using ARC primarily, but also with an ordinary generational mark-sweep collector that runs rarely (letting ARC take the bulk of the work, as it should) to make up for retain cycles. Although I guess I should allow the use of pure GC or pure ARC memory management, so I'll have an instruction that takes parameters to enable each of these on a value.
Anyway I agree on all other accounts with you. My OOP will be strictly multiple inheritance, although I hope that most users take advantage of the plans I have for algebraic data types. For example, I'll be treating Int as an ADT where integer literals are treated as constructors for it. This lets users take advantage of an idea I had:
func divide(x: Int, y: Int(!0)): Int {
return x / y
}
func divideOrNot(x: Int, y: Int): Maybe Int {
case b {
0 = {
return nil
}
otherwise = {
return Just divide(x, y)
}
}
}
Basically, the idea is that the compiler tracks pattern matching that you've done, so that it knows which constructors a value can and can't be. This enables us to define integer values that
b can't be, and that can be checked at compile time. Another example using something other than integers:
data MyType = Cons1 | Cons2 Int | Cons3 String
func someFunction(a: MyType(Cons2 | Cons3): Either Int String {
case a {
Cons2 i = {return Left i}
Cons3 s = {return Right s}
}
}
func whatever(a: MyType): () {
let x: Maybe (Either Int String) = case a {
Cons2 | Cons3 = {Just someFunction(a)}
Cons1 = {nil}
}
}
func orThis(): () {
let x: MyType = Cons3 "Hey"
let y = someFunction(x)
}
The syntax here is all completely made up on the spot FYI, I haven't done a great amount of design work there yet. But you can see that there are compile time restrictions on the ability to call certain functions. I haven't decided yet if I should make the divide operator require Int(!0) or if dividing by zero should just return NaN. But anyway, the compiler knows about the constructor restrictions on objects because of their instantiations, so it can infer that
x can be passed to
someFunction.
I need to decide how far I want this feature to go. For example, should code like this be allowed?
func x(n: Int, i: Int(!n)): Int {
return 2 / (n - i) // because i is known not to be n, the type of n - i is Int(!0)
}
But again, I'm not sure if this is too for or not. It could be difficult for the caller to prove in a case. And it has to be in a case, since == operators can be overloaded, meaning the compiler doesn't know what that operator does.
func y(n: Int, i:Int): () {
let z = case i {
n = {nil}
otherwise = {Just x(n, i)}
}
}
So this case sees that
i isn't matched to
n, so it reasons that they can be passed to x. And of course the same can be extended to other ADTs.