- •Введение
- •Немного о cgi
- •Как работает Perl
- •Первая программа на Perl
- •Переменные и типы данных в Perl
- •Строковые данные
- •От простого к сложному
- •Запуск интерпретатора Перл
- •Синтаксис
- •Переменные
- •Встроенные переменные Перл
- •Регулярные выражения (шаблоны)
- •Операторы и приоритеты
- •Встроенные функции
- •Группа системных вызовов
- •Подпрограммы
- •Модули (packages)
- •Форматы
- •Отладка Перл программ
- •Запуск интерпретатора Перл.
- •Ассоциативные массивы в Perl.
- •Что такое Perl?
- •Как Perl обрабатывает данные из форм
- •Как генерируются web-страницы "на лету"
- •В чем различие между программой и скриптом?
- •Альтернативы Perl
- •Что вам требуется, чтобы запустить Perl
- •Где взять Perl
- •Этапы создания скрипта
- •Основные части Perl скрипта
- •Пример скрипта с формой
- •Обсуждение: Настройка скрипта
- •Обсуждение: Чтение данных из формы
- •Обсуждение: Что делать с данными?
- •Обсуждение: Запись в файлы
- •Пример: Создание новой html страницы
- •Пример: Добавление в конец файла
- •Пример: Добавление в середину существующего файла
- •Пример: Отправка данных по e-mail
- •Обсуждение: Создание web-страниц "на лету"
- •Встроенные переменные Перл.
- •Модули (packages)
- •Конструкторы и деструкторы
- •Создание библиотеки
- •Стандартные Перл библиотеки
- •Pragma библиототеки
- •Операторы и приоритеты.
- •Tr/таблица1/таблица2/cds y/таблица1/таблица2/cds
- •От простого к сложному.
- •Переменные
- •Скалярные значения
- •Конструкторы скаляров
- •Конструкторы списков
- •Практический Перл для начинающего.
- •Add_guestbook.Pl - запись в книгу
- •Read_guestbook.Pl - чтение книги
- •Подпрограммы
- •Private переменные
- •Переменные типа local
- •Прототипы (prototypes)
- •Ссылка как параметр
- •Переопределение встроенных функций
- •Автозагрузка
- •Регулярные выражения (шаблоны) Perl.
- •Синтаксис
- •Декларации (объявления)
- •Простое предложение
- •Сложные предложения
- •Операторы управления циклом
- •Цикл for
- •Цикл foreach
- •Оператор goto
- •Pod операторы. Документирование программ
- •4.Языковые конструкции Perl 4.1.Ссылки
- •4.5.Подпрограммы и модули
- •Введение
- •Cтруктуры данных
- •Скалярные величины
- •Простые массивы
- •Ассоциативные массивы
- •Основные понятия
- •Простые операторы
- •Составные операторы
- •Термы и операторы списка
- •Оператор ``стрелка''
- •Экспоненциальный оператор
- •Символьные унарные операторы
- •Операторы связки
- •Бинарные операторы
- •Операторы сдвига
- •Операторы сравнения
- •Операторы эквивалентности
- •Побитовое и, побитовое или и Исключающее или
- •Логическое и и логическое или
- •Логическое и, или и Исключающее или
- •Оператор чтения из файла
- •Оператор замены строки
- •Оператор диапазона
- •Условный оператор
- •Операторы присваивания
- •Оператор ``запятая''
- •Логическое не
- •Оператор замены множества символов
- •Основные понятия
- •Символьные ссылки
- •Регулярные выражения
- •Зарезервированные переменные
- •Встроенные функции
- •Подпрограммы
- •Конструкторы и деструкторы пакетов
- •Объектная ориентация
- •Объекты
- •Вызов метода
- •Деструкторы
- •Установка поддержки perl для iis3 под Windows nt Почему была написана эта заметка
- •Кратко о perl-модулях от Active State
- •Что скачивать
- •Как устанавливать
- •Как проверить
- •Что дальше
- •Введение в Perl Пару слов от автора
- •Краткое лирическое отступление насчет cgi
- •Итак ...Приступим...
- •Переменные среды cgi
- •Прекрасный язык Perl
- •If(условие)оператор;
- •Заголовки запросов и ответов
- •Права Доступа
- •Генерация ответа
- •Обработка Форм
- •Изображения ismap
- •Анимация
- •Несколько советов по отладке
- •Кто посещает мою страничку?
- •Гостевая книга
- •Счетчик посещений
- •Введение
- •Взаимодействие с субд
- •Основные функции доступа
- •Дополнительные функции
- •Переменные
- •Переменные для подстановки
- •Написание модулей cgi
- •Обработка файлов формата dbf
- •Изучаем Perl. Глава 1
- •Происхождение
- •Похож на Си?
- •Стоимость и лицензия
- •Проинсталлирован ли у вас Perl?
- •Ваша первая программа на Perl
- •Создание программы
- •Глава 2
- •Числовые литералы
- •Стринговые литералы
- •Строки с одинарными кавычками
- •Строки с двойными кавычками
- •Строки с обратными одинарными кавычками
- •Массивы
- •Вложенные массивы
- •Использование диапазона значений
- •Глава 3
- •Типы операторов
- •Бинарные арифметические операторы
- •Унарные арифметические операторы.
- •Логические операторы
- •Пример оператора логического "и" - (&&)
- •Пример оператора логического "или" - (||)
- •Пример оператора логического "не" - (!)
- •Битовые операторы
- •Операторы числовых отношений
- •Операторы отношений строк
- •Использование ternary-оператора
- •Оператор интервала ".."
- •Использование оператора интервала
- •Строковые операторы "." и "X"
- •Использование оператора конкатенации
- •Использование оператора репликации (повтора)
- •Операторы присваивания
- •Глава 4
- •Строковые функции
- •Функции для работы с массивами.
- •Немножко о модуле cgi.Pm в Perl.
- •Жемчужные формы
- •Как "оживить" Perl/cgi скрипт Введение
- •Метод 1
- •Метод 2
- •Метод 3
- •Введение
- •Для чего нужен Perl?
- •Структура Perl-программ
Глава 4
Продолжаем изучать Perl. В этой главе мы обратим свой взор на функции. Функции - это блоки кодов, которым даются названия, чтобы мы могли использовать их при необходимости. Функции помогают организовывать код в простые для понимания фрагменты. Они позволяют создавать программу шаг за шагом, тестируя ее по ходу.
После того, как у Вас появится идея программы, Вы должны разработать схему ее построения - в вашей голове или на бумаге. Каждый шаг в схеме мог бы являть собой одну функцию в вашей программе. Это называется модульным программированием. Модульное программирование очень хорошо позволяет Вам скрывать детали программы, благодаря чему улучшается читабельность исходного текста вашей программы.
Например, если ваша программа содержит функцию, которая вычисляет площадь круга, следующей строкой Вы можете обратиться к ней: $areaOfFirstCircle = areaOfCircle($firstRadius);
Глядя на подобные вызовы функций, человек, читающий исходный код вашей программы, понимает, что ваша программа делает. В то же время, ему не нужно знать, как конкретно реализована та или иная функция. Поэтому важно давать функциям "говорящие" имена - чтобы по имени можно было понять, что именно функция делает.
Вызов функции означает, что интерпретатор Perl в месте вызова функции прекращает выполнение текущей серии строк кода и переходит к выполнению кода функции. При завершении кода функции интерпретатор возвращается в точку вызова и продолжает выполнение программы со следующей строки.
Давайте присмотримся к вызову функции - сначала мы видим скалярную переменную, затем - оператор присвоения. Вы уже знаете, что это означает - Perl присвоит переменной $areaOfFirstCircle значение, стоящее справа от знака присваивания. Но что в действительности стоит справа?
Первое, что вы видите - это имя функции areaOfCircle(). Круглые скобки справа и отсутствие перед именем символов $, @ и % говорит о том, что это - вызов функции. Внутри круглых скобок содержится список параметров или значений, передающихся функции.
Вычисление площади круга: $areaOfFirstCircle = areaOfCircle(5); print("$areaOfFirstCircle\n"); sub areaOfCircle { $radius = $_[0]; return(3.1415 * ($radius ** 2)); }
Программа напечатает: 78.7375
Объявление функции: sub имяФункции { тело функции }
И все. Ваша функция готова.
Сложнее дело обстоит с параметрами. Параметры - это значения, которые мы передаем в функцию. Параметры содержатся внутри круглых скобок, следующих сразу за именем функции. В примере выше вызов функции - это areaOfCircle(5). Здесь мы использовали только один параметр. Но даже в том случае, если функция имеет только один параметр, Perl при вызове функции создает массив параметров для использования их функцией.
Внутри функции массив параметров имеет имя @_. Все параметры, передаваемые функции, содержатся в массиве @_, откуда их можно извлечь при необходимости.
Наша маленькая функция из примера выше могла бы сделать это следующей строкой: $radius = $_[0];
Эта строка присваивает первый элемент массива @_ скалярной переменной $radius.
Если вы хотите, вы можете не использовать в функции оператор return для возврата значения, - Perl автоматически возвратит значение последнего вычисленного выражения. Но будет лучше, если вы все же будете использовать оператор return - так вы избежите многих случайных ошибок.
Возможно вы встречали в некоторых языках программирования различия между подпрограммами и функциями. В таких языках функция обязательно возвращает значение, в то же время, подпрограмма значение не возвращает. В Perl же такого нет - у вас есть только функция - независимо от того, возвращает она какое-либо значение или нет.
Использование массива параметров (@_)
Как уже говорилось ранее - все параметры функция может найти в массиве параметров @_. Это очень удобно - чтобы узнать, сколько параметров было передано функции, нужно всего лишь обратиться к массиву параметров @_ в скалярном контексте. firstSub(1, 2, 3, 4, 5, 6); firstSub(1..3); firstSub("A".."Z"); sub firstSub { $numParameters = @_ ; print("The number of parameters is $numParameters\n"); } Программа напечатает: The number of parameters is 6 The number of parameters is 3 The number of parameters is 26
Perl позволяет вам передавать в функцию любое число параметров. Функция сама может определить, какие параметры ей использовать, и в какой последовательности. Массив параметров @_ может использоваться так же, как и любой другой массив.
Конечно, это не очень удобно - обращаться к переданным функции параметрам по их номерам - @_[0] или @_[1]. Вы можете воспользоваться более удобной технологией: areaOfRectangle(2, 3); areaOfRectangle(5, 6); sub areaOfRectangle { ($height, $width) = @_ ; $area = $height * $width; print("The height is $height. The width is $width. The area is $area.\n\n"); } Программа напечатает: The height is 2. The width is 3. The area is 6. The height is 5. The width is 6. The area is 30.
Передача параметров функции по ссылке.
Если вы передаете в функцию не какое-либо число, а переменную, то в случае изменения ее значение внутри функции, она также изменяется и для всей остальной программы. Это называется передача параметров по ссылке. @array = (0..5); print("Before fuNCtion call, array = @array\n"); firstSub(@array); print("After fuNCtion call, array = @array\n"); sub firstSub{ $_[0] = "A"; $_[1] = "B"; } Программа напечатает: Before fuNCtion call, array = 0 1 2 3 4 5 After fuNCtion call, array = A B 2 3 4 5
Как вы видите, функция изменила значение переданных ей параметров, и это повлияло также на работу остальной программы - значения массива @array изменились не только для функции, но и для всей остальной программы. Это плохая практика программирования - если у вас нет именно такой конкретной цели, то никогда не пользуйтесь подобными премами - они чреваты неочевидными ошибками. С другой стороны, если вы в начале функции присваиваете значения переданных параметров новым переменным (как было показано ранее), и работаете в дальнейшем только с ними - такой проблемы у вас не возникнет - ведь вы в данном случае на самом деле не изменяете значений переданных функции параметров.
Вот пример той же программы, но написанной более правильно: @array = (0..5); print("Before fuNCtion call, array = @array\n"); firstSub(@array); print("After fuNCtion call, array = @array\n"); sub firstSub{ ($firstVar, $secondVar) = @_ ; $firstVar = "A"; $secondVar = "B"; } Программа напечатает: Before fuNCtion call, array = 0 1 2 3 4 5 After fuNCtion call, array = 0 1 2 3 4 5
Как вы видите - функция присваивает значения переданных ей параметров новым переменным, и оперирует в дальнейшем только ими - не изменяя непосредственно массив параметров.
Но тогда вы можете столкнуться с другой проблемой: $firstVar = 10; @array = (0..5); print("Before fuNCtion call\n"); print("\tfirstVar = $firstVar\n"); print("\tarray = @array\n"); firstSub(@array); print("After fuNCtion call\n"); print("\tfirstVar = $firstVar\n"); print("\tarray = @array\n"); sub firstSub{ ($firstVar, $secondVar) = @_ ; $firstVar = "A"; $secondVar = "B"; } Программа напечатает: Before fuNCtion call firstVar = 10 array = 0 1 2 3 4 5 After fuNCtion call firstVar = A array = 0 1 2 3 4 5
То есть, по умолчанию все переменные в Perl-программе доступны из любого фрагмента кода. Это очень удобно во многих случаях, но нередко доставляет неудобства и приводит к неприятным ошибкам. Далее вы узнаете, как создавать переменные, видимые только внутри соответствующих функций.
Области действия переменных.
Области действия переменной - это те фрагменты кода, в которых вы можете использовать данную переменную. По умолчанию любая переменная в Perl-программы "видна" из любой точки программы.
Иногда бывает очень полезным ограничить область действия той или иной переменной внутри какой-либо функции. В этом случае изменение значения переменной внутри функции никак не отразится на остальных частях программы. В Perl имеются две функции - my() и local(). Первая создает переменную, которая видна только внутри данной функции. Вторая создает переменную, которую также могут "видеть" функции, вызванные из данной функции. firstSub("AAAAA", "BBBBB"); sub firstSub{ local ($firstVar) = $_[0]; my($secondVar) = $_[1]; print("firstSub: firstVar = $firstVar\n"); print("firstSub: secondVar = $secondVar\n\n"); secondSub(); print("firstSub: firstVar = $firstVar\n"); print("firstSub: secondVar = $secondVar\n\n"); } sub secondSub{ print("secondSub: firstVar = $firstVar\n"); print("secondSub: secondVar = $secondVar\n\n"); $firstVar = "ccccC"; $secondVar = "DDDDD"; print("secondSub: firstVar = $firstVar\n"); print("secondSub: secondVar = $secondVar\n\n"); } Программа напечатает: firstSub: firstVar = AAAAA firstSub: secondVar = BBBBB secondSub: firstVar = AAAAA Use of uninitialized value at test.pl line 19. secondSub: secondVar = secondSub: firstVar = ccccC secondSub: secondVar = DDDDD firstSub: firstVar = ccccC firstSub: secondVar = BBBBB
Как вы видите, функция secondSub() не имеет доступа к переменной $secondVar, которая была создана функцией my() внутри функции firstSub(). Perl даже вывел сообщение, предупреждая вас об этом. В то же время, переменная $firstVar доступна и может быть изменена функцией secondSub().
По возможности старайтесь обходиться только функцией my() и не использовать функцию local() - так вы обеспечите себе более строгий контроль над областью действия переменных.
На самом деле, функция my() гораздо более сложна и функциональна. Но об этом пойдет речь в главе 15 - "Модули Perl".
Вы помните, в чем разница между передачей параметров функции по ссылке и по значению? Если вы передаете параметры по значению, то функция не может изменять значения переданных ей параметров (переменных), а значит это никак не отразится на всей программе. Если же вы передаете параметры по ссылке, то функция может изменять значения параметров (переменных), и это отразится на основной программе. Так вот, при использовании функции local() метод передачи параметров по ссылке работает немного по-другому - функции могут менять значения переданных им параметров (переменных), но это отразится только на самой "верхней" функции - той, где была использована функция local(), - на основную же программу это никак не повлияет.
Использование списка в качестве параметра функции.
Теперь, когда мы разобрались с областью действия переменных, давайте посмотрим на параметры функций с другой стороны. Как мы уже сказали - все параметры функции передаются в одном массиве, но что делать, если вам нужно передать в функцию один параметр - скаляр, а второй параметр - массив? Следующий пример показывает, что произойдет: firstSub((0..10), "AAAA"); sub firstSub{ local(@array, $firstVar) = @_ ; print("firstSub: array = @array\n"); print("firstSub: firstVar = $firstVar\n"); } Программа напечатает: firstSub: array = 0 1 2 3 4 5 6 7 8 9 10 AAAA Use of uninitialized value at test.pl line 8. firstSub: firstVar = Вы видите, что при инициализации переменных массив @array поглощает все элементы массива параметров @_, ничего не оставляя скаларной переменной $firstVar. Это подтверждает и предупреждающее сообщение интерпретатора Perl. Вы можете решить данную проблему путем перестановки местами параметров - если вы поставите сначала скалярную переменную, а потом массив, то все будет так как надо: firstSub("AAAA", (0..10)); sub firstSub{ local($firstVar, @array) = @_ ; print("firstSub: array = @array\n"); print("firstSub: firstVar = $firstVar\n"); } Программа напечатает: firstSub: array = 0 1 2 3 4 5 6 7 8 9 10 firstSub: firstVar = AAAA
Вы можете передавать в функцию сколько угодно скалярных величин, но только один массив. Если вы попытаетесь передать в функцию несколько массивов, их элементы просто сольются в один массив, и функция не сможет узнать, - где заканчивается один массив и начинается другой.
Вложенные (рекурсивные) функции.
Функции могут вызывать сами себя, углубляясь на несколько уровней. На сколько - это зависит от конкретной реализации Perl, от конкретной аппаратной части и от конфигурации. Обычно, вам хватит ресурсов вашей машины, и беспокоиться об этом не стоит. Но если вам интересно, вы можете попробовать запустить вот такую программу: firstSub(); sub firstSub{ print("$count\n"); $count++; firstSub(); } Программа напечатает: Error: Runtime exception Перед тем, как напечатать это сообшение об ошибке, программа будет увеличивать значение переменной $count до тех пор, пока будет возможен рекурсивный вызов функции. Таким образом, по значению переменной $count вы можете узнать, сколько уровней рекурсивных вызовов допускает ваша система.
Но не увлекайтесь рекурсией - этим стоит заниматься вплотную в особенных случаях, например, при некоторых математических рассчетах.
Частные функции.
Вам может потребоваться использовать функцию с ограниченной областью действия. Как это устраивать с переменными, мы уже разобрались. Вот как это реализуется в случае с функциями: $temp = performCalc(10, 10); print("temp = $temp\n"); sub performCalc { my ($firstVar, $secondVar) = @_; my $square = sub { return($_[0] ** 2); }; return(&$square($firstVar) + &$square($secondVar)); }; Программа напечатает: temp = 200 Как вы видите, у нас имеется функция $square. Точнее, $square - это обычная скалярная переменная, ссылающаяся на функцию. Для обращения к функции мы используем знак & перед именем переменной $square. Эту функцию мы можем использовать только внутри функции performCalc() - она недоступна для остальной программы.
