- 1. Факториалы
- 2. Строки
- 3. Регулярные выражения
А теперь давайте разберём код из некоторых наших предыдущих примеров программ.
Следующий пример появился впервые в этой главе .
def fact(n) if n == 0 1 else n * fact(n-1) end end print fact(ARGV[0].to_i), "\n"
Поскольку это первое пояснение, то рассмотрим каждую строку отдельно.
Факториалы
def fact(n)
В первой строке оператор def объявляет функцию (или, точнее, метод , мы поговорим о методах в другой главе). Здесь это указывает функцию fact, принимающую один аргумент, описанный как n .
if n == 0
Далее проверка условия. Когда условие выполняется, тогда выполняется код, следующий за условием, в противном случае выполняется код, следующий за else .
1
Возвращаемое значение, если условие выполнилось.
else
Если условие не выполнилось, то выполняется данный кусок кода до оператора end.
n * fact(n-1)
Если условие не выполнилось, то результатом является n раз выполнение функции факториала fact(n-1).
end
Первый оператор end, который закрывает оператор if.
end
Второй оператор end, закрывающий тело функции, то есть оператор def .
print fact(ARGV[0].to_i), "\n"
Вызываем функцию факториала fact() , используя значение переданное в командную строку и выводим результат.
ARGV является массивом, который содержит аргументы командной строки. Элементы ARGV являются строками, поэтому мы должны конвертировать их в целочисленный тип с помощью метода to_i. Ruby не преобразует строки в целочисленные типы автоматически, как это делает Perl.
Строки
Следующий пример был показан в главе о строках .
words = ['foobar', 'baz', 'quux'] secret = words[rand(3)] print "guess? " while guess = STDIN.gets guess.chop! if guess == secret print "you win\n" break else print "you lose.\n" end print "guess? " end print "the word is ", secret, ".\n"
В этой программе присутствует новая структура с условием, это цикл while. Код между while и его соответствующим оператором end будет выполняться до тех пор пока выполняется условие цикла.
rand(3) в строке 2 возвращает случайное число в диапазоне о 0 до 2. Это случайное число используется для извлечения одного из трёх слов в массиве words .
В строке 5 считывается строка из стандартного ввода STDIN.gets. Если получен EOF (конец файла), то gets возвращает nil . Таким образом код будет повторяться до тех пор, пока не получит комбинацию завершения D* (или * Z подDOS).
guess.chop! в строке 6 удаляется последние символы из переменной guess . В этом случае это всегда означает новую строку.
В строке 15 выводится секретное слово. Мы имеем оператор print с тремя аргументами (которые выводятся один за другим), но также эффективно, как если бы работали с одним аргументом, записывая secret как #{secret}, чтобы было ясно, что это переменная, а не строка для вывода:
print "the word is #{secret}.\n"
Регулярные выражения
И в конце рассмотрим программу из главы по регулярным выражениям .
st = "\033[7m" en = "\033[m" while TRUE print "str> " STDOUT.flush str = gets break if not str str.chop! print "pat> " STDOUT.flush re = gets break if not re re.chop! str.gsub! re, "#{st}\\&#{en}" print str, "\n" end print "\n"
В строке 4, условие цикла while установлено в true. Таким образом сделан бесконечный цикл. Однако в строках 8 и 13 добавлен оператор break для выхода из цикла. Эти два оператора break также являются примером модификация if . Модификация if выполняет оператор с левой стороны только если условие выполняется.
Имеется несколько слов о методе chop! (смотрите строки 9 и 14). В Ruby мы добавляем символы '!' или '?' в конец имён методов. Восклицательный знак (!, иногда произносится как "бах!") указывает на то, что метод является потенциально разрушительным и может изменить значение, которого касается. chop! непосредственно влияет на строку, но просто chop без восклицательного знака работает как копирование. В этом заключается различие.
ruby> s1 = "forth" "forth" ruby> s1.chop! # This changes s1. "fort" ruby> s2 = s1.chop # This puts a changed copy in s2, "for" ruby> s1 # ... without disturbing s1. "fort"
Вы позже столкнётесь с методом на конце которого будет применяться вопросительный знак (?, иногда произносится как "huh?"); который указывает что метод является предикатом, то есть возвращает значения между true и false.
Строка 15 заслуживает пристального внимания. Во-первых это метод gsub!, который является деструктивным методом. Он изменяет переменную str, заменяя все символы, которые совпадают с шаблоном re ( sub означает замену, а символ g впереди означает глобальное влияние, то есть замена все совпавших частей в строке, а не только первый найденный кусок). Итак, всё идёт нормально, но что мы заменяем в данном тексте? st и en определены в 1 и 2 строках, как ANSI последовательности, которые делают текст нормальный и инвертированный. В строке 15 они заключены в #{} , чтобы убедиться, что они действительно интерпретируются так как надо, а не как строки для вывода. Между ними мы видим последовательность "\&" . Это небольшой трюк. Так как замена осуществляется в двойных кавычках, то пара обратных слэшей будет интерпретироваться как "\&". В результате будет напечатана новая строка, похожая на старую, за исключением того, что будут подсвечены те части, которые совпали с шаблоном.