> Kr[Sv]:= 3: Kr[S]:= proc() 'procname(args)' end proc: Kr[W]:= readlib(ifactors): > with(Kr), Sv, S(42, 47, 67, 62, 89, 96), ifactors(2006);
[S, Sv, W], 3, S(42,47,67,62,89,96), [1, [[2, 1], [17, 1], [59, 1]]]
Это обстоятельство можно достаточно эффективно использовать при программировании в среде Maple-языка. Например, определив в качестве выходов Т-таблицы определения разных процедур, можно весьма просто организовывать их условное выполнение, как это иллюстрирует следующий весьма простой фрагмент:
> T[x]:=proc() `+`(args) end proc:T[y]:=proc() nargs end proc:T[z]:=proc() `*`(args) end proc: > if whattype(AGN) = 'symbol' then op(with(T, x)(64, 59, 39))/op(with(T, y)(64, 59, 39)) else op(with(T, z)(64, 59, 39)) end if; ⇒ 54
Наряду с отмеченными имеется еще целый ряд весьма интересных применений табличных структур Maple-языка, полезных для практического программирования в среде пакета [8-14,41,103]. Мы же в качестве примера представим один простой и в ряде случаев полезный тип пакетных модулей. Предположим, что определения 4-х процедур f1, f2, f3, f4 помещены в массив (array), который сохраняется в Maple-библиотеке Svetlana.
Для обеспечения доступа к такого типа нестандартным пакетным модулям создается весьма простая процедура ArtMod(L, f {, args}), первый формальный аргумент L которой определяет имя пакетного модуля, второй – имя f содержащейся в нем процедуры; тогда как остальные аргументы необязательны, определяя передаваемые f-процедуре фактические аргументы args. Если в качестве второго фактического аргумента указано `?`значение, то возвращается список имен процедур, содержащихся в L-модуле; при этом, все они становятся активными в текущем сеансе. Таким образом, процедуру ArtMod можно рассматривать в качестве некоторого аналога процедуры with пакета. Нижеследующий фрагмент представляет исходный текст процедуры, создание пакетного модуля Art и иллюстрирует вызовы процедур из модуля Art на конкретных фактических аргументах.
> ArtMod:=proc (L::symbol, f::symbol) local a,k; [`if`(type(L,'list'), assign('a'=L), `if`(type(L, 'array'), assign('a' = map(op, convert(L, 'list1'))), ERROR("structure type of module <%1> is invalid", L))), `if`(convert(args[2], 'string') = "?", RETURN(map(lhs, a), seq(assign(a[k]), k=1..nops(a))), [add(`if`(lhs(a[k]) = f, RETURN(rhs(a[k])(args[3..nargs])),1), k=1..nops(a)), ERROR("procedure <%1> does not exist in package module <%2>", f, L)])] end proc; ArtMod := proc(L::symbol, f::symbol) local a k, ; [`if` type( ,( L 'list'), assign(' 'a = L), `if` type( ,( L 'array'), assign(' 'a = map(op, convert(L, 'list1'))), ERROR "structure type of module <( \ %1> is invalid", L))), `if`(convert(args[2], 'string') = "?", RETURN(map(lhs a, ), seq(assign(a k[ ]), k = 1 .. nops(a))), [add( `if`(lhs(a k[ ]) = f, RETURN(rhs(a k[ ])(args 3 .. nargs[ ])), 1), k = 1 .. nops( )a ), ERROR("procedure <%1> does not exist in package module <%2>", ,f L)])] end proc > Kr:=array(1..2,1..2, [[f1=(() -> `+`(args)/nargs), f2 =(() -> add(args[k]^2, k=1..nargs)/nargs)], [f3 = (() -> [`+`(args), nargs]), f4 = (() -> `*`(args))]]); Kr := f3 = f1(( ) = → ( )[ → `+` args(`+` argsnargs( ), nargs) ]) f2 = ( )f4 → = add args ,(( )( → `*`(args)k2nargsk = 1 .. ) nargs) > savelibname:= "C:/Program Files/Maple 10/LIB/Svetlana": savelib(Kr); restart; > 2006*ArtMod(Kr, f4, 42, 47, 67, 89, 96), ArtMod(Kr, f3); ⇒ 2266804778112, [0, 0] > restart; ArtMod(Kr, `?`), 2006*f4(64, 59, 39, 44, 10, 17); ⇒ [f1, f2, f3, f4], 2209678648320 > 6*seq(k(64, 59, 39, 44, 10, 17), k = [f1, f2, f3, f4]); ⇒ 233, 11423, [1398, 36], 6609208320 |
Представленный выше фрагмент иллюстрирует создание пакетного модуля Kr, использующего структуру массива, с последующим сохранением его в Maple-библиотеке пользователя Svetlana. Остальные примеры фрагмента иллюстрируют использование процедуры ArtMod для того, чтобы обеспечить доступ к данному пакетному модулю. При вызове ArtMod процедуры поиск указанного ее первым фактическим аргументом модуля L производится сначала среди активных средств текущего сеанса пакета и только после этого в цепочке библиотек, определенной предопределенной libname-переменной. В ряде случаев подобные нестандартные подходы к организации структур пакетных модулей оказываются значительно эффективнее стандартных, поддерживаемых средствами пакета, позволяя выполнять над структурами таких модулей необходимые символьные вычисления и преобразования. Наш опыт апробации и эксплуатации пакета Maple релизов с 4-го по 10-й со всей определенностью говорят в пользу данного утверждения.
В заключение данного раздела кратко напомним способы обращения к пакетныму модулю и содержащимся в нем объектам в целом, предполагая, что модуль находится в библиотеке, логически связанной с главной библиотекой пакета:
М[Function](args), М:- Function(args) – вызов пакетной функции на заданных фактических аргументах args при условии, что пакетный модуль М имеет модульную структуру, в противном случае второй формат вызова инициирует ошибочную ситуацию с диагностикой «Error, `М` does not evaluate to a module». Первый формат корректен для пакетного модуля любого типа
with(M) – возврат списка имен объектов, находящихся в модуле М, с их автивацией в текущем сеансе. После такого вызова доступ к функциям модуля М обеспечивается в обычном формате Function(args); при этом, появление предупреждений типа «Warning, the name N has been redefined» говорит, что одноименная с библиотечной процедура N пакетного модуля заменила собой библиотечное средство. Во избежание этого рекомендуется использовать разовые вызовы пакетных средств по конструкциям следующего формата М[Function](args), М:- Function(args)
with(М, f1, f2, ...) – возврат списка имен [f1, f2, ...] объектов модуля М с активацией в текущем сеансе приписанных им определений. После данного вызова доступ к функциям f1, f2, ... модуля М обеспечивается в обычном формате fj(args)
packages() – возврат упорядоченного (согласно порядка обращения к модулям) списка имен всех пакетных модулей, хоть один экспорт которых был активирован в текущем сеансе ListPack() – возврат списка всех пакетных модулей, находящихся в главной Maple-библиотеке, ListPack(F) – возврат списка всех пакетных модулей, находящихся в Maple-библиотеке, имя которой или полный путь к ней определены фактическим аргументом F.
Примеры нижеследующего фрагмента иллюстрируют вышесказанное:
> with(linalg); [BlockDiagonal,GramSchmidt, JordanBlock,LUdecomp, QRdecomp, Wronskian, addcol, addrow, ==================================================================== submatrix, sylvester, toeplitz, trace, transpose, vandermonde, vecpotent, vectdim, vector, wronskian] > restart; with(linalg, det, rank); ⇒ [det, rank] > restart; m:= matrix(3, 3, [x, y, z, a, b, c, d, g, h]): linalg[det](m), linalg[rank](m); x b h - x c g - a y h + a z g + d y c - d z b, 3 > restart; m:= matrix(3, 3, [x, y, z, a, b, c, d, g, h]): linalg:- det(m), linalg:- rank(m); Error, `linalg` does not evaluate to a module > map(M_Type, [linalg, LinearAlgebra]); ⇒ [Tab, Mod] > restart; N:=Matrix(3, 3, [[x, y, z], [a, b, c], [d, g, h]]): LinearAlgebra:- Determinant(N), LinearAlgebra:- Rank(N); ⇒ x b h - x c g - a y h + a z g + d y c - d z b, 3 > restart; m:=matrix(3, 3, [x, y, z, a, b, c, d, g, h]): with(linalg, det, rank), det(m), rank(m); [det, rank], x b h - x c g - a y h + a z g + d y c - d z b, 3 > restart; map(with, [plots, linalg, LinearAlgebra, plottools]): packages(); Warning, the name changecoords has been redefined Warning, the protected names norm and trace have been redefined and unprotected Warning, the name arrow has been redefined [plots, linalg, LinearAlgebra, plottools] > restart; p:= x^3+10*x^2+17: m:=matrix(3, 3, [x, y, z, a, b, c, d, g, h]): norm(p, 1), linalg[norm](m); ⇒ 28, max(|x| + |y| + |z|, |d + |g| + |h|,|a| + |b| + |c|) > ListPack(); # Maple 8 {simplex, polytools, padic, geom3d, student, tensor, geometry, PDEtools, powseries, plots, plottools, =================================================================== Domains, liesymm, Sockets, SNAP, VectorCalculus,Units, Maplets,Worksheet, stats, SolveTools} > ListPack("C:/Program Files/Maple 8/LIB/UserLib"); {ACC, boolop, DIRAX, SimpleStat, SoLists, AlgLists} |
В заключение данного раздела сделаем еще одно существенное замечание. Процедура with пакета используется для обеспечения удобного доступа к модульным средствам пакета, в удобной форме на интерактивном уровне. Это - команда, которая обеспечивает функциональные возможности, аналогичные предложению use, но работает на интерактивном уровне и применима ко всем пакетным и программным модулям. При этом, предложение use обеспечивает средства только для работы с программными модулями.
Процедура with эффективна только на верхнем уровне и предназначена, прежде всего, для интерактивного использования. Поскольку with работает, используя специальный лексический предпросмотр, она не работает в телах процедур либо модулей. Между тем, в релизах 6-9 формат with работает корректно в телах процедур и модулей, тогда как в Maple 10 она не работает корректно в телах процедур либо модулей, выводя соответствующие предупреждения.
Наша процедура With [103] устраняет данный недостаток, позволяя корректно использовать вышеупомянутый формат в телах процедур и модулей. В целом ряде случаев это обеспечивает более удобное представление алгоритмов в среде Maple-языка. Наряду с этим, вызов процедуры With(P, Fo {, F1 {….}}) присваивает именам {Fo, F1,…} protected-атрибут, отсутствующий для стандартных средств пакета.