Найти в Дзене
Эксперименты с Renga

Работа с формулами в Renga. Неявное приведение типов и использование null значений на стороне добра (теория и практика)

Статья написана с использованием Renga версии 5.10.48974.0 Теория Небольшое вступление Для удобства различия в тексте значений и формул, используемых в свойствах, я буду брать их в такие скобки < >. Отдельно о записи вида <null> - она будет отражать неинициализированное значение (имеется по умолчанию для определенных типов, также возникает в процессе вычисления формул). Пользователь видит это в окне «Свойства» у экземпляров объектов Renga, как просто отсутствие какого-либо значения. Одним словом, любая ошибка при вычислении значения формулы (причем не важно, в каком месте формулы она возникла) по причине использования некорректного имени свойства/параметра, неправильного применения функций и операторов Renga, несоответствия полученного значения типу свойства и т.д. и т.п. приводит нас в итоге к получению неинициализированного значения. Далее мы научимся использовать данную концепцию разработчиков Renga, чтобы получить явное указание на отсутствие результата значения или проигнорировать
Оглавление

Статья написана с использованием Renga версии 5.10.48974.0

Теория

Небольшое вступление

Для удобства различия в тексте значений и формул, используемых в свойствах, я буду брать их в такие скобки < >.

Отдельно о записи вида <null> - она будет отражать неинициализированное значение (имеется по умолчанию для определенных типов, также возникает в процессе вычисления формул). Пользователь видит это в окне «Свойства» у экземпляров объектов Renga, как просто отсутствие какого-либо значения. Одним словом, любая ошибка при вычислении значения формулы (причем не важно, в каком месте формулы она возникла) по причине использования некорректного имени свойства/параметра, неправильного применения функций и операторов Renga, несоответствия полученного значения типу свойства и т.д. и т.п. приводит нас в итоге к получению неинициализированного значения.

Далее мы научимся использовать данную концепцию разработчиков Renga, чтобы получить явное указание на отсутствие результата значения или проигнорировать определенное значение. Нетерпеливые, конечно, могут сразу пролистать к практике :))) (она ближе к концу статьи). Ну а я пока продолжу.

1. Краткое рассмотрение типов значений в Renga

По сути, нам для понимания неявного приведения (преобразования) типов нужны будут далее только следующие типы значений: Целое, Действительное, Строка, Булевый, Логический. Ну и конечно же <null>.

Почему?

У Типа Перечисление выходное значение всегда является строковым типом, но с формулами он не работает. Поэтому нам он сейчас не интересен.
Оставшиеся типы:
Длина, Площадь, Объем, Масса и Угол сами по себе являются действительными (вещественными) числами, и отдельного интереса не представляют. Но есть один важный нюанс для этих типов:
помимо того, что все они могут иметь нулевое значение, т.е.
<0> (не путать с <null>), непосредственно значения Длины и Угла могут быть отрицательными (по значению Длины я сам удивлен). а вот значения Массы, Объема и Площади только положительными (Renga просто не даст ввести пользователю отрицательные значения, а если при расчете данных свойств с использованием формул будет получено отрицательное значение, то на выходе значение будет <null>).

Также нам надо запомнить некоторые моменты в части допустимости неинициализированных значений у типов, а также наличия у них значений по умолчанию.

Краткая таблица типов
Краткая таблица типов

Идем далее.....

2. Краткое описание принципа работы формул в Renga

Знатокам этот пункт будет не интересен. А вот для новичков, как дополнение к справке Renga по формулам, просто отмечу важный момент:
Формула для свойства срабатывает только на тех экземплярах объектов Renga, где значение данного свойства не было отдельно переопределено пользователем. Говоря простым языком: как только пользователь ввел свое значение в свойство, заданное изначально формулой, на каком-либо экземпляре объекта в модели – формула перестает работать для данного экземпляра (используется введенное пользователем значение), пользователь удалил свое значение – формула снова заработала (виден результат формулы).

При этом в формуле мы можем также явно указать какое-либо нужное нам значение (без необходимости его вычисления через формулу). Запомните данную информацию – она нам еще понадобиться.

Также для новичков, в дополнении к справке Renga по ссылкам в формулах, повторю некоторые моменты, о которых уже писал в группе:

1. Ссылки с использованием фигурных скобок { } применяются только в формулах у свойств строкового типа. В других типах свойств их ставить НЕ НАДО!
2. Все, что указанно в { } не обязательно должно быть только ссылкой на какое-то свойство (первоначальная ошибка новичков). В фигурных скобках также указываются любые (!!!) вычисляемые значения, т.е. результаты математических операций, функций, операндов и т.д. вместе с содержащимися в них значениями и именами свойств/параметров.
3. Все, что будет указано вне скобок { }, станет обычным текстом (символами) в строке.

