Имя:= table([P1 = proc(..) .. end proc, P2 = proc(..) .. end proc, …, Pn = proc(..) .. end proc]) где Имя – имя таблицы (впоследствии пакетного модуля) и Pj – имена процедур. При этом, в качестве выходов таблицы наряду с определениями процедур могут выступать также вызовы процедур, функций или произвольные Maple-выражения. На третьем заключительном этапе таблица сохраняется описанным выше способом в Maple-библиотеке. Если библиотека логически связана с главной библиотекой пакета, то сохраненная в ней таблица и будет вашим пакетным модулем. Рассмотрим пример создания простого пакетного модуля табличного типа.
> restart; TabMod:= table([Sr = proc() evalf(`+`(args)/nargs, 6) end proc, Ds = proc() local k; evalf(sqrt(sum((Sr(args) - args[k])^2, k = 1..nargs)/nargs), 6) end proc]):
> TabMod[Art]:= () -> `*`(args)/nargs^2:
> TabMod[SV]:= define(SV, SV() = nargs*sum(args['k'], 'k' = 1..nargs)), eval(SV): eval(TabMod); table([Sr = (proc() evalf(`+`(args)/nargs, 6) end proc ), Ds = (proc() local k; evalf(sqrt(sum((Sr args( ) − args[ ]k )^ ,2 k = 1 .. nargs nargs)/ ), 6) end proc ), Art = ( ) → `*` argsnargs( 2 ) , SV = (proc()description "a Maple procedure automatically generated by define()" ... end proc ) ]) > TabMod[SV](64, 59, 39, 10, 17, 44), TabMod[Sr](64, 59, 39, 10, 17, 44); ⇒ 1398, 38.8333 > TabMod[Ds](64, 59, 39, 10, 17, 44); 0.166667 (6. (Sr 64, 59, 39, 10, 17, 44( ) − 64.)2 + 6. (Sr 64, 59, 39, 10, 17, 44( ) − 59.)2 + 6. (Sr 64, 59, 39, 10, 17, 44( ) − 39.)2 + 6. (Sr 64, 59, 39, 10, 17, 44( ) − 10.)2 (1/2) + 6. (Sr 64, 59, 39, 10, 17, 44( ) − 17.)2 + 6. (Sr 64, 59, 39, 10, 17, 44( ) − 44.)2) > with(TabMod), TabMod[Ds](64, 59, 39, 10, 17, 44); ⇒ [Art, Ds, SV, Sr], 19.8948 > savelibname:= "C:/Program Files/Maple 10/LIB/UserLib": savelib(TabMod); restart; > libname, with(TabMod); "c:/program files/maple 10/lib/userlib", "C:\Program Files\Maple 10/lib", [Art, Ds, SV, Sr] > seq(F(42, 47, 67, 89, 96), F = [Art, SV, Ds, Sr]); restart; , 1705 21.6462 68.2000, ,> seq(F(42, 47, 67, 89, 96), F = [Art, SV, Ds, Sr]); Art(42,47,67,89,96), SV(42,47,67,89,96), Ds(42,47,67,89,96), Sr(42,47,67,89,96) |
Первые три примера фрагмента иллюстрируют поэтапное определение TabMod-таблицы, в которой входами являются имена процедур и выходами – их определения. При этом, следует отметить, т.к. define-определение функции в случае успешного завершения возвращает NULL-значение, то при необходимости включения определенной таким образом функции в таблицу следует использовать конструкцию, представленную модульной SV-функцией фрагмента, т.е. имеющей в общем случае следующий формат:
Id_table[Id_function] := define(Id_f1, Id_f1(...) = F(...)), eval(Id_f1) {;|:}
При этом, идентификатор Id_f1 может совпадать с идентификатором Id_function. Вызов функции eval(TabMod) возвращает содержимое таблицы TabMod, тогда как функции print(TabMod) – содержимое таблицы выводится на печать.
В следующем примере производится вызов погруженных в таблицу процедур SV и Sr на конкретном кортеже фактических аргументов с возвратом соответствующих значений, тогда как аналогичный вызов процедуры Ds возвращает результат невычисленным, если не считать весьма очевидных упрощений, обусловненных, прежде всего, использованием evalf-функции. Объясняется это тем, что в такого типа табличных объектах не производится полного вычисления их входов в том смысле, что при использовании одним из выходов какого-либо входа таблицы либо иного вызова, он рассматривает данный вход неопределенным. Для устранения такой ситуации следует перед вызовами входов таблицы использовать вызов процедуры with.
Так, для инициации в текущем сеансе процедур таблицы TabMod (пример 6) используется вызов with(TabMod); в результате последующий вызов Ds-процедуры получаем вполне определенным. При этом, вызов with(TabMod) возвращает список имен входов таблицы TabMod. Если же пакетный модуль Id находится в библиотечном файле, путь к которому определен в переменной libname пакета, то по вызову with(Id) производится его загрузка его в рабочую область пакета (РОП), обеспечивая доступ ко всем поддерживаемым им функциональным средствам. Тогда как по конструкциям формата:
Id_Модуля[Id_Функции] и Id_Модуля[Id_Функции](Фактические аргументы) можно загружать в РОП только конкретную модульную функцию и вычислять вызов конкретной модульной функции в конкретной точке соответственно, определяемой заданными фактическими аргументами при условии, что содержащий требуемую функцию/процедуру пакетный модуль находится в Maple-библиотеке, логически связанной с главной библиотекой пакета. Однако, и в данном случае требуется выполнение приведенного выше условия – предварительный вызов with-процедуры.
Так, из двух последних примеров фрагмента, иллюстрирующих сказанное, хорошо видно, что после сохранения таблицы TabMod в Maple-библиотеке, логически связанной с главной библиотекой пакета, выполнение вызова with(TabMod) делает полностью доступными все процедуры, определенные в пакетном модуле TabMod. С другой стороны, без вызова with(TabMod) процедуры пакетного модуля остаются неопределенными.
При создании пакетных модулей следует иметь в виду, что модульная таблица, обеспечивающая доступ к функциональным средствам модуля, имеет одно из двух основных представлений (в разрезе вход – выход), а именно:
Id-функции = readlib(`Id-модуля/alias-функции`) и Id-функции = (процедура/функция)
При этом, если в первом случае выход таблицы модуля определяет вызов соответствующего функционального средства, то во втором выход непосредственно определяет функцию, процедуру либо произвольное Maple-выражение.
В первом случае имеет место полезное эквивалентное соотношение вида:
with(Id-модуля)[<Функция>](Args) ≡ readlib(`Id-модуля/alias-функции`)(Args)
для конкретного вызова необходимой модульной функции, определяемой ее алиасом или именем, где Args - передаваемые в точке вызова фактические аргументы. Тогда как во втором случае допустимо использование только with-процедуры. В общем случае вызовы with-процедуры имеют два формата кодирования, а именно:
with(<Module>) и with(<Module>, P1, P2, …)
В первом случае возвращается список экспортируемых пакетным модулем Module имен средств с активацией их в текущем сеансе (загрузка в РОП), тогда как во втором случае возвращается список экспортируемых пакетным модулем Module имен [P1, P2, …] с активацией их в текущем сеансе. В частности, по конструкции op(with(Module, P1)(Args)) возвращается вызов пакетной функции/процедуры на заданных фактических Args-аргументах. Кстати, по вызову процедуры packages() возвращается упорядоченный список имен всех пакетных модулей, хоть один экспорт которых был активирован в текущем сеансе пакета.
Процедура ListPack [103] позволяет получать список пакетных модулей, содержащихся в главной Maple-библиотеке пакета или в библиотеке, подобной главной библиотеке. Процедура обрабатывает все основные ошибочные и особые ситуации. Вызов процедуры ListPack() без фактических аргументов предполагает, что пакетные модули разыскиваются в главной Maple-библиотеке, тогда как вызов процедуры ListPack(F) обеспечивает поиск в Maple-библиотеке, имя которой или полный путь к ней определены фактическим аргументом F. Имеются и другие полезные приложения процедуры. В частности, она позволяет получать более точную классификацию пакетных модулей, чем по вызову ?index, package для Maple 8. Так классифицируемый по такому вызову пакетный модуль Rif на самом деле таким не является, что и констатирует процедура. Следующий фрагмент представляет исходный текст процедуры и примеры ее применения.
ListPack := proc() local a b c d g h f k n m s v w t tst gs qt p, , , , , , , , , , , , , , , , , ; global _modpack; if 0 < nargs and type(args 1[ ], 'mlib') then f := cat "",( args 1[ ], "/maple.hdb" ;) if not belong(CF(args[1]), map(CF, [libname])) then assign67(p = 8, f = cat "",( args 1[ ], "/maple.hdb"), 'libname' = libname, args 1[ ]) end if; if type ,(f 'file') then assign(d = { }, n = 120000, s = { }, v = { }) else ERROR("Maple library <%1> does not contain help database"args[1], ) end if else type sin, '( libobj'), assign(d = { }, f = cat(_libobj, "/maple.hdb"), n = 120000, s = { }, v = { }) end if; tst := proc( )x try parse( )x ; eval(%); parse( )x catch : NULL end try end proc; gs := proc(x::{set, list}) local a f, ; assign(f = cat([libname][ ]1 [1 .. 2], "\__$Art16_Kr9$__")), assign(a = cat "_000:=proc(x::{list,set}) local a,b,c,k; global _modpack\;( assign(c = interface(warnlevel), '_modpack' = {}),null(interfac\e (warnlevel = 0)); for k in x do try b:= with(k); if type(b, 'list') th\ n _modpack:= {op(_modpack), k} end if catch : NULL end try\ end do; _modpack,null(interface(warnlevel = c)) end proc: _000\ (" convert( ,, x 'string'), "):")); writeline ,(f a), close( )f ; read f; fremove( )f , _modpack, unassign '( _000', '_modpack'), `if`(p = 8, assign('libname' = op [( libname][1 .. -2])), NULL) end proc; qt := x → `if`(x = { }, NULL x, ); assign(m = filepos(f, ∞)), close(f), assign(b = open ,(f 'READ'), h = {"with("}, w = { }); while filepos( )b < m do assign ' '( a = convert( subs {( 0 = NULL, 13 = NULL, 10 = NULL}, readbytes(b n, )), 'bytes')), assign('c' = Search2(a, h)); if c ≠ [ ] then for k in c do g := Search2(a[k .. k + 35], {"):" ")" ");", , }); if g ≠ [ ] then d := {op(d), FNS(a[k + 5 .. k + g[ ]1 − 2], " " 3, )} end if |
end do end if end do; seq `if`( (search(k, "," ' ', t ) or search(k, ":-" ' ', t ), assign(' 'v = {op( )v , cat(``, k[1 .. t − 1])}), `if` search( ,( k "[" ' ', t ), assign('v' = {op(v), cat(``, k[1 .. t − 1])}, 'w' = {k, op(w)}), assign(' 'v = {op( )v , cat(`` k, )}))), k = d); assign(' 'v = {seq(`if`(type(k, 'package'), ,k NULL), k = v)}, ' 'w = map(tst w, )), qt v( ), `if`(w = { }, NULL, qt(gs w( ))) end proc > restart; ListPack(); # Maple 8 {finance, Slode, PolynomialTools, tensor, plots, simplex, DEtools, group, student, polytools, Units, numapprox, geom3d, codegen, stats, diffalg, RealDomain, algcurves, numtheory, ScientificConstants, geometry, ListTools, combinat, Maplets, plottools, LinearOperators, PDEtools, inttrans, ExternalCalling, Ore_algebra, RandomTools, CodeGeneration, LargeExpressions, Groebner, VariationalCalculus, process, difforms, LibraryTools, CurveFitting, orthopoly, RationalNormalForms, linalg, powseries, LinearFunctionalSystems, LinearAlgebra, VectorCalculus, sumtools, genfunc, queue, GaussInt, Matlab, TypeTools, OrthogonalSeries, StringTools, Student, RootFinding, Spread, Sockets, Domains, liesymm, networks, SoftwareMetrics, padic, SolveTools, MatrixPolynomialAlgebra, XMLTools, SNAP, LREtools, priqueue, Worksheet, context, combstruct, MathML, SumTools}, {Elements, Tools, Examples, Standard, Converter, Calculus1, Natural, Hypergeometric, stats[fit], stats[anova], stats[describe], stats[statplots]} > ListPack("C:\Program Files\Maple 8\Lib\UserLib"); { SoLists, DIRAX, SimpleStat, ACC, AlgLists} |
Механизм with-процедуры, в частности, состоит в том, что ее вызов непосредственно влечет за собой вычисление (всех или заданных) выходов соответствующей модульной таблицы, в качестве которых могут выступать любые допустимые Maple-выражения, включая вызовы функций/процелур, как это иллюстрирует следующий простой пример: