Nim: Add "proc `[]`(n: NimNode, s: HSlice[int, T])"

Created on 22 Apr 2018  路  8Comments  路  Source: nim-lang/Nim

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 but expected one of:
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

expression:
```

Feature Macros

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.

All 8 comments

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:

  • What I don't like about 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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mratsim picture mratsim  路  38Comments

abudden picture abudden  路  46Comments

dom96 picture dom96  路  30Comments

kaushalmodi picture kaushalmodi  路  25Comments

timotheecour picture timotheecour  路  33Comments