Россия, Новосибирск, НГПУ, 1994 |
Функциональное программирование
9.1.4. Атрибут функций Listable
П. Веллин и др. [14, с. 80–82] наравне с функциями уделяет особое внимание такому атрибуту функций, как Listable. И нам следует познакомиться с этим атрибутом ближе.
Множество встроенных функций Mathematica, имеющих один аргумент, если они содержат в качестве аргумента список, применяются в отдельности к каждому элементу списка. Одна из таких функций — функция нахождения синуса угла Sin. Так выражения Sin[{a,b,c}] и Map[Sin,{a,b,c}] при вычислении имеют одинаковые результаты (см. примеры In[1] и In[2] на рис. 9.8, соответственно).
Множество встроенных функций Mathematica, имеющих два и более аргументов, если аргументы являются списками, применяются к соответствующим элементам списков в отдельности. Среди таких функций — Plus. Так одинаковыми являются результаты вычислений выражений Plus[{1,2,3},{x,y,z}] и MapThread[Plus,{{1,2,3},{x,y,z}}] (примеры In[3] и In[4] на рис. 9.8, соответственно).
Функции, которые автоматически применяются не к целым спискам, а к элементам списков, обладают атрибутом Listable. Убедиться в наличии этого атрибута у функции можно при помощи функции Attributes, что мы и делаем в примерах In[5] и In[6] на рис. 9.8. для функций Sin и Plus.
Если выражение не обладает атрибутом Listable, как применённая нами к некоторому списку {k,l,m,n} неопределённая функция g в примере In[7], то добавить его в список атрибутов выражения можно при помощи функции SetAttributes. В примере In[8] мы устанавливаем функции g атрибут Listable, а в In[9] вновь пытаемся вычислить выражение In[7]. Если в Out[7] функция g оказалась применена ко всему списку, то в In[9] — к каждому элементу списка в отдельности.
Избавить выражение от любого присущего ему атрибута можно при помощи функции ClearAttributes. В примере In[10] мы удаляем из списка атрибутов функции Sin атрибут Listable: теперь, как иллюстрирует пример In[11], Sin будет применяться ко всему списку в целом.
9.1.5. Функции Inner и Outer
Функция Outer[func,list1,list2,...] применяет функцию func ко всевозможным комбинациям элементов списков list1,list2,... (пример In[1] на рис. 9.9), при этом совершенно необязательно, чтобы списки содержали одинаковое число элементов (пример In[2]). При помощи Outer можно, например, из нескольких списков сформировать один вложенный список со всевозможными сочетаниями элементов: для этого первым аргументом следует задать заголовок List (пример In[3]).
Если аргументы list1,list2,... являются вложенными списками, то уровень вложенного списка, с которым следует проводить манипуляции, указывается в качестве дополнительно аргумента n, то есть, функция задаётся в виде Outer[func,list1,list2,...,n]. В примере In[4] на рис. 9.9 мы воспользовались функцией Outer без дополнительных аргументов для двух двухуровневых вложенных списков. По умолчанию функция func (в нашем примере это неопределённая функция g) применяется к комбинациям элементов самого низшего уровня вложенных списков (в нашем примере это уровень 2). В примере In[5] мы указали дополнительным аргументом, что оперировать следует элементами списков первого уровня.
Кроме того, для разных списков можно задавать разные уровни элементов, участвующих в вычислениях. Для этого соответствующая функция задаётся в виде Outer[func,list1,list2,...,n1,n2,...]. В примере In[6] на рис. 9.9 мы указываем, что в первом списке следует оперировать элементами второго уровня, а во втором — первого.
Глубина списков в аргументах функции Outer может быть разной. Так в примере In[7] на рис. 9.9 мы задали в качестве аргументов одноуровневый и трёхуровневый списки и получили результирующий четырёхуровневый список.
Функция Inner[func1,{a1,a2,…},{b1,b2,…},func2] в качестве результата генерирует выражение func2[func1[a1,b1],func1[a2,b2],...], то есть, сначала она формирует из двух списков аргументы для функции func1, а полученный результат задаёт в качестве аргументов функции func2. На рис. 9.10 мы привели абстрактный пример In[1] последовательного применения неопределённых функций f1 и f2 к спискам из четырёх элементов {w,x,y,z} и {10,20,30,40}, а также конкретный пример In[2] перемножения соответствующий элементов тех же списков (при помощи функции Times) и последующего сложения результатов (Plus).
Подробней о функциях Inner и Outer см. книги Е. М. Воробьёва [1, с. 122–123] и П. Веллина и др. [14, с. 84].