Управляющие конструкции языка и обработка аргументов
Мы кратко рассмотрели основные конструкции языка на первой лекции, а на этом занятии уделим время рассмотрению управляющих конструкций языка. Все конструкции языка расписаны в официальной документации и их можно посмотреть на данной странице.
Ввиду того, что официальная документация очень обширная, перевести её не представляется возможной задачей, поэтому в тексте данного документа рассмотрим только лишь основные моменты. Если что-то не понятно, то сразу обращаемся к официальной документации.
Условные операторы
Без условного оператора в программировании было бы нечего делать, поэтому начнём рассмотрение именно с его. В Ruby существует несколько вариантов условных операторов:
- Классический оператор
if
- Тернарный условный оператор
- Отрицающий оператор
unless
- Условные операторы в форме модификаторов
Однако перед переходом к рассмотрению конкретных операторов нам необходимо определиться с тем что является правдой, а что является ложью в Ruby. Ruby по своей природе не очень требователен к тому, что окажется в условии, и там действует достаточно простое правило:
- ложью является
false
(логическая константа, ложь) иnil
(константа отсутствия значения); - всё остальное является правдивым значением.
Условный оператор if
Рассмотрим полную форму условного оператора.
data = 1
if data == 0
puts 'В переменной data записано число 0'
elsif data == 1
puts 'В переменной data записано число 1'
elsif data > 1
puts 'В переменной data записано число больше 1'
else
puts 'В переменной data записано другое число'
end
- Условие пишется сразу после
if
до конца строки - Альтернативные условия пишутся на отдельных строках после
elsif
- Альтернативное безусловное действие пишется после
else
Тернарный оператор
Тернарный оператор создан, чтобы делать код ещё более сложным и нечитаемым. Его необходимо по возможности избегать.
input_type = gets =~ /hello/i ? "greeting" : "other"
Поэтому в Ruby условный оператор возвращает значения, то есть он является выражением с результатом. Результатом работы условного оператора является выражение, которое было успешно выполнено в рамках одного из блоков оператора. Поэтому вместо него удобнее и понятнее будет написать следующее:
input_type = if gets =~ /hello/i
"greeting"
else
"other"
end
В языке Ruby большинство операторов являются выражениями и возвращают результат своего выполнения.
Условный оператор unless
Если ваше условное выражение не должно выполняться, то есть условие неверно, тогда удобно использовать оператор unless
. У данного оператора также есть возможность описать альтернативный поток выполнения, но нет возможности описать альтернативные условия.
unless false
puts "Этот блок БУДЕТ выполнен"
else
puts "Этот блок НЕ будет выполнен"
end
Русскоязычным читателям зачастую сложно воспринимать код с оператором unless
, поэтому его рекомендуется использовать, если нет альтернативной ветви исполнения. О ментальной сложности использования данного оператора также сообщают и носители языка.
Операторы в форме модификаторов
Операторы if
и unless
могут быть написаны после любого выражения. Таким образом это выражение будет выполняться только лишь в том случае, если условное выражение верно.
В результате данного кода в переменной data будет записана 1
data = 0
data += 1 if data.zero?
p data
А в результате этого кода в переменной data будет записан 0
data = 0
data += 1 unless data.zero?
p data
Не следует их очень часто применять, особенно в сложных ситуациях. Но если при их применении код остаётся понятным, то следует их использовать.
Оператор ветвления case
С помощью case
-выражения вы можете сравнить значение с набором шаблонов. И выполнить в зависимости от этого определённые задачи.
Рассмотрим пример оператора ветвления:
data = '2'
case data
when /^1/, "2"
puts 'строка начинается с числа 1 или является строкой \'2\''
when /^3/
puts 'строка начинается с числа 3'
else
puts 'неизвестная строка'
end
После ключевого слова case
пишется выражение. Значение этого выражения затем проверяется относительно условий, которые написаны после ключевого слова when
. Сравнение происходит с помощью оператора ===
. Литерал /^1/
описывает регулярное выражение, строку, которая начинается с символа единицы.
Для большинства типов сравнение ===
идентично сравнению с помощью ==
, однако для ряда классов реализовано дополнительные варианты сравнения. Например для классов, реализующих регулярные выражения или промежутки. Ниже представлен пример работы с промежутками чисел. Пожалуйста обратите внимание на количество точек между границами промежутков - это важно.
num = 150
case num
when 1...50
puts 'Число от 1 до 49'
when 50..99
puts 'Число от 50 до 99'
else
puts 'Другое число'
end
Обработка аргументов командной строки
На прошлом занятии мы создавали с вами интерактивные приложения для консольного интерфейса. В этот раз будем создавать приложения, которые получают информацию из аргументов командной строки.
С точки зрения приложения все переданные ему аргументы представляют собой просто массив из строк. Как дальше будут обрабатываться данные строки и что они значат будет решать ваше приложение.
С пользовательской точки зрения аргументы приложения могут быть двух типов: позиционные и именованные.
К позиционным аргументам относятся те, значение которых определяется их порядковым номером. Рассмотрим пример - приложение-калькулятор. С точки зрения разработчика его приложение ожидает 3 аргумента: операцию, первое число и второе число.
> ruby calc.rb sum 10 15
Сумма элементов: 25
Если мы поставим сумму на 3 позицию, то приложение не сможет выполнить свою операцию, т.к. не найдёт операцию 10
среди доступных.
Именованные аргументы помимо своего значения имеют также и название. Рассмотрим как может выглядеть интерфейс приложения-калькулятора в этом случае. Для каждого аргумента мы введём свои имена: operation
для операции, first
- для первого аргумента, second
для второго аргумента.
> ruby calc.rb --first=267 --operation=div --second=17
Целочисленное деление: 15
Очевидно, что размер данных, передаваемых приложению, вырос. Однако пользователи теперь имеют возможность указать аргументы в произвольном порядке и теперь всегда понятно к чему относится то или иное число.
На практике всегда используется некоторая смесь из данных подходов. Обычно чрезвычайно важные параметры задаются как позиционные, а все остальные через аргументы. В сложных системах количество различных аргументов может достигать несколько десятков.
Для того, чтобы не запутаться в таком разнообразии приложения зачастую обрабатывают аргумент --help
. При его указании выводится краткая справка о том какие аргументы есть и как ими пользоваться:
> ruby calc.rb --help
Приложение для выполнения арифметических операций над целыми числами.
--operation=OPERATION Операция, которую надо выполнить: sum, sub, mul, div
--first=NUM Значение первого операнда
--second=NUM Значение второго операнда
В стандартной поставке языка Ruby есть несколько библиотек, которые облегчают задачу по обработке аргументов. В рамках данной практической работы используйте переменную-массив ARGV
для получения списка аргументов.
Практические задачи
При реализации приложений пожалуйста разбивайте вашу программу на методы. Не рекомендуется в дальнейшем писать код для решения практических задач сплошным потоком кода. Начинать решение задачи рекомендуется со следующего минимального кода:
def main
puts 'I am working!'
puts "My arguments are: #{ARGV}"
p ARGV # See them like Ruby sees them.
end
# Keep it in the bottom of the file
if __FILE__ == $0
main
end
Исследуем условный оператор if
Напишите приложение, которое будет просить пользователя ввести вещественное число.
- Если число больше нуля, тогда вывести “положительное число”.
- Если число меньше нуля, тогда вывести “не положительное, а отрицательное число”.
- Если число равно нулю, тогда вывести “непонятное число”.
Приложение должно выводить информацию о работе, указание для ввода данных. Реализуйте приложение с помощью условного оператора if
.
> ruby check_number.rb
Данное приложение производит проверку числа. Передайте число в качестве первого аргумента приложения.
check_number.rb NUMBER
> ruby check_number.rb 15
Число «15» положительное.
При реализации приложения выделите код для преобразования строки в число в отдельный метод, чтобы можно было его заново использовать в других задачах.
Данный метод должен проверять введённые пользователем данные на корректность. Т.е. если пользователь ввёл пустую строку или ввёл не вещественное число, тогда метод должен сообщить пользователю о неправильном вводе данных.
Игра на рынке
Напишите приложение, которое будет принимать следующие аргументы:
- Объём изначальных инвестиций.
- Сколько дней ждать до вывода остатка денежных средств.
Каждый день на рынке происходит “игра”. В зависимости от случайного значения, которое вернёт метод rand(15)
выполните:
- Больше 14 - повысьте счёт на 10%
- Больше 12 - повысьте счёт на 2%
- Больше 9 - оставьте счёт неизменным
- Больше 7 - отнимите со счёта 2%
- Больше 5 - отнимите со счёта 10%
- Остальное - отнимите со счёта 50%
По окончании каждой игры приложение должно показать пользователю текущее состояние счёта.
Приложение должно выводить информацию о своей работе, если пользователь не указал никаких аргументов. Приложение также должно выполнять проверку на правильность ввода числа.
> ruby market_game.rb
Приложение эмитирует игру на рынке. Передайте стартовый капитал и количество дней в качестве аргументов приложения.
market_game.rb CAPITAL DAYS
> ruby market_game.rb 100 10
...
Реализуйте приложение с помощью оператора ветвления case
.
Заполнение формы
Реализуйте приложение, которое позволит пользователю указать информацию о себе для приёма на работу. Приложение должно анализировать данные, переданные пользователю и предлагать на их основании предлагать различные должности, которые может занять кандидат.
Пользователь вводит следующие данные:
- Имя и фамилию, непустая строка.
- Адрес электронной почты, непустая строка.
- Возраст, положительное число от 15 до 100.
- Стаж работы в профессии, положительное число.
Приложение должно показать справку об использовании при указании аргумента --help
и проверять их корректность. Для реализации данной задачи используйте именованные аргументы.
После ввода данных приложение должно проверять данные и показывать список должностей, на которые может устроиться кандидат. Для проверки и вывода свойств используйте модификаторы if
и unless
.
- Профессия «Руководитель», если имя и фамилия совпадает с «Пётр Петрович».
- Профессия «Инженер», если адрес электронной почты включает в себя строку “code”. Проверяйте с помощью метода String#include?.
- Профессия «Стажёр», если стаж работы в профессии меньше двух лет.
- Профессия «Бывалый», если возраст от 45 до 60.
- Добавьте к профессии слово “Заслуженный”, если стаж работы в профессии больше 15 лет.
- Добавьте к профессии слово “Известный”, если стаж работы в профессии больше 5 лет.
> ruby find_job.rb
Приложение подбирает работу для вас на основании введённых данных
find_job.rb --name=NAME --surname=SURNAME --mail=MAIL --age=AGE --experience=EXPERIENCE
> ruby find_job.rb --age=45 --name=Bob --surname=Martin --experience=30 --mail=bob@example.com
...
Решение задачи №12 из пункта 1.2 задачника
Реализуйте приложение, решающее задачу №12 из пункта 1.2 задачника. Приложение должно выводить справку об использовании, проверять правильность ввода. Желательно использовать различные варианты логических операторов при выполнении сравнений.