4. Функции пользователя

 

Функции пользователя

 

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

Функции подразделяются на встроенные в ядро системы внутренние функции и функции, заданные пользователем. Примером первых могут быть Sin[x], Bessell [n, x] и т.д. Mathematica содержит множество таких функций, охватывающих практически все широко распространенные элементарные и специальные математические функции. Есть и возможность создания функций со специальными свойствами — чистых (pure functions) и анонимных функций.

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

Встроенные стандартные функции и их типовые применения уже были описаны в предшествующих уроках. Так что далее мы рассмотрим только задание функций особого вида, создаваемых пользователем или используемых в управляющих структурах программ.

Хотя в системах Mathematica имеется около тысячи встроенных функций, любому пользователю рано или поздно может потребоваться создание какой-либо своей функции. Кажется естественным задать ее по правилам, принятым во многих языках программирования. Например, функцию для возведения х в степень п можно было бы определить так:


powerxn[x, n] := x^n

Однако такая функция отказывается работать:


{powerxn[2, 3], powerxn[a, b]}

{powerxn[2, 3] , powerxn[a, b]}

Причина этого кроется в том, что в системе Mathematica символы х и n являются обычными символами, не наделенными особыми свойствами. Будучи использованными в качестве параметров функции, они не способны воспринимать формальные параметры [2,3] или [ а, b ]. Так что вычислить нашу ущербную функцию можно лишь при предварительном присваивании х иn нужных значений:


х := 2; n := 3; powerxn[x, n]

8

Разумеется, заданная таким образом функция является неполноценной. Для того чтобы функция пользователя нормально воспринимала переданные ей аргументы, в списке параметров надо использовать образцы в виде переменных, но имеющие после своих имен символы подчеркивания. Образцы способны быть формальными параметрами функций и воспринимать значения фактических параметров (в нашем случае значений 2 и 3). Таким образом, правильной будет запись функции пользователя в виде


powerxn[x_, n_] := х^n

Теперь вычисление по заданной функции пользователя пройдет гладко, причем как в численном, так и в символьном виде:


{powerxn[2, 3], powerxn[z, у], powerxn[x, n]}

{8, zy, 8}

Заметим, что для уничтожения определения заданной функции можно использовать команду-функцию Clear [Name_f unction], где Name_f unction — имя функции.

Можно также задать функцию пользователя, содержащую несколько выражений, заключив их в круглые скобки:


f[x_] := (t = (1 + х)^2; t = Expand[t])

Переменные списка параметров, после имен которых стоит знак «_», являются локальными в теле функции или процедуры. На их место подставляются фактические значения соответствующих параметров, например:


f [а + b]

1+2а+а2+2b+2ab+b2

t

1+2а+а2+2b+2ab+b2

Обратите внимание на то, что переменная t в функции f является глобальной. Это поясняет результат последней операции. Применение глобальных переменных . в теле функции вполне возможно, но создает так называемый побочный эффект — в данном случае меняет значение глобальной переменной t. Для устранения побочных эффектов надо использовать образцы и другие специальные способы задания функций, описанные ниже. Итак, можно сформулировать ряд правил для задания функций пользователя:

  • такая функция имеет идентификатор — имя, которое должно быть уникальным и достаточно понятным;
  • в списке параметров функции, размещенном в квадратных скобках после идентификатора, должны использоваться образцы переменных, а не просто переменные;
  • может использоваться отложенное (: =) или немедленное (=) присваивание;
  • тело функции может содержать несколько выражений, заключенных в круглые скобки, при этом возвращается значение последнего выражения;
  • переменные образцов в списке параметров являются локальными и действуют только в пределах тела функции;
  • в теле функции могут использоваться глобальные переменные, но при этом возможны побочные эффекты;
  • возможно обращение к функции из тела этой же функции (рекурсия).

Параметрами функций могут быть списки при условии допустимости их комбинации. Например, допустимо задать х списком, an — переменной или числом:


powerxn[{l, 2, 3, 4, 5}, z]

{1, 2Z, 3Z, 4Z, 5Z}

powerxn[{l, 2, 3, 4, 5}, 2]

{1, 4, 9, 16, 25}

После своего задания функции пользователя могут использоваться по тем же правилам, что и встроенные функции.

Чистые функции

Иногда может потребоваться создание функции, не имеющей имени (например, если функция будет использоваться только один раз, сразу же после ее создания). Эта функция представляется только выражением без идентификатора, отсюда и ее название — чистая функция (pure function). Для создания такого объекта служит встроенная функция Function, используемая в одном из следующих вариантов:

  • Function [body] — создает чистую функцию с телом body;
  • Function [ {х}, body ] — создает чистую функцию параметра х с телом body;
  • Function [ {xl, х2,...} ,body] — создает чистую функцию ряда параметров x1, х2, ... с телом body.

Для вычисления созданной таких образом функции после нее задается список параметров в квадратных скобках. Например, взятую ранее в качестве примера функцию возведения в степень можно задать и использовать следующим образом:


Function[{x, n}, x^n]

Function! {х, п), xn]

%[2, 3]

8

Чистую функцию можно легко превратить в обычную функцию пользователя, что показывает следующий пример:


fun=Function[{x,n},х^n]

Function[ {х, n}, хn]

{fun[2,3],fun{z,y}}

{8, zy }

Анонимные функции

Предельно компактную форму задания имеют так называемые анонимные функции. Они не имеют ни названия, ни обычного определения и задаются только выражениями специального вида. В этом выражении вместо переменных используют обозначения # (для одной переменной) или #1, #2, ... (для ряда переменных). Завершается тело функции символом «&». Если надо вычислить функцию, то после ее записи в квадратных скобках указывается список фактических параметров.

Для нашего примера анонимная функция выглядит так:


#1^#2 &[2, 3]

8

#1^#2 &[у, z]

y^z

С помощью анонимных функций нетрудно создавать обычные функции пользователя:


f[x_, y_] = #1^#2 &[х, у]

хy

f[2, 3]

8

Несмотря на то что применение анонимных функций открывает возможности компактного задания многих функций, эта форма едва ли интересна для большинства читателей — они наверняка предпочтут пусть немного более длинное, но значительно более очевидное задание функций другими способами.