TON Telegram Open Network - Fift - часть 2 - передача аргументов, условный оператор

avatar cromlehg 1 month ago

Оглавление
Предыдущая статья
Следующая статья

Введение

В этой статье мы научим наш скрипт приветствовать по имени, которое будем передавать в аргументах. Для этого мы познакомимся с несколькими новыми операторами, узнаем как передавать и обрабатывать аргументы. И сделаем наш скрипт устойчивым к ошибкам.

Передача аргументов

Давайте научим наш скрипт приветствовать пользователя по имени. Имя будем передавать в аргументах при заупске скрипта.

Мы уже сказали в предыдущей статье что fift запускаем в интреактивном режиме (параметр -s), а значит можем передавать аргументы скрипту. Аргументы указываются сразу после указания имени скрипта. 

fift -I <путь_к_библиотекам> -s hw.fif тут пишем аргументы нашему скрипту

Передавать как оказалось просто. А как получать аргументы внутри скрипта? Для этого есть три оператора. Все они помещают результат работы на стэк:

  • $# - количество аргументов указанных в командной строке
  • $0 - название запускаемого скрипта
  • $1, $2, $3 ... - аргументы, которые были переданы в командной строке скрипту, номер соответствует номеру аргумента при передачи и отсчитывается от единицы

Теперь мы знаем как поместить в стэк аргументы и и их кол-во. Но в конечном итоге нам нужно уметь выводить их на экран чтобы отобразить имя. Как их распечатать из стэка?
Для распечатки значений из стэка мы воспользуемся оператором type - он извлекает из стэка последнее значение и распечатывает его в виде строки.

Теперь у нас есть все необходимое чтобы попроавить наш скрипт, чтобы он распечатывал приветствие с переданным именем. Давайте посмотрим, ч у нас получилось:

."Hello, " $1 type ."!" cr

Разберем:

  1. ."Hello, " - печатает строчку: Hello, 
  2. $1 - помещает в стэк первый аргумент переданный в наш скрипт
  3. type - забирает последнее значение со стэка и распечатывает его
  4. ."!" - печататет: !
  5. cr - перемещает курсор на новую строчку

Попробуем запустить наш скрипт передав ему имя Vasia: 

<папка_с_собраным_клиентом>/crypto/fift -I <папка_с_исходниками>/crypto/fift/lib/ -s hw.fif Vasia

В последствие для краткости мы будем опускать параметры для запуска интерпретатора. Будем указывать только имя нашего скрипта и аргументы. А читатель всегда может вернуться к этой или первой статье и посмотреть как запускать интерпретатор. Т.е. в следующие разы мы будем показывать примеры запуска примерно так:

hw.fif Vasia

В результате работы скрипта получим:

Hello, Vasia!

Отлично, это то что надо!

Проверки правильности указания аргументов

Что если указать более одного аргумента? Программа отработает также. А если не указать ни одного аргумента?

hw.fif

Мы получим ошибку, похожую на эту:

Дело в том что пользователь не знает заранее как пользоваться скриптом и может забыть указать аргументы или указать больше. Хорошим тонов таких случаях считается выводить подсказку пользователю при неверном использовании скрипта. Поэтому нам нужно сделать чтобы скрипт успешно работал только с одним аргументом. А в остальных случаях пусть скрипт выводит подсказку и выходит.

Как поместить в стэк кол-во аргументов мы знаем. Мы не знаем как проверить что кол-во аргументов равно единице. Давайте познакомимся с тремя операторами, которые помогут решить нашу задачу:

  1. число - помещает на вершину стэка число
  2. = - извлекает из стэка последние два значения и сравнивает. Если числа равны, то помещает в стэк -1, если не равны то помещает 0.
  3. { выражение } - помещает на стэк выражение состоящее из операторов fift, но не выполняет его
  4. cond - условный оператор. Перед его вызовом в стэк нужно поместить в указанном порядке: любое число или 0, какое-то выражение 1, какое-то выражение 2.  Оператор cond достанет три последних значения из стэка. Если самое первое значение которое мы поместили не равно 0, то выполнится выражение 1, иначе выражение 2. Давайте проиллюстрируем работу оператора на примере. Слева-напрвао показаны изменения стэка и экрана после пооператорного выполнения:

    Мы поместили 1 на стэк а затем два выражения. Оператор cond все достал, увидел что мы поместили не ноль и выполнил выражение { ."true" cr }. B результате на экране вывелось: true.

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

$# 1 = { ."Hello, " $1 type ."!" cr } { ."Please, specify only your name!" cr } cond

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

  1. $# - помещает в стэк кол-во переданных скрипту аргументов
  2. 1 - помещает в стэк еиницу
  3. = - достает последние два значения из стэка. Проверяет что предыдущее значение на стэке равно последнему. Т.е. кол-во переданных скрипту аргументов равно единице. Если это так то помещает на стэк 1 иначе 0.
  4. { ."Hello, " $1 type ."!" cr } - записывает в стэк выражение, не выполняя его. Распишем что оно будет делать, если выпоонится:
    1. ."Hello, " - печатает: Hello
    2. $1 - помещает в стэк первый аргумент переданный скрипту
    3. type - печатает последнее значение из стэка в виде строки 
    4. ."!" - печатает: !
    5. cr - перемещает курсор на новую строку
  5. { ."Please, specify only your name!" cr } - Помещает на стэк выражение, не выпонляя его. Если выполнится потом, то выведет: Please, specify only your name!
  6. cond - извлекает из стэка последние три значения. Если самое нижнее на стэке больше нуля, то предпоследнее выражение в стэке, т.е. приветсвие. Иначе выполняет послденее выражение на стэке, т.е. подсказку.

Теперь попробуем протестировать наш скрипт при разном кол-ве аршументов:

  1. Один раргумент: 
    nw.fif Vasya

    Успешно отработает и выведет приветсвие
    Hello, Vasya!
  2. Два аргумента:
    nw.fif Vasya extendarg
    Успешно отработает и выведет:
    Please, specify only your name!
  3. Без аргументов:
    nw.fif
    Скрипт упал с ошибкой:

В чем же дело? Мы, казалось, правильно использовали операторы и ошибки в логике нету.
А дело в том, что выржения в скбоках { } выполняются не сразу. А к тому времени, когда начнет выполнятся код внутри скобок, значение $1 может быть нам уже недоступно. Пока не будем вдаваться в подробности причин такого поведения. $1 - это для выражения в скобках называется значением времени исполнения. И для его восстановления внтури скобок есть специальный оператор @' - он указывается перед именем восстанавливаемого значения. Давайте поправим наш скрипт:

$# 1 = { ."Hello, " @' $1 type ."!" cr } { ."Please, specify only your name!" cr } cond

Как видите, мы добавили @' непосредственно перед $1. Теперь скрипт успешно будет работать!

Резюме

В этой статье мы научились передавать нашему скрипту аргументы. Узнали как распечатывать занчения со стэка и как пользоваться одним из условных операторов. 

Обсудить, задать вопросы или сообщить о неточностях можно в нашей официальной группе - Blockchain's Witnesses

Оглавление
Предыдущая статья
Следующая статья