Просто банальные примеры для новичков:
{Свойство1+Свойство2} - будет сложение значений свойств с преобразованием результата в строку.
{Свойство1}+{Свойство2} - будет строка вида Значение1 + Значение2, т.е. сложения не будет, так как здесь + трактуется уже как символ, а не как арифметический оператор.
{Свойство1 == 2 ? 6 : 25} - выражение просчитается корректно.
{Свойство1} == 2 ? 6 : 25 - часть "== 2 ? 6 : 25" так и запишется, как текст.

3. Неявное приведение (преобразование) типов в формулах Renga. Начинаем погружение

Итак. Те, кто знаком с программированием, знают, что такое явное и неявное приведение типов. Остальным для общего интереса (но не обязательно) можно просто погуглить на эту тему. А пока итог:

Renga при расчете формул использует неявное приведение типов значений между собой

Определимся сразу, что под числовыми типами далее я подразумеваю Целое, Действительное, Длина, Масса, Объем, Площадь, и Угол.

Под строковым типом - только Строка (результат Перечисления - как строковый тип, нам все-также не интересен). Ну а с Булевым и Логическим и так понятно.

Итак. Поехали....

  • <null> (неинициализированные значения свойств, а также результаты ошибочных операций, считаем его нетипизированным значением )
  1. Приведение к числовым типам: нет приведения, результат также будет <null>, все формулы и операции у данных типов в результате всегда дают <null>.
  2. Приведения к Булевому и Логическому типу: по сути приведения не будет, но так как данные типы не могут иметь неинициализированное значение, то наличие <null> будет вырождаться в значение <Нет>.
  3. Приведение к строковому типу: будет приведение к пустой строке (нулевой длины) именно в месте возникновения <null>, т.е. остальная часть значения строки, полученной из формулы, отобразиться корректно. Если же в результате всех операций в формуле итоговое значение ожидается <null>, то итоговое значение строки также будет пустой строкой нулевой длины, но уже не <null> (визуально пользователь это не отличит, но через метод HasValue() в API видно, что строковое значение теперь инициализировано).
  • Булевый (нам он очень важен)
  1. Приведение к числовым типам: <Нет> это <0>, <Да> это <1>.
  2. Приведение к строковому типу: Нет и Да (как написано значение, так и будет написано текстом).
  3. Приведение к Логическому типу: без изменений, т.е. <Да> это <Да>, <Нет> это <Нет>.
  • Логический (нам не особо полезен, просто указал его)
  1. Приведение к числовым типам: <Нет> это <0>, <Да> это <1>, <Неизвестно> это <2>.
  2. Приведение к строковому типу: Нет, Да и Неизвестно (как написано значение, так и будет написано текстом).
  3. Приведение к Булевому типу: без изменений <Да> и <Нет>, <Неизвестно> станет <Да>.
  • Числовые типы
  1. Приведение к Булеву типу: <0> это <Нет>, любые остальные значения, в т. ч. отрицательные это <Да>.
  2. Приведение к строковому типу – число, отформатированное в соответствии с региональными настройками системы (региональным форматом данных в окне Административные языковые параметров ). Но здесь есть один нюанс - в русских региональных настройках используется пробел (код символа 32), а Renga использует неразрывный пробел (код символа 160), чтобы не было переноса части числа на новою строку при заполнении данных в спецификации.
  • Строковые типы

1. Приведение к числовым типам: возможно приведение только значений, содержащие одни лишь цифры и пробелы, расположенные в строго определенных местах. Отсутствие значения в строковом типе (<null>) или наличие только пробелов в значении не преобразуются в числовой тип, а только в <null>. Прочее преобразование работает так:
- концевые пробелы (до и после числа, указанного цифрами), обрабатываются корректно, т.е. значения строки вида
< 156 > преобразуется в число <156>;
- пробелы, разделяющие количество тысяч, миллионов и т.д., обрабатываются корректно. Т.е. значения строки вида
<12 456> обработаются корректно в число <12456>;.
- пробелы в иных местах не дают преобразования, т.е. значение строки вида
<12 5> не обработается (будет <null>);
- наличие точки или запятой в разделителе разрядов целой и дробной части не влияет на корректность приведения к
Действительному (вещественному) типу, т.е. значения строк вида <156.56> (с точкой) и <156,56> (с запятой) преобразуются одинаково в число.
2. Приведение к
Булеву типу: используется вырождение <null> в <Нет>, любые иные значения строк, из которых можно получить числа - в полном соответствии с приведением числовых типов к Булеву (описано уже ранее).

Практика

Отмечу, что неявные преобразования туда/обратно <null> и Булевого типа позволяют реально творить некоторые "чудеса".

Вы точно все поняли из теории? Или все это уже знали? А применяли ли на практике? Сейчас проверим :)))

Для удобства чтения формул я буду использовать у свойств простые названия, содержащие в себе именно наименование/название типа. А теперь приступим.

Пример № 1 (числовые свойства)

Любите писать в формулах у числовых свойств что-то наподобие Булево ? 1 : 0 или Число > 10 ? 1 : 0 ? Напишите просто Булево или Число > 10.

