[0..min(10,^1)]
why Nim is not powerful enough to do something like that? :)type
MinPair = (int, BackwardsIndex)
proc min(idx: int, back: BackwardsIndex): MinPair = (idx, back)
proc `[]`[T](s: seq[T], idx: HSlice[int, MinPair]): seq[T] = s[idx.a .. min(idx.b[0], s.len - idx.b[1].int)]
echo @[1,3,4,5,5][0 .. min(10, ^1)]
echo @[1,3,4,5,5][0 .. min(2, ^1)]
@[1, 3, 4, 5, 5]
@[1, 3, 4]
why Nim is not powerful enough to do something like that?
The "power" of Nim is the fact that you can use the entire language (yes, including "garbage collection" and "exception handling" or whatever else it is that kernel developers in 2021 are still unfamiliar with) for:
A language's power lies not at "can I have my favorite syntax in Nim". But as @haxcramper has shown in this case you got lucky and Nim can support it. :-)
I managed to make this into a general thing!
import fusion/matching
import std/macros
{.experimental: "caseStmtMacros".}
proc rewriteBackwardIndices(n: NimNode; lenNode: NimNode): NimNode =
case n
of Prefix([== ident"^", @i]):
return quote: `lenNode` - `i`
else:
if n.kind in AtomicNodes:
return n
else:
result = newTree(n.kind, @[])
for child in n.children:
result.add child.rewriteBackwardIndices(lenNode)
macro get[T](s: seq[T], i: untyped): untyped =
let lenNode = quote: len(`s`)
let rewritten = i.rewriteBackwardIndices(lenNode)
quote: s[`rewritten`]
let s = @[3, 6, 9, 2, 5, 8, 1, 4, 7]
echo s.get(min(20, ^1))
echo s.get(min(3, ^1))
echo s.get(^1 div 2) # middle element
echo s.get(2..(^6 * 2))
Any ideas how to allow the [] syntax without having the macro try to call itself?