* Подпрограммы * 


Для применения подпрограммы ее необходимо определить либо в текщем модуле
(файле) либо во внешнем модуле (файле).
Подпрограммы определяются и декларируются следующим образом:

	sub имя;	# Только декларация. Определение ниже.

	sub имя (прототипы);  То же но с декларацией параметров.

	sub имя блок;	# Декларация и определение.

	sub имя (прототипы) блок; # То же, но с парамметрами.

Для определения динамичской анонимной подпрограммы можно указать:

	$переменная = sub блок;

Для импортирования подпрограмм из других модулей используйте:

	use модуль qw(подпрограмма1 подпрограмма2 );

Вызов подпрограммы:

	имя(список параметров);	# символ '&' можно не указывать.

	имя список;	# Если подпрогрмма уже декларирована.

	&имя;		# Параметры в @_

Все параметры передаются подпрограмме как массив @_.
Соответсвенно $_[0] - первый параметр, $_[1] - второй и т.д.
Массив @_ - локальный, но он содержит адреса параметров поэтому
можно изменять значение параметров.
Возвращаемое значение подпрограммы - результат последнего оператора.
Это может быть как скаляр так и массив. Можно принудительно возвращать
результат используя функцию return().

Подпрограмму можно вызвать используя префикс '&' перед именем
подпрограммы. Если подпрограмма предварительно продекларирована то
префикс и скобки можно опустить.



Для применения переменных доступных только внутри блока или подпрограммы
необходимо определить их с помощью функции my(список).

Если переменная одна то скобки можно опустить.

my() декларирует private переменные в пределах текущей подпрограммы,
блока, функции eval() или do/require/use файлов. Private переменные
аналогичны auto переменным в С.

Пример:

	# Программа вычисления факториала.

	print fact(3);  # вычислить факториал 3*2*1

	sub fact	# Определяем подпрограмму.
	{ my $m;                # private переменная но не local !
	$m = $_[0];
	return 1 if $m <= 1;
	return($m * fact($m -1));
	}

Можно указывать начальные значения private переменных как:

	my(список) = выражение;

Так для вышеприведенного примера лучше было написать:

	my($m) = $_[0];


Переменные типа local.

В общем лучше использовать private переменные так-как это надежней и
быстрее. private переменные обеспечивают лексическую область применения
(видимости) а local - динамическую. Обычно это переменные форматов
значение которых должно быть видимо из вызываемых подпрограмм.
Применение функции local() не целесообразно в циклах так как
она вызывается каждый раз и таким образом заметно замедляет время
выполнения цикла.




Для краткого описаня типа параметров передаваемых подпрограмме
можно применять прототипы. В Пел существуют следующие прототипы:

	Декларация		Пример вызова

	sub mylink($$)		mylink $old, $new
	sub myvec($$$)		myvec $var, $offset, 1
	sub myindex($$;$)	myindex &getstring, "substr"
	sub myreverse(@)	myreverse $a, $b, $c
	sub myjoin($@)		myjoin ":",$a,$b,$c
	sub mypop(\@)		mypop @array
	sub mysplice(\@$$@)	mysplice @array, @array, 0, @pushme
	sub mykeys(\%)		mykeys %{$hashref}
	sub myopen(*;$)		myopen HANDLE, $name
	sub mypipe(**)		mypipe READHANDLE, WRITEHANDLE
	sub mygrep(&@)		mygrep { /foo/ } $a, $b, $c
	sub myrand($)		myrand 42
	sub mytime()		mytime

Здесь:
	\'символ'	- параметр с типом 'символ'

	'@' или '%'	- все оставшиеся параметры как список

	'$'		- скаляр

	'&'		- безимянная подпрограмма

	'*'		- ссылка на таблицу имен

	';'		- разграничитель обязательных и не обязательных параметтров.




Иногда нужно в качестве параметра передать подпрограмме не значение
элемента массива а ссылку на него, что бы подпрограмма могла изменить
значение элемента. Для этого в Пел к имени переменной добавляется
символ '*' Подбное выражение называют 'type glob' так как в Юниксе
символом '*' обозначают "все возможные значения". Поэтому '*' для
массива означает "все элементы массива".
Для скаляров употряблять '*' не имеет смысла т.к. они и так передаются
ссылкой и вы можете изменять значение параметра изменяя например
переменную $_[0].




Большинство встроенных функций Пел можно переопределить своими
собственными. Обычно это делают для удобства совместимости Пел для
разных платформ систем.

Для этого нужно перечислить имена этих функций в виде:

	use subs 'функция1', 'функция2' ....;

и далее в модуле определить сами функции.




Если вы попытаетесь вызвать не существующую функцию то Пел выдаст
немедленно сообщение об ошибке. Но если вы определите подпрограмму
с именем 'AUTOLOAD' то она будет вызвана с теми же параметрами
а переменная $AUTOLOAD будет содержать имя не существующей
подпрограммы. Данный механизм очень удобен для средств отладки.


Last-modified: Thu, 24-Apr-97 18:06:07 GMT