Описание функциональности всех блоков вы можете посмотреть в справочнике, а на этом занятии мы остановимся на особенностях работы некоторых блоков.
Чем отличается начинающий программист от опытного? Тем, что он сразу начинает программировать, а опытный вначале изучит инструменты, с которыми ему придётся работать. Иначе может получиться так, как у многих пользователей Thunkable X, которые много дней делают свой проект, а потом выясняется, что необходимой функциональности в Thunkable X ещё нет, и закончить проект не получится, либо для завершения проекта придётся приложить много усилий для реализации отсутствующей функциональности.
Изучать блоки можно и в процессе разработки, но блоков в Thunakble X немного, и, если вы вначале изучите их, то при разработке своего проекта вам будет на порядок проще и интереснее его создавать.
Control
Если после блока navigate to расположены другие блоки, то они будут выполнены.
Блок wait seconds используйте только в том случае, если без него действительно невозможно обойтись. Если ваши блоки начинают работать с данными правильно только при использовании этого блока, то в 95% ваши блоки содержат ошибку. Вспомните о том, что запись и получение данных не может происходить моментально, и всегда существует задержка, а механизм выполнения блоков може быть синхронным или асинхронным.
Logic
Все блоки данной категории можно присоединять не только к условным блокам if, но и переменным. Это позволит упростить сложные блоки if.
Операция or вычисляет все операнды до первого, который вернёт true (спотыкается на true) и возвращает его. Если все операнды ложные, то возвращается последний из них. Например,
false or 0 or 5 вернёт значение 5
"" or "test" вернёт "test"
100 or 0 вернёт 100
Операция and вычисляет все операнды до первого false (спотыкается на false) и возвращает его. Если все операнды истинные, то возвращается последний из них.
false or 0 or 5 вернёт значение false
"" or "test" вернёт ""
100 or 10 вернёт 10
Некоторые блоки в Thunkable X могут в локальном блоке вернуть значение null, которое не равно значению блока null. Это выглядит очень странно, и для устранения таких ошибок необходимо при помощи блока join привести значение локальной переменной к строковому типу и сравнить его со строкой "null":
if <- join <- [( myValue ) = ( "null" )]
do <- from Label1 set Text <- "Value is null"
При использовании операций сравнения (>,>=,<,<=,=) операнды приводятся к числовому типу, если оба операнда не являются строками.
При сравнении объектов сравниваются ссылки на них.
Существует специальное правило - undefined = null. Если значение переменной может быть равно undefined или null, то при помощи этой операции сравнения невозможно определить точное значение переменной. Необходимо использовать дополнительную проверку на равенство null, как это было показано в примере выше.
При использовании блоков логических операций or или and операнды приводятся к логическому типу.
Math
Использование математических блоков не должно вызывать сложностей, но при этом может произойти потеря точности:
myVar <- [[( 0.1 ) + (0.2)] = (0.3)] // false
Для исправления таких ошибок используйте блок ограничения точности with decimal places:
myVar <- [ [( 0.1 ) + (0.2)] with 2 decimal places ] = (0.3)] // true
Блок remainderof (остаток от деления) можно использовать для создания периодически повторяющегося ряда чисел. Это часто используется в графических приложениях для отображения фигур, упорядоченных по колонкам и строкам.
Эту задачу можно решить при помощи вложенных циклов, но благодаря "remainder of" используется один цикл, что выглядит проще.
Text
Некоторые блоки для работы с текстом можно использовать и для работы со списками. Если к такому блоку присоединить переменную, содержащую список, то он буде преобразован в строку с разделителями.
В блоке in text get substring можно использовать отрицательные числа. В этом случае позиции символов будет отсчитываться от конца строки. Значение параметра from по абсолютной величине должно быть больше параметра to по абсолютной величине.
В блоке in text get не используйте отрицательные числа.
При использовании символов Юникода нужно помнить о том, что многие символы являются двухсимвольными и блок length of для них вернёт значение 2. Это нужно учитывать при использовании блоков для работы со строками.
Блок intextget корректно работает только односимволными сущностями. Для получения двухсимвольного Юникод-символа используете блок in text get substring.
Понятия "пустая строка" и "строка не содержит символы" могут иметь разный смысл. Существуют невидимые символы Юникода, которые можно добавить в строку, но пользователь их не увидит при выводе этой строки на экран. То есть, зрительно строка будет пустой, но в то же время она будет содержать символы, что можно проверить путём её копирования и дальнейшего вычисления её длины.
Вывод текста вертикально:
myVar <- "This is a string"
myVar <- [ make list from text (
myVar ) with delimiter ( "" ) ]
from Label1 set Text <- [
make text from list (
myVar ) with delimiter ( newline ) ]
Lists
Некоторые блоки для работы со списками можно использовать и для работы со строками. Если такому блоку передать строку, то он будет работать с ней как со строкой. Например, если блоку shuffle передать строку, то он вернёт список букв в случайном порядке. Если после этого выполнить текстовой блок length of, то он вернёт длину списка, а не количество символов. Если же нужно посчитать количество символов в результате выполнения блока shuffle, то используйте блок join для преобразования в строку:
x <- "Hello"
y <- shuffle (x)
z <- length of <- y // 5
z <- length of <- join <- y // 9
Если нужно вернуть случайную букву из строки, то можно использовать блок random item.
Блок does list contain вернёт true, если значение элемента списка в точности соответствует проверяемому значению от начала и до конца строки, тогда как текстовой блок does contain вернёт true, если текст содержит проверяемое значение (в начале, в конце или внутри себя). Это нужно учитывать при поиске текста.
Существует несколько видов поиска:
Каждый вариант поиска имеет свои преимущества. Самым точным является последний вариант, потому что в нём учитываются все фрагменты, которые ввёл пользователь.
Objects
Блоки для работы с объектами использовать несложно, но часто эта работа заканчивается ошибкой из-за непонимания формата данных JSON.
При работе с объектами я рекомендую использовать переменные функции и не использовать глобальные переменные. Как быть, если объект нужно передать из одного экрана в другой? Для этого перед переходом на другой экран необходимо блок переменной функции присоединить глобальному блоку напрямую, или преобразовав их вначале в строку JSON. При открытии другого экрана производится обратная операция: блок глобальной переменной присоединяется к переменной функции для того, чтобы опять работать с ними при помощи переменной функции. Учтите, при работе с объектами переменные функции работают как ссылки на объекты. Если вы не знаете, что такое ссылка, то изучите первый урок.
JSON
Работа с данными JSON у многих вызывает сложности, но на самом деле всё достаточно просто, если понять несколько ключевых моментов.
Данные JSON представляют собой древовидную структуру данных, состоящую из объектов, свойства которых могут хранить данные разных типов:
Объект, который вложен в другой объект, называется дочерним, а содержащий его объект – родительским. При этом объект, который не имеет родителя, называется корневым. Примеры JSON-данных:
{} – пустой объект
[] – пустой массив
[{}] – массив объектов, который содержит один пустой объект
[{},{}] - массив объектов, который содержит два пустых объекта
Пример набора объектов:
{ "object1":{}, "object2":{}, "object3":{} }
В этом примере корневой объект содержит набор из трёх дочерних объектов - это не массив!
Как правило, объекты содержат в себе данные, которые хранятся в виде пары "ключ:значение". Ключ можно понимать как переменную, а значение – как значение переменной, но применительно к объектам более правильно воспринимать ключ в качестве свойства объекта.
Ниже показан объект, который имеет два непустых свойства:
{ "name":"Robin", "age":25 }
Имена ключей должны заключаться в двойные кавычки и быть уникальными для ключей одного уровня:
{ "name":"Robin", "name":25 //ошибка, дублирования ключа }
Рассмотрим пример сложной структуры
{ "objects": [{ "detail": { "age": 25, "contacts": { "email": "test@test.com", "tel": "+2222222222" } } }, { "detail": { "age": 25, "contacts": { "email": "test@test.com", "tel": "+7777777777" } } }] }
Корневой объект имеет только одно свойство "objects", значением которого является массив из двух объектов, каждый из которых содержит свойство "contacts", значением которого является объект
Найдём значение свойства "tel", выделенное жирным цветом. Для получания значения ключа необходимо составить путь до него. Путь удобнее составлять от этого значения, а не от корня объекта, как при работе с файлами.
Для составления пути нужно давать ответы на вопрос, где хранится (кому принадлежит) значение или свойство.
Где хранится значение "+7777777777"? В свойстве tel. Добавляем это свойство в строку пути:
tel
Где хранится свойство tel? В свойстве contacts. Добавляем его к пути:
tel/contacts
Где хранится свойство contacts? В свойстве detail. Добавим его к пути:
tel/contacts/detail
Где хранится свойство detail? В объекте массива с индексом 2. Добавим его к пути:
tel/contacts/detail/2
Где хранится массив? В свойстве objects. Добавим его к пути:
tel/contacts/detail/2/objects
Где хранится свойство object? В корневом объекте – построение пути завершено.
После этого осталось соединить друг с другом блоки, указав в них названия свойств и объекты.
Если в качестве корневого элемента выступает массив, то здесь также нет ничего сложного:
[{ "number":12 }, { "number":13 }]
Где хранится хранится значение 12? В свойстве number. Добавим его к пути:
number
Где хранится свойство number? В первом объекте массива. Добавим его к пути:
number/1
Где хранится массив? Это корневой объект – построение пути завершено.
Какую структуру данных выбрать – массив объектов или набор объектов? Для доступа к объекту массива необходимо указать его индекс в массиве, а для доступа к объекту набора – имя ключа (свойства), значением которого является данный объект. На практике удобнее работать с именованными сущностями, но, если исходная структура объектов будет меняться, то удобнее использовать массив объектов. В этом случае для выполнения операции удаления, добавления или вставки объекта в массив используются имеющиеся блоки для работы со списком.