Смекни!
smekni.com

Программирование и разработка приложений в Maple (стр. 125 из 135)

Вышеприведенный фрагмент содержит исходный текст и примеры применения процедуры simplel. Представленная процедура может оказаться полезным средством при организации простых библиотек пользователя, несущих и архивные черты программных средств. Данная процедура может быть расширена новыми функциональными возможностями, которые оставляем читателю в качестве достаточно полезного упражнения. С более общими средствами поддержки ведения простых библиотек пользователя, отличных от Maple-библиотек, можно познакомиться в наших книгах [13,14,41-43,103,108] и в прилагаемых к ним библиотеках.

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

'parse("module <Имя> () export ... end module")'

где Имя определяет имя программного модуля. После этого созданная таким образом таблица сохраняется посредством save-предложения в файле любого допустимого формата (внутреннем либо входном). Последующие загрузки данного файла по read-предложению активируют в текущем сеансе сохраненные в нем программные средства, доступ к которым аналогичен доступу к средствам пакетного модуля. При этом, если обращение к процедуре обеспечивается стандартным для таблиц способом, т.е. по конструкции следующего формата кодирования

<Имя таблицы>[<Имя процедуры>](…)

то к программному модулю по конструкции формата

<Имя модуля> :- <Имя экспорта>](…)

только после вызова процедуры with(<Имя таблицы>). Нижеследующий весьма простой фрагмент хорошо иллюстрирует вышесказанное.

