1.2.4. Операторы и приоритеты
Познакомившись с основными типами данных, перейдем к операторам в языке Ruby. В приведенном ниже списке они представлены в порядке убывания приоритета:
:: Разрешение области видимости
[] Взятие индекса
** Возведение в степень
+ - ! ~ Унарный плюс/минус, НЕ…
* / % Умножение, деление…
+ - Сложение/вычитание
<< >> Логические сдвиги…
& Поразрядное И
|| ^ Поразрядное ИЛИ, исключающее ИЛИ
> >= < <= Сравнение
== === <=> != =~ !~ Равенство, неравенство…
&& Логическое И
|| Логическое ИЛИ
.. ... Операторы диапазона
= (also +=, -=, …) Присваивание
?: Тернарный выбор
not Логическое отрицание
and or Логическое И, ИЛИ
Некоторые из перечисленных символов служат сразу нескольким целям. Например, оператор << обозначает поразрядный сдвиг влево, но также применяется для добавления в конец (массива, строки и т.д.) и как маркер встроенного документа. Аналогично знак + означает сложение чисел и конкатенацию строк. Ниже мы увидим, что многие операторы — это просто сокращенная запись вызова методов.
Итак, мы определили большую часть типов данных и многие из возможных над ними операций. Прежде чем двигаться дальше, приведем пример программы.
1.2.5. Пример программы
В любом руководстве первой всегда приводят программу, печатающую строку Hello, world!, но мы рассмотрим что-нибудь более содержательное. Вот небольшая интерактивная консольная программа, позволяющая переводить температуру из шкалы Фаренгейта в шкалу Цельсия и наоборот.
print "Введите температуру и шкалу (С or F): "
str = gets
exit if str.nil? or str.empty?
str.chomp!
temp, scale = str.split(" ")
abort "#{temp} недопустимое число." if temp !~ /-?\d+/
temp = temp.to_f case scale
when "С", "с"
f = 1.8*temp + 32
when "F", "f"
с = (5.0/9.0)*(temp-32)
else
abort "Необходимо задать С или F."
end
if f.nil?
print "#{c} градусов C\n"
else
print "#{f} градусов F\n"
end
Ниже приведены примеры прогона этой программы. Показано, как она переводит градусы Фаренгейта в градусы Цельсия и наоборот, а также как обрабатывает неправильно заданную шкалу или число:
Введите температуру и шкалу (С or F): 98.6 F
37.0 градусов С
Введите температуру и шкалу (С or F): 100 С
212.0 градусов F
Введите температуру и шкалу (С or F):
92 G Необходимо задать С или F.
Введите температуру и шкалу (С or F): junk F
junk недопустимое число.
Теперь рассмотрим, как эта программа работает. Все начинается с предложения print, которое есть не что иное, как вызов метода print из модуля Kernel. Данный метод выполняет печать на стандартный вывод. Это самый простой способ оставить курсор в конце строки.
Далее мы вызываем метод gets (прочитать строку из стандартного ввода) и присваиваем полученное значение переменной str. Для удаления хвостового символа новой строки вызывается метод chomp!.
Обратите внимание, что print и gets, которые выглядят как «свободные» функции, на самом деле являются методами класса Object (который, вероятно, наследует Kernel). Точно так же chomp! — метод, вызываемый от имени объекта str. При вызовах методов в Ruby обычно можно опускать скобки: print "foo" и print("foo") — одно и то же.
В переменной str хранится символьная строка, но могли бы храниться данные любого другого типа. В Ruby данные имеют тип, а переменные - нет. Переменная начинает существовать, как только интерпретатор распознает присваивание ей; никаких предварительных объявлений не существует.
Метод exit завершает программу. В той же строке мы видим управляющую конструкцию, которая называется «модификатор if». Он аналогичен предложению if, существующему в большинстве языков, только располагается после действия. Для модификатора if нельзя задать ветвь else, и он не требует закрытия. Что касается условия, мы проверяем две вещи: имеет ли переменная str значение (то есть не равна nil) и не является ли она пустой строкой. Если встретится конец файла, то будет истинно первое условие; если же пользователь нажмет клавишу Enter, не введя никаких данных, — второе.
Это предложение можно было бы записать и по-другому:
exit if not str or not str[0]
Эти проверки работают потому, что переменная может иметь значение nil, а nil в Ruby в логическом контексте вычисляется как «ложно». На самом деле как «ложно» вычисляются nil и false, а все остальное — как «истинно». Это означает, кстати, что пустая строка "" и число 0 — не «ложно».