Анимация
JavaScript
|
Главная Библионтека sub mess with f00 { Sfoo=0; SLbmyfunc { locals£00=20; mess with foo(); myfunc(); abness with foo { $foo=0; > submyfunc { nySf00=20; , mess with foo( J pint $f 0?; myfunс{); Два фрагмента текста, приведенные в табл. 8.1, практически идентичны, за исключением объявления неременной $foo в функции niyfunc(). Слева эта неременная объявлена как приватная, а справа - как локальная. В коде слева функция mess with foo() изменяет глобальную неременную $foo. После возвращения управления в myfunc<) будет напечатано число 20, так как приватная переменная $foo, принадлежащая этой функции, не была изменена. В коде справа в функции th foo() создается локальная переменная $foo. Затем функция mesB with foo(} устанавливает для переменной $foo значение 0. Это та же переменная, что и B~myfunc(), - локальные переменные передаются в подпрограммы. После возвращения в будет напечатано значение 0. Специально для любителей терминологии сообщим, что локальные переменные также называются переменными с динамической областью видимости, так как их область видимости изменяется по мере вызова подпрограмм. Переменная, объявленная с помощью оператора ту, \лмеетлексическую область видимости, которая сравнительно просто определяется после анализа кода, Лексическая область видимости совпадает с блоком, в котором была объявлена данная переменная, причем s процессе выполнения программы эта область не изменяется. Итак, если вам нужно объявить по-настоящему приватную переменную, используйте оператор ray. Как сделать Perl строже Perl - снисходительный и терпимый язык программирования. Он не обращает особого внимания на то, как выглядит ваш код, лишь бы он работал. Но имеется возможность указать интерпретатору Perl, чтобы тот более взыскательно анализировал исходный код. Например, предупреждения, включенные в командную строку или в первую строку программы, позволяют избежать многих досадных ощибок. Perl предупреждает об использовании неопределенных переменных, однократном использовании имен и подобных вещах. При разработке больщих программных проектов (особенно по мере усложнения программы) бьшо бы неплохо, чтобы Perl хоть как-то удерживал вас от соверщения случайных ощибок. Кроме ключа -w, в интерпретаторе Perl имеются и другие средства для вывода дополнительных предупреждений во время компиляции. Для этого используется оператор use strict: use strict; sub musub { $x; ! mysub(); Чть I. :Ei Perl Оператор use strict называется директивой компилятора. Эта директива указывает Perl, что необходимо отслеживать перечисленные ниже ситуации и выводить сообщения об ошибках времени выполнения с информацией о текущем файле и блоке. • Использование имени переменной, не являющейся специальной, без ее объявления в онераторе ту. • Использование недопустимого имени функции (бе и скобок) перед тем, как эта функция была определена. • Другие потенциальные ошибки Директива use strict помогает справиться с первыми двумя проблемами. Теперь в программе вы уже не сможете использовать глобальную переменную вместо приватной. Это способствует созданию более изолированного кода, не полагающегося на использование глобальных переменных. Другая ловушка, выпутаться из которой помогает директива use strict, - использование недопустим1х ключев1х слов. Посмотрите на код $var=value; В данном случае непонятно, что такое value - строка без кавычек или имя функции. При использовании директивы use strict Perl сообщит, что этот код непонятен и синтаксически недопустим, если только соответствующая функция предварительно не определена. С этого момента все примеры и относительно длинные листинги в книге будут содержать директиву use strict. Рекурсия Рано или поздно вы познакомитесь со специальным классом подпрограмм. Во время своей работы эти подпрограммы вызывают сами себя. Они называются рекурсивными подпрограммами. Рекурсивные подпрограммы используются в случае, если задача может быть сведена к решению более простой идентичной задачи, а та, в свою очередь, - к еще более простой, и т.д. Одна из рекурсивных задач - поиск файла в древовидной структуре каталогов: вначале поиск ведется в самом верхнем каталоге, затем наступает очередь подкаталогов и т.д. Как видите, в данном случае подзадачи идентичны основной задаче. Другая рекурсивная задача связана с вычислением факториалов. Факториалы используются в статистике. Количество перестановок букв ABCDEF равняется факториалу шести. Факториал - это произведение всех цел1х чисел, меньших данного, включая 1. Например, факториал числа 6 - 6x5x4x3x2x1 или 720. Для вычисления факториала 6 необходимо факториал 5 умножить на 6. Для вычисления факториала 5 Необходимо факториал 4 умножить на 5 и т.д. Рекурсивная функция для нахождения факториалов приведена в листинге 8.3. Лист 8.3. ВЬч: фарриов с мюью ракурса 1: sub fectodal { 2: my {Snum)=i ; return(l) if(5num <= 1); return($nuin*factorial($!ium-l)); 6: print factorial(6); ! Проведем анализ программы. • Строка 2. Аргумент подпрограммы factorial!) присваивается переменной которая объявлена в данной подпрограмме как приватная. • Строка 3. Для каждой рекурсивной функции необходимо предусмотреть условие прекращения. Это то значение аргумента, при котором функция больше не вызывает сама себя. Для подпрограммы factorial() условие прекращения - это вычисление факториала 1 или 0. Два приведенных значения равны единице, поэтому подпрограмма factorial(), вызванная с аргументом 0 или 1, выполняет код return(l) (это случай $пшп<=1). • Строка 4. Если аргумент не равен нулю или единице, вычисляется факториал предыдущего числа, как показано ниже. $ р.. зоке 4вычисляется... б return!6*factorial(5)) 5 return(5*factorial(4)) 4 return (4*factoriaH3)) 3 return(3*factorial(3)} 2 return(2*factorial(l)) 1 строка 4 не выполняется; функция factorial(l) возвращает зна- чение 1 В результате выполнения цепочки вызовов рекурсивных функций будут последовательно вычислены факториалы всех чисел, меньших данного. Их значения по цепочке передаются в вызвавшие их функции, и в конце концов вычисляется значение факториала 6. Рекурсивные функции встречаются не часто. Большие рекурсивные функции тяжело создавать и отлаживать. Любая задача, решаемая с помощью циклов for, while, foreach, может быть решена при помощи рекурсии, и, наоборот, всякая рекурсивная задача может быть выполнена с помощью циклов. Рекурсивные процедуры обычно используются для решения относительно небольшого круга задач, естественным образом формализуемых с помощью метода рекурсии. Резюме Perl поддерживает определяемые пользователем функции, называемые подпрограммами, которые ведут себя подобно встроенным функциям. Им можно передавать аргументы; при необходимости подпрограммы пользователя могут возвращать значения в место вызова. Функции Perl могут вызывать другие функции и даже самих себя. В Perl также можно объявить приватную переменную внутри функции или блока кода и создать законченные фрагменты кода, допускающие повторное использование. Вопросы и ответы Есть ли на самом деле какая-то разница при вызове функции с символом & и без него? Нет ничего такого, что могло бы иметь к вам какое-нибудь отношение. Существует небольшая разница между вызовами ifoo и foo при использовании прототипов функций 136 Часть I. HOEi Perl 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 [ 39 ] 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |