version 1.0 battle plan
=======================
- make 'not nil' the default (produce warnings instead of errors for a smooth migration path)
That's great. What's the syntax for declaring possibly nil types?
- case objects needs to be safe and need to support pattern matching
ML/Rust style pattern matching?
- sanctionize some macro implementation for interfaces
While I greatly appreciate the use of the American/Oxford suffix, the word sanction needs no suffix here. I hope that whichever implementation is sanctioned works well with all of the other relevant language features of Nim.
- implement a way to forward object type declarations across module boundaries; C++ style
That would be really useful, but as a hard blocker for 1.0?
That's great. What's the syntax for declaring possibly nil types?
nil ref T.
ML/Rust style pattern matching?
Oh we might as well start a discussion here about its syntax. I thought it would be just
case x.kind
of enumValue(a, b, c): ...
...
I hope that whichever implementation is sanctioned works well with all of the other relevant language features of Nim.
Well I don't know what that means. :-) Please list your criteria.
That would be really useful, but as a hard blocker for 1.0?
Seems easy enough to do though.
To start with a practical example, I would like to talk about, how I would pattern match the NimNode types, mostly because they are types I would care about. The syntax should be almost identical to the construction, just it should work in reverse. Here is an example of how I could imagine it:
import macros
proc foobar(arg: NimNode, id: int): void =
echo arg.repr
macro myMacro(arg:untyped): untyped =
for section in arg:
case section # pattern matching is always the whole object, not just the kind
of nnkCall.newTree(ident"variantA", `stmtList`):
foobar(stmtList, 0)
of nnkCall.newTree(ident"variontB", `stmtList`):
foobar(stmtList, 1)
of nnkCall.newTree(ident"variantC", nnkStmtList.newTree(nnkCall.newTree(ident"subVariantA", `stmtList`))):
foobar(stmtList, 2)
of nnkCall.newTree(ident"variantC", nnkStmtList.newTree(nnkCall.newTree(ident"subVariantB", `stmtList`))):
foobar(stmtList, 3)
Mymacro:
variantA:
a += 1
b += 2
variantB:
a += 4
b += 8
variantC:
subVariantA:
a += 8
b += 19
variantC:
subVariantB:
a += 20
b += 30
Full input ast:
StmtList
Call
Ident !"variantA"
StmtList
Infix
Ident !"+="
Ident !"a"
IntLit 1
Infix
Ident !"+="
Ident !"b"
IntLit 2
Call
Ident !"variantB"
StmtList
Infix
Ident !"+="
Ident !"a"
IntLit 4
Infix
Ident !"+="
Ident !"b"
IntLit 8
Call
Ident !"variantC"
StmtList
Call
Ident !"subVariantA"
StmtList
Infix
Ident !"+="
Ident !"a"
IntLit 8
Infix
Ident !"+="
Ident !"b"
IntLit 19
Call
Ident !"variantC"
StmtList
Call
Ident !"subVariantB"
StmtList
Infix
Ident !"+="
Ident !"a"
IntLit 20
Infix
Ident !"+="
Ident !"b"
IntLit 30
I have to admit thet newTree is not the best name to extract trees, but that is the way I construct them, and that is the only syntax that works reliably with every node kind.
That's great. What's the syntax for declaring possibly nil types?
nil ref T.
Optional Types suggests another alternative of
T?
so
var
v1: int # not nil
v2: int? # can be nil
proc xyz[T?](): T? =
result = nil # <- compile error, since not allowed
nil ref T.
Super. I think this change will turn some heads. I also like the recent work on region collection. Rust and Swift are going all in on doing away with the tracing GC; it's a good thing that Nim can hedge it's bets.
> ML/Rust style pattern matching?
Oh we might as well start a discussion here about its syntax.
Could you expand the example a bit? I'm not following.
> I hope that whichever implementation is sanctioned works well with all of the other relevant language features of Nim.
Well I don't know what that means.
How will interfaces interact with generics? Will we have generic interfaces, like in Java and D?
What's to be gained by sanctioning or endorsing one approach right now?
> That would be really useful, but as a hard blocker for 1.0?
Seems easy enough to do though.
Sure, but I'd like to see Nim 1.0 sooner rather than later, and this strikes me as an easily compatible change (a feature addition, that shouldn't interfere with much else) that could go in 1.X
T?
The syntax for type constructions follows Nim's syntax for expression construction and in expressions there are no postfix operators so T? doesn't fit Nim's syntactic framework. In other words I decided against this as this syntax is hard to implement and inconsistent.
To start with a practical example, ...
Syntactic issues aside, you start with an example that cannot be checked for exhaustiveness and so is pretty much against the idea of case.
The reason why pattern matching needs to be built into the language is not convenience (you can get that with a PM macro easily enough even though nobody uses that for macros right now) but safety. Right now Nim's case objects are not safe:
type
E = enum
valA, valB
Obj = object
case k: E
of valA: a: int
of valB: b: string
proc modify(o: var Obj) =
reset(o)
o.k = valB
o.b = "xx"
case x.kind
of valA:
modify(x)
echo x.a
of valB: ...
Right now Nim's case objects are not safe:
Ah, I didn't get that this was the intent of the pattern matching, though you did say you were going for safe case objects right there.
I don't see why pattern matching is necessary for version 1.0. Can you explain the rationale for it?
I'd guess that one of the goals for 1.0 is making Nim a safer language, given not-nil as default an safe case objects. IMO that's a good direction to head, with Rust and Swift being in the same space as Nim. What troubles me is that the decisions about the path to 1.0 are largely invisible to users, and changes somewhat arbitrarily.
- make 'not nil' the default
@Araq - does this also mean var x: seq[T] gets default initialized to @[] (when not explicitly initialized)?