Новые типы данных в скриптах JAWS

(По материалам Freedom Scientific)
Дата публикации:25.05.2010
Дата обновления:12.01.2017
Поделиться в Twitter Поделиться в F******k Поделиться в VKontakte Поделиться в Telegram Поделиться в Mastodon

После выхода обновления программы экранного доступа JAWS for Windows версии 11.0.1430 в скриптах JAWS стали доступны новые типы данных, обзор которых представлен в данной статье. Рассматриваются только те нововведения в скриптах JAWS, которые нашли отражение в официальном пособии по написанию скриптов "Basics of Scripting", а также изменения в последующих версиях JAWS, упомянутые в официальной документации.

Массивы

Массивы могут содержать элементы одного из стандартных типов данных в скриптах JAWS. Объявляется массив как тип данных, за которым сразу (без пробела) следует слово array:

Var
StringArray names,
IntArray ages,
VariantArray mixed
...

Массив типа VariantArrays может содержать элементы разных типов. Объявление массива не приводит к его немедленному созданию. Массив должен быть создан при помощи ключевого слова new:

Var
  StringArray strings

  let strings = new StringArray[50]
...

В примере создаётся пустой одномерный массив, состоящий из 50-ти строковых элементов. В квадратных скобках указывается число элементов в массиве.

  let strings = new StringArray[50,5]

Создаст двумерный строковый массив, который можно логически представить как таблицу из 50 строк (рядов) и 5 столбцов. Каждая ячейка такой таблицы является строковой переменной JAWS. Здесь количество элементов в массиве задаётся двумя числами – по одному для каждой размерности.

Для доступа к элементам массива используется оператор []. Внутри [] должно находиться одно индексное значение для каждой размерности массива. Первый элемент массива имеет единичные индексы для каждой размерности, то есть индекс меньше 1 является некорректным. Так, для двумерного строкового массива из примера выше:

  SayString(strings[1,3])

Вернёт и озвучит элемент из третьего столбца первой строки (ряда).

Присваивание значения элементу массива выполняется при помощи обычного оператора присваивания, а в квадратных скобках указывается индекс того элемента, которому необходимо присвоить значение:

Var
	IntArray Numbers

	let Numbers = new IntArray[10]
	let Numbers[1] = 55
...

Массивы передаются в функции как параметры и возвращаются как результат всегда по ссылки.

Присваивание одного массива другому приведет к тому, что две переменные будут ссылаться на один и тот же массив. Таким образом, происходит копирование ссылки, а не копирование содержимого массива. Это вызвано тем, что разработчики стремились синизить потери производительности при такой операции. Так что при использовании массивов необходимо проектировать скрипт так, чтобы не возникло необходимости копировать массивы (в противном случае придётся это делать поэлементно в самом скрипте, что сделает операцию ещё более медленной).

Обратите внимание, что во время компиляции или во время выполнения не генерируется никаких сообщений об ошибке, если индекс вышел за границы массива. Просто возвращается пустой элемент соответствующего типа (0 для int, пустая строка для String и т.п.), а присваивание значения несуществующему элементу игнорируется.

Функции для работы с массивами

В JAWS версии 14 появилась встроенная функция ArrayLength для определения длины массива (одномерного или по одному измерению). В качестве параметра функция принимает массив и возвращает целочисленное значение, равное его длине.

В JAWS версии 17.0 была добавлена встроенная функция StringArrayCompact, которая на основе строкового массива, переданного в качестве параметра, создаёт новый (компактный) строковый массив, из которого исключены пустые элементы .

Также в JAWS версии 17 появилась функция StringArrayConcat, которая создаёт новый строковый массив, копируя в него последовательно элементы двух строковых массивов, переданных в качестве первого и второго параметров. В качестве необязательного третьего параметра можно передать True, если необходимо, чтобы результирующий массив имел компактную форму.

Коллекции

Коллекции – это новый тип данных. Каждый элемент коллекции представляет собой пару имя - значение. Имя (также называемое "ключом") всегда является строкой, а значение может иметь любой допустимый в JAWS тип данных. Объявление коллекции в секции Var не создаёт её. Для создания коллекции необходимо использовать ключевое слово new:

Var
  Collection MonthDays

  let MonthDays = new collection
...

Существует два способа получить доступ к элементу коллекции. Если на этапе написания скрипта известно имя элемента, то доступ к элементу коллекции можно получить при помощи оператора . (точка):

  let MonthDays.february = 28
  SayInteger(MonthDays.February)

Если имя элемента коллекции задаётся строковым литералом (строкой в двойных кавычках), строковой переменной или результатом вызова функции, то можно использовать оператор [], поместив в него строковый литерал, имя переменной или вызов функции:

Var
  string MonthName

  let MonthName = "january"
  let MonthDays[MonthName] = 31    

Оператор . и оператор [] могут использоваться попеременно для одной и той же коллекции.

Элементы коллекции создаются в момент выполнения первого присваивания. Когда элементу коллекции присваивается значение, то этот элемент автоматически получает тот же тип данных, что и тип данных присваиваемого значения. Однако когда извлекается значение элемента коллекции, то контроль за соответствием типов элемента коллекции и переменной, которой присваивается значение, полностью ложится на плечи программиста. Во время компиляции скрипта проверка соответствия типов переменной и элемента коллекции не выполняется. Не предусмотрено никаких стандартных способов узнать тип элемента коллекции во время выполнения скрипта. Однако стоит заметить, что во время исполнения скрипта JAWS пытается выполнить приведение типов, которое может оказаться успешным для некоторых случаев присваивания (например, числовое значение элемента коллекции может быть корректно преобразовано в значение строковой переменной, строка из цифр может быть корректно преобразована в число и так далее).