Пример № 2 (числовые свойства)

Нужно получить сумму, например, трех чисел, каждое из которых должно учитываться только при определенных условия? Напишите Булево1*Число1 + Булево2*Число2 + Булево3*Число3.

Пример № 3 (делаем для свойств значения по умолчанию)

Часто пользователи используют для ручного задания каких-либо значений (без использования формул) свойств с типами, имеющими по умолчанию неинициализированное значение, т.е. <null>. При этом предполагается, что данные свойства должны быть обязательно заполнены. А еще бывает так, что потом значения этих свойства уже используются далее в формулах.

Хм... А что нам мешает для таких свойств тоже использовать формулу, но только прописать в ней стразу определенное значение, которое будет использоваться как значение по умолчанию? Пишите сразу в формулу что-то наподобие <число>, <какой-то текст> и т.д. Теперь там, где надо, пользователь введет свое значение, отличное от значения по умолчанию. Не надо? Оставит имеющееся. Надо быстро сменить значение по умолчанию: зашли в формулу и сменили значение. Также любые иные формулы, содержащие ссылки на такие свойства, перестанут давать по итогу ошибки (результат <null>) по причине отсутствия у данных свойств не инициализированных значений.

Пример № 4 (прячем/показываем значения у числовых типов)

Временами пользователю необходимо, чтобы только в определенных ячейках спецификации были расчетные числовые значения, а там где значение <0>, ничего бы не показывалось.

У вас еще не созрел план, как превратить значение <0> в <nulll>? Значит вам надо познакомиться с некоторыми "мега-формулами" в Excel. А пока просто пишем в формуле Число/Булево (число делим на булево значение), где Булево задает показ значения. При значении <Да> результат - Число. При значении <Нет> итоговый результат уйдет в <null> и не отобразиться как значение в ячейке. Под Числом я подразумеваю как ссылку на числовое свойство, так и операцию по расчету числового значения (например, (156*Число1+2,45)/Булево).

Пример № 5 (прячем/показываем числовые значения в строках)

По умолчанию любое числовое значение просто так нельзя спрятать в строке. Но мы то уже знаем, что <null> в строковом типе (в месте получения результата <null>) будет приведен к пустой строке (строке с нулевой длиной).

Допустим, мы хотим иметь возможность местами отображать значение строки (просто условный пример) в виде <Текст1> или <Текст25>, а местами просто <Текст>. Хорошо.
Пишем в формуле для строки
Текст{Число/Булево} (внимание, использованы фигурные скобки). При значении <Нет> у Булево получим только значение <Текст>.

Можно также комбинировать получение различных цифр/чисел в строке отдельными разрядами вида {Число1/Булево1}{Число2/Булево2} и т.д. и т.п..

Пример № 6 (создаем свойство, контролирующее корректность расчета всех вычисляемых значений у свойств с числовым типом)

Просто включаем фантазию. Имеем, например, три расчетных свойства числового типа Расчет_Число1, Расчет_Число2 и Расчет_Число3. А также имеем шанс, что при определенных условиях какие-то из этих значений могут переродиться в <null> (что-то где-то не так указали или не так рассчиталось... и понеслось по цепочке). Хорошо

Создаем Булево свойство с формулой и пишем туда:
Расчет_Число1 + Расчет_Число2 + Расчет_Число3 (сложение не принципиально, используем любые удобные нам арифметические операции).

Если у расчетных числовых свойств имеются конкретные значения, то значение у Булево свойства будет всегда <Да>. Если значение хотя бы одного из свойств вдруг станет неинициализированным из-за ошибки в вычислениях его формулы, то Булево станет <Нет>.
Выводим
Булево в спецификацию и отслеживаем экземпляры объектов со сбившимися расчетами.

Пример № 7 (ищем переопределенные пользователем значения результатов формул)

Можно придумывать внесение каких либо значений вместо формулы, но нам проще ввести в данную формулу значение или математическую операцию, вызывающую по итогу <null> (предварительно сохранив/скопировав исходную формулу куда-либо) и далее в спецификации по конкретному свойству среди пустых значений будут видны только значения, заданные пользователем. Примеры для понимания: у Массы, Объема и Площади в формуле записали, например, -1, для иных числовых значений задали формулу 1/0 (единица деленная на ноль), а в строковом типе просто указали пустую ссылку вида {} (фигурные скобки).

Видите? Все просто! Ну и напоследок для новичков:

Прекратите уже мучить выражение (составной оператор) A ? B : C в попытках заставить его работать со стоковыми значениями. Он не работает пока с ними (Ни операнд A, ни B, ни C не понимает строковые значения, введенные напрямую или с помощью имени свойства строкового типа... значение выражения сразу уходит в <null>.

Всем удачи в своих экспериментах.

Для обсуждения статьи: группа в Телеграмм "Эксперименты с Renga".