|
Андрей Сергиенко e-mail - erazer@erazer.virtualave.net site - http://erazer.virtualave.net Продолжаем изучать Perl. В этой главе мы обратим свой взор на функции. Функции - это блоки кодов, которым даются названия, чтобы мы могли использовать их при необходимости. Функции помогают организовывать код в простые для понимания фрагменты. Они позволяют создавать программу шаг за шагом, тестируя ее по ходу. После того, как у Вас появится идея программы, Вы должны разработать схему ее построения - в вашей голове или на бумаге. Каждый шаг в схеме мог бы являть собой одну функцию в вашей программе. Это называется модульным программированием. Модульное программирование очень хорошо позволяет Вам скрывать детали программы, благодаря чему улучшается читабельность исходного текста вашей программы. Например, если ваша программа содержит функцию, которая вычисляет площадь
круга, следующей строкой Вы можете обратиться к ней: Глядя на подобные вызовы функций, человек, читающий исходный код вашей программы, понимает, что ваша программа делает. В то же время, ему не нужно знать, как конкретно реализована та или иная функция. Поэтому важно давать функциям "говорящие" имена - чтобы по имени можно было понять, что именно функция делает. Вызов функции означает, что интерпретатор Perl в месте вызова функции прекращает выполнение текущей серии строк кода и переходит к выполнению кода функции. При завершении кода функции интерпретатор возвращается в точку вызова и продолжает выполнение программы со следующей строки. Давайте присмотримся к вызову функции - сначала мы видим скалярную переменную, затем - оператор присвоения. Вы уже знаете, что это означает - Perl присвоит переменной $areaOfFirstCircle значение, стоящее справа от знака присваивания. Но что в действительности стоит справа? Первое, что вы видите - это имя функции areaOfCircle(). Круглые скобки справа и отсутствие перед именем символов $, @ и % говорит о том, что это - вызов функции. Внутри круглых скобок содержится список параметров или значений, передающихся функции. Вычисление площади круга: Программа напечатает: Объявление функции: И все. Ваша функция готова. Сложнее дело обстоит с параметрами. Параметры - это значения, которые мы передаем в функцию. Параметры содержатся внутри круглых скобок, следующих сразу за именем функции. В примере выше вызов функции - это areaOfCircle(5). Здесь мы использовали только один параметр. Но даже в том случае, если функция имеет только один параметр, Perl при вызове функции создает массив параметров для использования их функцией. Внутри функции массив параметров имеет имя @_. Все параметры, передаваемые функции, содержатся в массиве @_, откуда их можно извлечь при необходимости. Наша маленькая функция из примера выше могла бы сделать это следующей
строкой: Эта строка присваивает первый элемент массива @_ скалярной переменной $radius. Если вы хотите, вы можете не использовать в функции оператор return для возврата значения, - Perl автоматически возвратит значение последнего вычисленного выражения. Но будет лучше, если вы все же будете использовать оператор return - так вы избежите многих случайных ошибок. Возможно вы встречали в некоторых языках программирования различия между подпрограммами и функциями. В таких языках функция обязательно возвращает значение, в то же время, подпрограмма значение не возвращает. В Perl же такого нет - у вас есть только функция - независимо от того, возвращает она какое-либо значение или нет. Использование массива параметров (@_) Как уже говорилось ранее - все параметры функция может найти в массиве
параметров @_. Это очень удобно - чтобы узнать, сколько параметров было
передано функции, нужно всего лишь обратиться к массиву параметров @_
в скалярном контексте. Perl позволяет вам передавать в функцию любое число параметров. Функция сама может определить, какие параметры ей использовать, и в какой последовательности. Массив параметров @_ может использоваться так же, как и любой другой массив. Конечно, это не очень удобно - обращаться к переданным функции параметрам
по их номерам - @_[0] или @_[1]. Вы можете воспользоваться более удобной
технологией: Передача параметров функции по ссылке. Если вы передаете в функцию не какое-либо число, а переменную, то в
случае изменения ее значение внутри функции, она также изменяется и для
всей остальной программы. Это называется передача параметров по ссылке.
Как вы видите, функция изменила значение переданных ей параметров, и это повлияло также на работу остальной программы - значения массива @array изменились не только для функции, но и для всей остальной программы. Это плохая практика программирования - если у вас нет именно такой конкретной цели, то никогда не пользуйтесь подобными премами - они чреваты неочевидными ошибками. С другой стороны, если вы в начале функции присваиваете значения переданных параметров новым переменным (как было показано ранее), и работаете в дальнейшем только с ними - такой проблемы у вас не возникнет - ведь вы в данном случае на самом деле не изменяете значений переданных функции параметров. Вот пример той же программы, но написанной более правильно: Как вы видите - функция присваивает значения переданных ей параметров новым переменным, и оперирует в дальнейшем только ими - не изменяя непосредственно массив параметров. Но тогда вы можете столкнуться с другой проблемой: То есть, по умолчанию все переменные в Perl-программе доступны из любого фрагмента кода. Это очень удобно во многих случаях, но нередко доставляет неудобства и приводит к неприятным ошибкам. Далее вы узнаете, как создавать переменные, видимые только внутри соответствующих функций. Области действия переменных. Области действия переменной - это те фрагменты кода, в которых вы можете использовать данную переменную. По умолчанию любая переменная в Perl-программы "видна" из любой точки программы. Иногда бывает очень полезным ограничить область действия той или иной
переменной внутри какой-либо функции. В этом случае изменение значения
переменной внутри функции никак не отразится на остальных частях программы.
В Perl имеются две функции - my() и local(). Первая создает переменную,
которая видна только внутри данной функции. Вторая создает переменную,
которую также могут "видеть" функции, вызванные из данной функции. Как вы видите, функция secondSub() не имеет доступа к переменной $secondVar, которая была создана функцией my() внутри функции firstSub(). Perl даже вывел сообщение, предупреждая вас об этом. В то же время, переменная $firstVar доступна и может быть изменена функцией secondSub(). По возможности старайтесь обходиться только функцией my() и не использовать функцию local() - так вы обеспечите себе более строгий контроль над областью действия переменных. На самом деле, функция my() гораздо более сложна и функциональна. Но об этом пойдет речь в главе 15 - "Модули Perl". Вы помните, в чем разница между передачей параметров функции по ссылке и по значению? Если вы передаете параметры по значению, то функция не может изменять значения переданных ей параметров (переменных), а значит это никак не отразится на всей программе. Если же вы передаете параметры по ссылке, то функция может изменять значения параметров (переменных), и это отразится на основной программе. Так вот, при использовании функции local() метод передачи параметров по ссылке работает немного по-другому - функции могут менять значения переданных им параметров (переменных), но это отразится только на самой "верхней" функции - той, где была использована функция local(), - на основную же программу это никак не повлияет. Использование списка в качестве параметра функции. Теперь, когда мы разобрались с областью действия переменных, давайте
посмотрим на параметры функций с другой стороны. Как мы уже сказали -
все параметры функции передаются в одном массиве, но что делать, если
вам нужно передать в функцию один параметр - скаляр, а второй параметр
- массив? Следующий пример показывает, что произойдет:
Вы можете передавать в функцию сколько угодно скалярных величин, но только один массив. Если вы попытаетесь передать в функцию несколько массивов, их элементы просто сольются в один массив, и функция не сможет узнать, - где заканчивается один массив и начинается другой.
Вложенные (рекурсивные) функции. Функции могут вызывать сами себя, углубляясь на несколько уровней. На
сколько - это зависит от конкретной реализации Perl, от конкретной аппаратной
части и от конфигурации. Обычно, вам хватит ресурсов вашей машины, и беспокоиться
об этом не стоит. Но если вам интересно, вы можете попробовать запустить
вот такую программу: Но не увлекайтесь рекурсией - этим стоит заниматься вплотную в особенных случаях, например, при некоторых математических рассчетах. Частные функции. Вам может потребоваться использовать функцию с ограниченной областью
действия. Как это устраивать с переменными, мы уже разобрались. Вот как
это реализуется в случае с функциями: |