Попытка получить несуществующий элемент не генерирует сообщение об ошибке.

Коллекции передаются функциям как параметры и возвращаются как результат всегда по ссылке.

Присваивание одной коллекции другой приведёт к тому, что две переменные будут ссылаться на одну и ту же коллекцию, то есть выполняется копирование ссылки, а не копирование содержимого коллекции.

Имена всех элементов, содержащихся в коллекции, можно перебрать при помощи оператора ForEach, о котором будет сказано ниже .

Массивы могут быть членами коллекций, а коллекции могут быть элементами массивов, если это массивы типа VariantArray.

Поскольку в JAWS 11.0 не был предусмотрен стандартный способ получения количества элементов в коллекции, то при необходимости в качестве варианта можно использовать приём, встречающийся в скриптах JAWS. В коллекции создаётся элемент, например, с именем Count, который увеличивается на единицу при каждом добавлении нового элемента в коллекцию. Чтобы избежать ошибок, необходимо операцию добавления элемента в коллекцию оформить в виде отдельной функции, в которой и увеличивать значение счётчика элементов Count. В более поздних версиях JAWS необходимость в подобных трюках отпала.

Функции для работы с коллекциями

В JAWS версиях 12.0 и более поздних были документированы несколько функций для работы с коллекциями. Они перечислены ниже:

ФункцияОписание
Int CollectionCompare ( Collection, Collection )Сравнивает содержимое двух коллекций, переданных в качестве параметров. Возвращает True, если содержимое коллекций совпадает; иначе возвращает False.
Collection CollectionCopy ( Collection )Выполняет полное копирование коллекции, переданной в качестве параметра. В отличие от простого присваивания переменных типа Collection, когда разные переменные ссылаются на одну и ту же коллекцию, эта функция создаёт полную независимую копию исходной коллекции.
Int CollectionItemCount ( Collection )Возвращает количество элементов в коллекции, переданной в качестве параметра. Функция появилась в JAWS версии 14.0.
Int CollectionItemExists ( Collection, String )Возвращает True, если элемент с именем, указанным во втором параметре, содержится в коллекции, указанной в первом параметре. В противном случае возвращается False.
Void CollectionRemoveAll ( Collection )Удаляет все элементы из коллекции, переданной в качестве параметра.
Int CollectionRemoveItem ( Collection, String )Удаляет из коллекции, указанной в первом параметре, элемент с именем, указанным во втором параметре. Возвращает True, если удаление прошло успешно; иначе -- False.

Оператор For

Этот оператор имеет следующий синтаксис:

for x = start to end
  ...
EndFor

Где x это локальная переменная типа Int, а start и end могут быть целочисленными константами, целочисленной переменной, а также любым выражением, возвращающим значение типа Int . Обычно переменная цикла x увеличивается от start до end, но при использовании ключевого слова descending переменная цикла будет уменьшаться на единицу при каждой итерации цикла. Соответственно, значение start в таком цикле должно быть больше, чем значение end.

for x = start to end descending
  ...
EndFor

При необходимости переменную цикла x можно изменять внутри цикла. Это можно использовать, чтобы изменить шаг цикла или осуществить преждевременный выход из цикла. Пример цикла, озвучивающего только чётные числа:

for x = 1 to 10
	let x = x + 1
	SayInteger(x)
EndFor

Оператор ForEach

Оператор ForEach имеет два варианта использования. Он позволяет перебрать (последовательно обойти) все имена элементов, содержащихся в коллекции. В этом случае локальная переменная, используемая для последовательного получения имён элементов, должна иметь тип String.

Var
  String month

  ForEach month in MonthDays
    SayString(Month)
    SayInteger(MonthDays[Month])
  EndForEach

Предполагается, что коллекция MonthDays предварительно была заполнена элементами, имена которых являются названиями месяцев, а значения – количеством дней в соответствующем месяце.

Обратите внимание, что нельзя делать никаких предположений относительно порядка следования элементов коллекции при переборе их при помощи ForEach. Оператор ForEach лишь гарантирует, что будут перечислены все элементы, содержащиеся в коллекции. Это объясняется тем, что имена элементов внутренне сохраняются в хеш-таблице или сортированном списке, чтобы обеспечить быстрый доступ к элементам коллекции.

Оператор ForEach также может быть использован для перебора элементов внутри COM-объекта, поддерживающего интерфейс IEnumVARIANT. Это можно использовать, например, по отношению к объектам Documents в приложениях Microsoft Word & Excel. В этом случае локальная переменная, получающая очередной элемент, должна иметь тот же тип, что и значения, возвращаемые IEnumVARIANT конкретного COM-объекта. Для объекта Documents из Word & Excel это будет тип object.

Инициализация переменных

Теперь можно инициализировать переменные (то есть присваивать им начальные значения) во время их объявления в секции Var. Кроме того, использование результата вызова функции для инициализации переменных не приводит к ошибке:

Var
  Int x = 759,
  Int y = 60 * 60 *24,
  String Message ="Привет!" ,
  String sLang = GetSystemDefaultLang()
	...


Распространение материалов сайта означает, что распространитель принял условия лицензионного соглашения.
Идея и реализация: © Владимир Довыденков и Анатолий Камынин,  2004-2024