I want a function like "proc `[]`T".
When I compile this:
```test.nim
import macros
macro test(): untyped =
let n = nnkStmtList.newTree(
newEmptyNode(),
newEmptyNode(),
newEmptyNode(),
newEmptyNode(),
newEmptyNode(),
newEmptyNode(),
)
for i, x in n[1..^1]:
echo i
test()
I expect:
0
1
2
3
4
But really behavior is:
Hint: system [Processing]
Hint: test [Processing]
Hint: macros [Processing]
test.nim(13, 13) Error: type mismatch: got
proc []T, U: string
proc []T: T
proc []I: Ordinal; T: T
proc []T: var T
proc []Idx, T: var T
proc []Idx, T: T
proc [](s: string; i: BackwardsIndex): char
proc []T, U, V: seq[T]
proc []Idx, T, U, V: seq[T]
proc [](n: NimNode; i: int): NimNode
proc [](n: NimNode; i: BackwardsIndex): NimNode
What type is suitable as the return type of the proc?
Does anyone have a good idea?
I say iterator, which needs the snippet to do for i, x in toSeq(n[1..^1])
Thanks!
But maybe proc toSeq(x: NimNode) is not exist.
I will make the proc [] returns seq[NimNode].
this looks very much like a hypothetical problem, not a real problem. Can you show me a real use case where you actually use this slicing in action?
nimlSpecial:
*PP[T] = Foo[int, int, T]
*P = PP[string]
and use Foo[int, int, T] as b in
proc parseBracket(b: NimNode): tuple[name: string, bracket: seq[NimNode]] =
if b.kind == nnkIdent:
result.name = $b.ident
result.bracket = @[]
elif b.kind == nnkBracketExpr:
result.bracket = @[]
for i, n in b:
if i == 0:
result.name = $n.ident
else:
result.bracket.add(n)
else:
error "Bracket is Invalid:\n" & b.treeRepr
I want to write this as
proc parseBracket(b: NimNode): tuple[name: string, bracket: seq[NimNode]] =
...
elif b.kind == nnkBracketExpr:
result.name = $b[0].ident
result.bracket = b[1..^1]
...
This is used in https://github.com/loloiccl/nimltype
And I think it is natural to implement `[]`(n: SomeType, s:HSlice[T, U]): seq[SomeType] if there is `[]`(n: SomeType, i: int): SomeType.
I disagree that your solution is a good solution. You should process or at least do a sanity check on the arguments of the bracket expression arguements.
elif b.kind == nnkBracketExpr:
result.name = $b[0].ident
for i in 1 ..< b.len:
result.bracket.add checkBracketArg(n[i]) # <-- this needs a check
And even if you don't use the sanity check on the argument, this version is just 1 line more than you want.
this looks very much like a hypothetical problem, not a real problem
I actually need that in many of my macros, because:
for i in 1 ..< b.len: ... is that I often need the slice multiple times, maybe passing it to other functions etc.for i in 1 ..< b.len: ... doesn't tell me why I had to omit a certain number of children at the beginning or the end. I prefer to give the slice a variable name in an attempt to clarify why it is semantically different than the set of all children.My common solution is let relevantChildren = toSeq(node)[1 .. ^1] and often I have to import sequtils just for the purpose of this subslicing.
The main reason why I would add the feature is consistency though. A NimNode has seq-like children, and when I use [] I intuitively expect it to behave like a seq. It always comes as a surprise that it behaves almost like a seq, but when you want subslicing you have to fall back to a work-around of importing sequtils and converting it to a full-blown seq first, and slice it as a second step.
Most helpful comment
And I think it is natural to implement
`[]`(n: SomeType, s:HSlice[T, U]): seq[SomeType]if there is`[]`(n: SomeType, i: int): SomeType.