> T:= table([P = (() -> `+`(args)/nargs), M = 'parse("module M () export Sr;

Sr:= () -> `+`(args)/nargs end module")', P1 = proc() `*`(args)/`+`(args) end proc, M1 = 'parse("module M1 () export X; X:= () -> `*`(args)/nargs end module")']); # Maple 8

T := table([P1 = (proc() `*` args `+`(args)( )/ end proc ), P = ( ) → `+`nargs(args) ,

M1 = parse "module M1 () export X; X:= () -> `*`(args)/nargs end module",( ) M = parse("module M () export Sr;

Sr:= () -> `+`(args)/nargs end module")

])

> save(T, "C:/Temp/library.m"); save(T, "C:/Temp/library"); > restart; read "C:/Temp/library.m"; with(T); ⇒ [M, M1, P, P1]

> 3*T[P](64, 59, 39, 10, 17, 43), 29*T[P1](64, 59, 39, 10, 17, 43), 3*M:- Sr(64, 59, 39, 10, 17, 43), M1:- X(64, 59, 39, 10, 17, 43); ⇒ 116, 134562480, 116, 179416640

> restart; read "C:/Temp/library"; with(T); ⇒ [M, M1, P, P1]

> 3*T[P](64, 59, 39, 10, 17, 43), 29*T[P1](64, 59, 39, 10, 17, 43), 3*M:- Sr(64, 59, 39, 10, 17, 43), M1:- X(64, 59, 39, 10, 17, 43); ⇒ 116, 134562480, 116, 179416640

При этом, в релизах Maple, начиная с 9-го, вызов процедуры with на таблицах вышеописанной организации вызывает ошибочную диагностику (приведенную ниже) на первом же модуле, погруженном в таблицу, однако все последующие вычисления выполняются корректно. Поэтому, при необходимости, такие ошибочные ситуации легко обрабатываются программно посредством try-предложения.

> restart; read "C:/Temp/library.m";

> with(T);

Error, (in M) attempting to assign to `M` which is protected

> 3*T[P](64, 59, 39, 10, 17, 43), 29*T[P1](64, 59, 39, 10, 17, 43), 3*M:- Sr(64, 59, 39, 10, 17, 43), M1:- X(64, 59, 39, 10, 17, 43); ⇒ 116, 134562480, 116, 179416640

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

SoftTab := proc(T::symbol, F::{symbol, string}, R::symbol) local a b s k, , , ; b := ( ) → ERROR(

"procedure call does not contain procedures and/or modules for saving - %1, [args 3 .. -1[ ]]); if 2 < nargs then for k from 3 to nargs do

if type(args[ ]k , 'procedure') then assign(' 'T[args[ ]k ] = eval args[ ]( k )) elif type(args[ ]k , `module`) then s := convert(eval args[ ]( k ), 'string');

assign('T'[args[k]] = parse( cat "'parse(", """,( cat(s[1 .. 7], args[ ]k , s[7 .. -1]), """ ")'" )), )

else a := 17

end if

end do;

if a ≠ 17 then save T, F else b(args) end if else b(args) end if

end proc

> Proc:= () -> `*`(args)/nargs: Mod:= module () export Sr; Sr:= () -> `+`(args)/nargs end module: Proc1:= () -> `+`(args): Mod1:= module () export avz; avz:= () -> `+`(args)^2 end module: SoftTab(Tab, "C:/Temp/library", Proc, Mod, Proc1, Mod1);

> SoftTab(Tab, "C:/Temp/library.m", Proc, Mod, Proc1, Mod1);

> restart; read "C:/Temp/library": with(Tab); ⇒ [Mod, Mod1, Proc, Proc1]

> Tab[Proc](64,59,39,10,17,43), 3*Mod:- Sr(64,59,39,10,17,43), Tab[Proc1](64,59,39,10,17,43),

Mod1:- avz(64, 59, 39, 10, 17, 43); ⇒ 179416640, 116, 232, 53824

> restart; read "C:/Temp/library.m"; with(Tab); ⇒ [Mod, Mod1, Proc, Proc1]

> Tab[Proc](64,59,39,10,17,43), 3*Mod:- Sr(64,59,39,10,17,43), Tab[Proc1](64,59,39,10,17,43),

Mod1:- avz(64, 59, 39, 10, 17, 43); ⇒ 179416640, 116, 232, 53824

> read "C:/Temp/library.m"; with(Tab); ⇒ 179416640, 116, 232, 53824

Warning, the protected names Mod and Mod1 have been redefined and unprotected

> Tab[Proc](64,59,39,10,17,43), 3*Mod:- Sr(64,59,39,10,17,43), Tab[Proc1](64,59,39,10,17,43), Mod1:- avz(64, 59, 39, 10, 17, 43); ⇒ 179416640, 116, 232, 53824

> SoftTab(Tab, "C:/Temp/library", A, V, Z);

Error, (in b) procedure call does not contain procedures and/or modules for saving - [A,V,Z]

> SoftTab(Tab, "C:/Temp/library");

Error, (in b) procedure call does not contain procedures and/or modules for saving - []

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

Процедура SoftTab(T,F,R) имеет не менее трех аргументов, из которых первый аргумент имеет symbol-тип и определяет имя сохраняемой таблицы T, тогда как второй определяет принимающий файл F, имеющий входной Maple-формат или внутренний Maple-формат. Вызов процедуры SoftTab(T, F, X, Y, Z, …) возвращает NULL-значение, обеспечивая сохранение в файле F таблицы T, содержащей определения процедур и/или модулей, имена которых определены фактическими аргументами, начиная с третьего. Таблица T в качестве входов имеет имена сохраненных процедур и модулей, тогда как выходы – их определения. При этом, если определения процедур представляются в T-таблице непосредственно, то определения модулей представляются в специальном формате, который обеспечивает последующее корректное их использование. Вызов процедуры с двумя аргументами либо с аргументами X, Y, Z, …, чей тип отличен от {procedure, `module`} вызывает ошибочную ситуацию с возвратом соответствующей диагностики.

Файл F, созданный вызовом процедуры SoftTab(T,F, X, Y, Z,…), читается read-предложением, активируя в текущем сеансе сохраненные в нем объекты X,Y,Z,…. При этом, обращения к данным объектам производятся принятыми в Maple способами, а именно:

1) к процедурам по конструкции T[<Имя>](...)

2) к программным модулям по конструкции <Имя>:- <Экспорт>(...) после вызова with(T) Еще на одном моменте следует акцентировать внимание. Сохранение T-таблицы следует выполнять отдельно для каждого нового F-файла, разделяя их restart-предложениями во избежание возникновения ошибочных ситуаций с диагностикой следующего вида “Error, (in assign/internal) invalid left hand side in assignment”. Представленные в предыдущем фрагменте примеры весьма наглядно иллюстрируют сказанное. В качестве весьма полезного упражнения читателю рекомендуется рассмотреть организацию SoftTabпроцедуры и расширить ее возможностью сохранять файл с таблицей по произвольному адресу подобно тому, как это реализовано в предыдущей процедуре simplel. Такая возможность весьма существенна при программировании задач, имеющих дело с доступом к файлам данных различных типа и организации.

С рядом других средств ведения простых библиотек пользователя (т.н. первый уровень), организационно отличных от Maple-библиотек пакета, можно познакомиться в книгах [8-14,41,42,45, 46,103]. В них достаточно детально описана сущность алгоритмов, реализованных средствами, которые оказываются достаточно полезными при работе с библиотеками пользователя нестандартной организации, а также с файлами, содержащими определения Maple-объектов, прежде всего процедур и программных модулей.

Ко второму уровню средств работы с библиотеками пользователя можно отнести набор наших процедур, обеспечивающих создание, обновление, просмотр библиотек, подобных Maple-библиотеке пакета, основной из которых является процедура User_pflMH, наряду с перечисленными обеспечивающая три режима создания справочной базы библиотек. Данную процедуру можно рассматривать в качестве наиболее общего и универсального инструмента создания пользовательских библиотек, структурно подобных главной библиотеке пакета, которые логически связаны с ней. В общем, процедура выполняет следующие основные операции [41,103,109]:

* регистрация в системном файле "Win.ini" текущего релиза пакета, если ранее этого не было сделано;

* создание либо обновление инициализационного файла "Maple.ini" с целью обеспечения логической связи создаваемой библиотеки пользователя с главной Maple-библиотекой

(при этом, последняя операция обеспечивает возможность создания справочной базы библиотеки согласно пользовательскому предложению).

Процедура выводит соответствующие сообщения о проделываемой работе. Таким образом, при создании или обновлении библиотеки пользователь должен определить только ее имя (если библиотека будет расположена в каталоге LIB пакета) либо полный путь к ней, наряду с множеством или списком имен Maple-объектов, сохраняемых в библиотеке, и чьи определения были вычислены в текущем сеансе. Дополнительно, пользователь может определить размер для вновь создаваемой библиотеки, ее справочную базу данных и режим логической связи библиотеки с главной библиотекой пакета. Ряд других процедур [41,103,109] обеспечивают наиболее массовые операции с Maple-подобными библиотеками, включая средства восстановления поврежденных библиотек, обновления библиотек и их справочных баз, отмены/восстановления логической связи с главной библиотекой пакета, эффективной упаковки, конвертации библиотек первого уровня организации во второй. В этом смысле они в определенном отношении поддерживают продвинутые функциональные возможности автоматизации работы с библиотеками подобно случаю известной утилиты sed операционной системы UNIX (Linux).