Кортежи
QSP позволяет упаковывать несколько значений в одну переменную, а затем извлекать их оттуда. Упакованные данные называются “кортеж”.
Чтобы создать кортеж, нужно присвоить переменной, имя которой начинается с символа %, группу значений, перечисленных в квадратных скобках через запятую. Пример:
! создаём кортеж
%personage = ["Петя", 27, 182, 92, "боксёр"]
Когда мы создаём кортеж, это называется упаковкой данных. Обратный процесс называется распаковкой:
! распаковываем данные из кортежа
$name, age, height, weight, $sports = %personage
Кортежи можно помещать и в отдельные ячейки массивов:
%personage[0] = ["Петя", 27, 182, 92, "боксёр"]
%personage[1] = ["Вася", 32, 162, 57, "жокей"]
%personage[2] = ["Маша", 19, 158, 42, "фигуристка"]
%personage[3] = ["Даша", 24, 202, 81, "баскетболистка"]
В кортежи можно помещать значения любых типов, в том числе и другие кортежи:
%unit = [187, 94, 'steel', [0, 2]]
Допустимо использовать круглые скобки () для перечисления значений кортежа, однако рекомендуется использовать именно квадратные скобки [] для улучшения читаемости кода.
%q = (65,'ddd')
%q = () & ! пустой кортеж
%q = (56, (32,'sdsd'), 3)
Так же допустимо совсем опускать скобки при присваивании значений кортежу, однако такая запись тоже не рекомендуется, потому что плохо читаема:
%q = 65,'ddd'
local %q = 65,'ddd',33
Операции с кортежами
Объединение кортежей (конкатенация) &
Для объединения кортежей в один кортеж нужно использовать операцию конкатенации. Общая запись:
[%новый_кортеж] = ([%кортеж_1] & [%кортеж_2] & ...)
В данном случае ставить скобки обязательно. Только так плеер поймёт, что это операция конкатенации, а не перечисление команд через амперсанд &.
Пример:
%tpl = ([1, 2] & [3, 4])
! в переменную %tpl будет записан кортеж [1, 2, 3, 4]
Эта же операция используется для добавления отдельных значений в кортеж:
%tpl = [1, 2, 3, 4]
%tpl = (%tpl & 5)
%tpl & ! [1,2,3,4,5]
Увеличение значений кортежа +
Общая запись:
[%новый_кортеж] = [%кортеж_1] + [значение]
При выполнении данной операции к каждому элементу кортежа [%кортеж_1] будет прибавлен элем ент [значение]. [значение] может быть кортежем, тогда каждый элемент [%кортеж_1] будет сложен с кортежем [%значение]. Примеры:
%tuple = [4, 10, 16]
%a = %tuple + 2
! %a будет равно [6, 12, 18]
[4, 10] + ['b', 'x'] & ! [4 + ['b', 'x'], 10 + ['b', 'x']]
! [['4b','4x'], ['10b','10x']]
Уменьшение значений кортежа -
Общая запись:
[%новый_кортеж] = [%кортеж_1] - [#значение]
При выполнении данной операции из каждого элемента кортежа [%кортеж_1] будет вычтен элемент [#значение]. [#значение] может быть только числом. Все остальные варианты приведут к ошибке о несоответствии типов данных. Примеры:
%tuple = [4, 10, 16]
%a = %tuple - 2
! %a будет равно [2, 8, 14]
[4, 10] - ['b', 'x'] & ! ошибка о несоответствии типов данных
Увеличение значений кортежа *
Общая запись:
[%новый_кортеж] = [%кортеж_1] * [#значение]
При выполнении данной операции каждый элемент кортежа [%кортеж_1] будет умножен на значение элемента [#значение]. [#значение] может быть только числом. Все остальные варианты приведут к ошибке о несоответствии типов данных. Примеры:
%tuple = [4, 10, 16]
%a = %tuple * 2
! %a будет равно [8, 20, 32]
[4, 10] * 'b' & ! ошибка о несоответствии типов данных
Сокращение значений кортежа /
Общая запись:
[%новый_кортеж] = [%кортеж_1] / [#значение]
При выполнении данной операции каждый элемент кортежа [%кортеж_1] будет поделён на значение элемента [#значение]. [#значение] может быть только числом. Все остальные варианты приведут к ошибке о несоответствии типов данных. Примеры:
%tuple = [4, 10, 16]
%a = %tuple / 2
! %a будет равно [2, 5, 8]
[4, 10] / 'b' & ! ошибка о несоответствии типов данных
Отрицание кортежей (''-'' унарный минус)
Общая запись:
[%новый_кортеж] = -[%кортеж_1]
Эта операция эквивалентна умножению кортежа на -1. Т.е. значения всех элементов кортежа будут умножены на -1. Примеры:
%tpl = -[2] & ! [-2]
-[5,6,7] & ! [-5,-6,-7]
! a = 12
-[a, a+2, a+4] & ! [-12,-14,-16]
-[5,6,7]+3 & ! [-2,-3,-4]
-([5,6,7]+3) & ! [-8,-9,-10]
-[1,[2,-3],-4] & ! [-1,[-2,3],4]
Операции с присваиванием
Операции с присваиванием +=, -=, *= и /= применимы для кортежей.
Только в операции += можно добавлять к элементам кортежей значения любых типов. В операциях -=, *= и /= можно использовать только целые значения.
Примеры:
%tuple = [5, 10, 15]
%tuple /= 5
! %tuple будет равно [1, 2, 3]
%tuple *= 10
! %tuple будет равно [10, 20, 30]
%tuple -= 10
! %tuple будет равно [0, 10, 20]
%tuple += 13
! %tuple будет равно [13, 23, 33]
Сравнение кортежей
Любые операции сравнения можно использовать и для сравнения кортежей. При этом:
-
Кортежи сравниваются поэлементно, и большим оказывается тот кортеж, элемент которого оказался большим. Примеры:
%one = [12, 13, 14]%two = [12, 13, 99]! %one < %two т.к. 14 < 99%three = [13]! %three > %one т.к. 13 > 12 -
Любой непустой кортеж, всегда больше пустого кортежа. Отсюда следует, что если кортежи разной длины, можно представить недостающие элементы более короткого кортежа, как пустые элементы, а они всегда меньше непустых. Примеры:
%one = [12]%two = ['']%empty = []! %one > %empty! %two > %empty%three = [12, '']! %three > %one -
при сравнении кортежа с числом или строкой, число или строка воспринимаются движком как кортеж из одного элемента:
%one = [12, 13]! %one > 12! %one < 13! [] < 0 т.к. [0] - не пустой кортеж
Функции и операторы, работающие с кортежами
-
LEN([%кор])- возвращает число элементов кортежа[%кор].*pl LEN([5,7,'a']) &! на экране будет число 3 -
ISNUM([%кор])- проверяет, можно ли преобразовать[%кор]в число. Функция возвращает0(ложь) или1(истина).ISNUM([' 9999 ']) &! 1ISNUM([' -888']) &! 1ISNUM(['777a6']) &! 0ISNUM(['']) &! 0, т.к пустая строка не содержит числаISNUM(['1', '1']) &! 0, т.к. кортеж из двух значенийISNUM([1, 1]) &! 0, т.к. кортеж из двух значений -
VAL([%кор])- переводит кортеж[%кор]в соответствующее число. Если преобразование невозможно, возвращает0.val(['123']) & ! увидим 123val(['']) & ! увидим 0val(['1', 1]) & ! увидим 0 -
$STR([%кор])- переводит кортеж в строку.*pl $STR([5,7,'a']) &! на экране увидим [5,7,'a'] -
%ARRPACK([$имя_массива], [#начальный_индекс], [#количество])- упаковывает массив[$имя_массива]в кортеж.-
Можно указать, сколько элементов
[#количество]упаковать в кортеж, и с какого элемента[#начальный_индекс]начинать упаковку. Параметры опциональны, по умолчанию[#начальный_индекс]равен нулю, а[#количество]соответствует размеру массива. -
Функция возвращает кортеж с упакованными значениями.
-
Примеры:
LOCAL type, name = %ARRPACK('args')! Из массива char берём пять элементов, начиная со второго, и упаковываем в кортеж:%unit[123] = %ARRPACK('char', 2, 5)
-
-
UNPACKARR [$имя_массива], [%кортеж], [#начальный_индекс], [#количество]- распаковывает значения из кортежа[%кортеж]в массив[$имя_массива].-
Можно указать, сколько элементов
[#количество]распаковать, и с какого элемента[#начальный_индекс]начинать распаковку. Параметры опциональны, по умолчанию[#начальный_индекс]равен нулю, а[#количество]соответствует длине кортежа. -
Пример:
UNPACKARR 'A', ['тест','нескольких','значений',67, ['вложенный кортеж']]! $A[0] будет содержать 'тест'! $A[1] будет содержать 'нескольких'! $A[2] будет содержать 'значений'! A[3] будет содержать 67! %A[4] будет содержать ['вложенный кортеж'] -
оператор позволяет извлечь из кортежа одно значение по указанному индексу:
%tpl = ['тест','нескольких','значений',67, ['вложенный кортеж']]UNPACKARR 'A', %tpl, 3, 1! в A будет 67
-
Индексация ячеек массивов через кортежи
Мы можем индексировать ячейки массивов с помощью кортежей, точно так же, как и с помощью строк. При этом повторяющиеся квадратные скобки можно и нужно опускать для лучшей читаемости кода. Таким образом можно создавать многомерные массивы:
! многомерный массив:
$map[1,2] = 'space'
$map[1,3] = 'space'
$map[5,7] = 'tree'
$map[0,-1] = 'hero'
*pl $map[x,y]
! можно, но не рекомендуется,
! писать так:
$map[[1,2]] = 'space'
$map[[1,3]] = 'space'
$map[[5,7]] = 'tree'
$map[[0,-1]] = 'hero'
*pl $map[[x,y]]
Почитать про многомерные массивы можно в соответствующем подразделе раздела “Массивы”.
Опускать повторяющиеся скобки нельзя, если для индексации используются кортежи, состоящие из одного значения.
Кортеж из одного значения
В QSP 5.9.0 появилась возможность создавать кортежи из одного значения. Например:
%tuple = [-1]
*pl %tuple & ! [-1]
С помощью таких кортежей можно индексировать массивы, обходя ограничение на отрицательные индексы ячеек. Но в этом случае необходимо сохранять повторяющиеся квадратные скобки:
$line_map[[-1]] = 'personage'
*pl $line_map[[-1]]
Возвращение нескольких значений из функции
Поскольку кортежи позволяют упаковывать в переменную несколько значений, появилась возможность возвращать из пользовательской функции сразу несколько значений, используя распаковку:
!foo
%result = [12, 45]
!start
x, y = @foo()
Ограничения кортежей
-
Используя лишь одну пару квадратных скобок нельзя создать кортеж из более чем двадцати элементов. Пример попытки создать кортеж из 21 элемента:
%tpl = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]! это приведёт к ошибке: Неверное число аргументов операции/функцииОднако вы можете создать кортеж, сколько угодно большой длины, используя конкатенацию:
%tpl = ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] & [21])Настоятельно не рекомендуется создавать кортежи большой длины.
-
Кортежи нельзя изменять. То есть, например, в кортеже из трёх элементов нельзя заменить второй элемент. Нужно распаковать кортеж в переменные, изменить одну из переменных и снова упаковать в кортеж:
%pos_in_space = [12, -3, 9]x, y, z = %pos_in_spacey = -13%pos_in_space = [x, y, z] -
Нельзя извлечь из кортежа одно конкретное значение, например, второе. Зато можно извлекать одно или несколько первых значений. В этом случае из набора переменных, в которые распаковывается кортеж, имя последней должно начинаться с символа
%, так как в эту переменную будет упаковываться оставшаяся часть кортежа:%personage = ["Петя", 27, 182, 92, "боксёр"]$name, %tail = %personage*pl $name &! 'Петя'$name, age, height, %tail = %personage*pl "Имя: <<$name>>, возраст: <<age>>, рост: <<height>>."weight, $sports = %tail*pl $sports -
Как и в строках, предел объёмов данных для кортежа 2 Гигабайта или 2147483648 элементов. Величина кортежа не может превысить объём оперативной памяти.