В настоящее время сопоставление с образцом в Nim работает только с tuples
. Это также имеет смысл, потому что сопоставление с образцом требует статически известной арности. Например, что должно произойти в вашем примере, если длина seq
не равна трем? Обратите внимание, что в вашем примере длина последовательности может быть определена только во время выполнения, поэтому компилятор не знает, действительно ли возможно извлечь три переменные.
Поэтому я думаю, что решение, на которое ссылается @def-, идет в правильном направлении. В этом примере используются массивы, которые действительно имеют статически известный размер. В этом случае компилятор знает арность кортежа, т. е. извлечение определено корректно.
Если вам нужен альтернативный (возможно, удобный, но небезопасный) подход, вы можете сделать что-то вроде этого:
import macros
macro extract(args: varargs[untyped]): typed =
## assumes that the first expression is an expression
## which can take a bracket expression. Let's call it
## `arr`. The generated AST will then correspond to:
##
## let <second_arg> = arr[0]
## let <third_arg> = arr[1]
## ...
result = newStmtList()
# the first vararg is the "array"
let arr = args[0]
var i = 0
# all other varargs are now used as "injected" let bindings
for arg in args.children:
if i > 0:
var rhs = newNimNode(nnkBracketExpr)
rhs.add(arr)
rhs.add(newIntLitNode(i-1))
let assign = newLetStmt(arg, rhs) # could be replaced by newVarStmt
result.add(assign)
i += 1
#echo result.treerepr
let s = @["X", "Y", "Z"]
s.extract(a, b, c)
# this essentially produces:
# let a = s[0]
# let b = s[1]
# let c = s[2]
# check if it works:
echo a, b, c
Я еще не включил проверку длины seq
, поэтому вы просто получите ошибку выхода за пределы, если последовательность не имеет требуемой длины. Еще одно предупреждение: если первое выражение не является литералом, выражение будет оцениваться/вычисляться несколько раз.
Обратите внимание, что литерал _
разрешен в привязках let в качестве заполнителя, что означает, что вы можете делать такие вещи:
s.extract(a, b, _, _, _, x)
Это будет относиться к вашему примеру splitLine[0..1, 5]
, который, кстати, просто не является допустимым синтаксисом индексации.
person
bluenote10
schedule
12.08.2015