Смекни!
smekni.com

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

Загрузка сохраненного по save-предложению файла данных выполняется по предложению read, которое имеет следующие простые форматы кодирования: read <Файл> или read(<Файл>)

где Файл – имя файла или полный путь к нему типа {string, symbol}; при этом, если файл указывается только именем, а не полным путем к нему, то предполагается, что он находится в текущем каталоге. Между тем, результат save-предложения зависит от формата загружаемого файла. Общим является тот факт, что после загрузки файла содержащиеся в нем определения становятся доступными в текущем сеансе, если впоследствии не определяется противного. Между тем, если загружается файл входного Maple-формата, то в случае завершения read-предложения (;)-разделителем на монитор выводится содержимое файла, а вызов read-предложения возвращает значение последнего его предложения. Тогда как по (:)-разделителю информации не выводится, но также возвращается значение последнего предложения загруженного файла. В случае загрузки m-файла информации не выводится и возвращается NULL-значение. Примеры следующего фрагмента иллюстрируют применение read-предложения для загрузки файлов данных обоих форматов (входного и внутреннего):

> restart; read("C:/Temp/Sr"); 5*Sr(64, 59, 39, 10, 17); ⇒ 189

`+`(args)

Sr := ( ) →

nargs

> restart; read("C:/Temp/Sr"): 5*Sr(64, 59, 39, 10, 17); ⇒ 189

> restart; read("C:/Temp/Sr.m"); 5*Sr(64, 59, 39, 10, 17); ⇒ 189

> restart; read("C:/Temp/Sr.m"): 5*Sr(64, 59, 39, 10, 17); ⇒ 189

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

В Maple 6 save-предложение допускает формат save(F), по которому пишет все вычисленные в текущем сеансе имена в файл F как последовательность предложений присвоения. Кроме того, данная возможность предоставляется только для F-файлов данных, чьи имена завершаются ".m", т.е. файлы внутреннего Maple-формата. Однако, начиная с Maple 7, такая возможность отсутствует. Между тем, в ряде случаев подобное средство может упростить программирование и облегчить работу с Maple. В этом плане может оказаться достаточно полезной наша процедура saveall [41-43,103,108,109].

saveall := proc(F::{string, symbol }) local _avz_agn_asv_ a k j t, , , , , ψ, , ;p f

_avz_agn_asv_ := ((

({anames( )} minus {anames '( environment')}) minus {anames '( builtin')}

) minus {anames '( package')}) minus {'`type/interfaceargs`', 'lasterror',

'lastexception', '`Context/InitProcs`', 'ContextKey', '`context/InitProcs`', 'ContextData', 'stack', 'interface'};

_avz_agn_asv_ := {seq( `if`(cat "",( k)[1 .. 3] = "CM:" or type( ,k 'libobj'), NULL k, ), k = _avz_agn_asv_ )}; assign(a = interface(warnlevel), p = packages( )), null interface(( warnlevel = 0)),

assign(ψ = (a → convert(eval(a), 'string')));

_avz_agn_asv_ := {seq(`if`(

Search2(ψ( )k , {"the University of Waterloo" "Waterloo Maple Inc", }) ≠ [ ]

, NULL, k), k = _avz_agn_asv_ )};

_avz_agn_asv_ := {seq `if` search(( ( cat "",( k), "/" ' ', t ), `if`(type(cat(``, cat "",( k)[1 .. t − 1]), 'libobj'), NULL k, ), k), k = _avz_agn_asv_ )};

null interface(( warnlevel = a)); if p ≠ [ ] then for j in p do for k in _avz_agn_asv_ do if type(cat ,(j "/", k), 'libobj') then

_avz_agn_asv_ := subs(k = NULL _avz_agn_asv_, )

end if

end do

end do

end if;

if _avz_agn_asv_ = { } then WARNING(

"current session does not contain user definite objects suitable for saving") else _avz_agn_asv_ := op(_avz_agn_asv_ ); f := pathtf(F); (proc(_avz_agn_asv_ ) save args, f end proc )(_avz_agn_asv_ ), f end if

end proc

> saveall("c:&bsol;temp&bsol;aaa&bsol;bbb&bsol;file");

Warning, current session does not contain user definite objects suitable for saving

> saveall("c:&bsol;temp&bsol;grodno&bsol;bbb&bsol;ccc&bsol;save169.m");

"c:&bsol;temp&bsol;grodno&bsol;bbb&bsol;ccc&bsol;save169.m"

Вызов процедуры saveall(F) возвращает реальный путь к принимающему файлу данных

(имя которого либо путь к нему определены фактическим аргументом F), содержащему все вычисленные в текущем сеансе имена в виде последовательности предложений присвоения. При этом, процедура не сохраняет встроенные средства, переменные среды пакета, пакетные модули, библиотечные средства в рамках всех библиотек, определенных предопределенной libname-переменной Maple. При отсутствии сохраненных имен вызов процедуры возвращает NULL-значение, т. е. ничего, с выводом соответствующего сообщения, как это иллюстрирует предыдущий фрагмент. В целом ряде случаев saveallпроцедура имеет достаточно полезные приложения.

Еще на одном весьма существенном аспекте следует заострить внимание. Предложение save некорректно сохраняет программные модули, например:

> restart; M:= module () export x; x:= () -> `*`(args)/nargs end module: M1:= module () export y; y:= () -> `+`(args)/nargs end module: M2:= module () export z; z:= () -> `+`(args) end module: save(M, M1, M2, "C:/temp/M.m"); restart; read("C:/temp/M.m"); > map(type, [M, M1, M2], `module`), with(M), with(M1), with(M2);

[true, true, true], [x], [y], [z]

> M:- x(64, 59, 39, 17, 10, 44), x(64, 59, 39, 17, 10, 44);

x(64, 59, 39, 17, 10, 44), x(64, 59, 39, 17, 10, 44)

> M1:- y(64, 59, 39, 17, 10, 44), y(64, 59, 39, 17, 10, 44);

y(64, 59, 39, 17, 10, 44), y(64, 59, 39, 17, 10, 44)

> M2:- z64, 59, 39, 17, 10, 44), z(64, 59, 39, 17, 10, 44); z(64, 59, 39, 17, 10, 44), z(64, 59, 39, 17, 10, 44)

Из приведенного фрагмента видно, что сохраненные по save-предложению в m-файле модули M, M1 и M2, затем читаются read-предложением в текущий сеанс и распознаются type-функцией действительно как модули. Более того, вызов with-процедуры вполне корректно возвращает списки экспортируемых модулями переменных. Тогда как стандартные вызовы этих переменных возвращаются невычисленными, т.е. экспортируемые такими модулями переменные оказываются неопределенными. Причина лежит в том, что save-предложение не сохраняет в m-файлах внутреннего Maple-формата тела программных модулей.

Весьма детальное обсуждение данного вопроса может быть найдено в наших книгах [29-33,39,42-44,103]. Для устранения подобного недостатка нами был предложен ряд интересных средств, существенно расширяющих функциональные возможности стандартных предложений save и read, с которыми можно ознакомиться в нашей книге [103] и в прилагаемой к ней Библиотеке. В частности, предложение save не позволяет сохранять в файле динамически вычисляемые имена, что в целом ряде случаев представляется существенным недостатком. Наша процедура save1 [103] устраняет данный недостаток.

Вызов процедуры save1(N, E, F) пишет указанные переменные, определенные фактическим аргументом N, в файл, указанный фактическим аргументом F, как последовательность предложений присвоения. Если некоторому элементу n из N не присваивалось значения, то в файл записывается предложение присвоения n := n с выводом соответствующего сообщения. Если некоторый элемент n из N защищен (имеет protected-атрибут), то элемент игнорируется с выводом соответствующего сообщения. Более того, если все элементы из N защищены, то инициируется ошибочная ситуация. Успешный вызов процедуры save1 возвращает полный путь к файлу данных F, обеспечивающему присвоения выражений E соответствующим символам из N в текущем сеансе Maple с выводом необходимых сообщений.

Данная процедура существенно расширяет возможности предложения save, обеспечивая сохранение в файлах данных и входного формата Maple, и внутреннего Maple формата присвоений переменным с динамически генерируемыми именами. В целом ряде задач это – весьма важная возможность. Более того, процедура поддерживает сохранение Maple-объектов в файлах данных с произвольными путями к ним. Примеры фрагмента, представленного ниже, иллюстрируют некоторые из наиболее типичных применений save1-процедуры.

save1 := proc(N::{symbol, list(symbol )}, E::anything, F::{string, symbol }) local a b c k, , , , ν ω ζ ψ, , , , , , ;r s x assign(b = (x → null interface(( warnlevel = x))), ζ = "_$Euro$_", ν = "save(", s = "symbols %1 are protected");

if not type(eval(F), {'string', 'symbol'}) then ERROR("argument <%1> can't specify a datafile", F) elif not type( ,F 'file') then c := interface(warnlevel); b(0); r := CF1 MkDir( ,( F 1)); b c( )

else r := CF1(F)

end if; ψ := proc(f) local a k p h, , , ;

`if`(f[-2 .. -1] = ".m" RETURN( ), , assign(p = fopen ,(f 'READ', 'TEXT'), a = "_$$$_" );) while not Fend(p) do h := readline(p);

writeline(a, `if`(h[-1] ≠ ";", h, cat(h[1 .. -2], ":")))

end do;

null(close ,(f a), writebytes ,(f readbytes(a, ∞)), close( )f , fremove(a))

end proc ; ω := proc(N::{symbol, list(symbol )}, E::anything, F::{string, symbol }) local k;

`if` type(( N, 'symbol'), assign(' 'ν = cat(ν, N, ",")), seq(assign(' 'ν = cat(ν, N k[ ], ",")), k = 1 .. nops(N))), writeline(ζ, cat(ν, """, ,r """ "):", )), close(ζ); if type(N, 'symbol') then assign(N = eval(E)) elif type(E, 'list') then for k to min(nops(N), nops(E)) do assign(N k[ ] = eval(E k[ ]))

end do

else assign(N[1] = eval(E))

end if;

(proc( )ζ read ζ; fremove(ζ) end proc )(ζ) end proc ;

if type(N, 'symbol') and type(N, 'protected') then ERROR "symbol <%1> is protected",( N) elif type(N, 'list') then assign(a = [ ]); for k to nops(N) do `if`(type(N k[ ], 'protected'), NULL, assign(' 'a = [op(a), N k[ ]])) end do;

`if`(a = [ ], ERROR("all symbols %1 are protected", N), op([ ω(a, args 2[ ], r), ψ( )r , `if`(nops(a) = nops(N), NULL,

WARNING(s, {op(N)} minus {op(a)}))]))

else ω(args 1 .. 2[ ], r), ψ( )r

end if; r, WARNING("the saving result is in datafile <%1>", r)

end proc

> save1([G, cat(x, y, z), cat(a, b, c), cat(h, t), convert("RANS", 'symbol'), cat(S, v)], [59, 64, 39, 43, 10, 17], "C:&bsol;Academy/RANS&bsol;IAN.m"); G, xyz, abc, ht, RANS, Sv; Warning, the saving result is in datafile <c:/academy/rans/ian.m>

"c:/academy/rans/ian.m", 59, 64, 39, 43, 10, 17

> restart; read("C:&bsol;Academy/RANS&bsol;IAN.m"); G, xyz, abc, ht, RANS, Sv;

59, 64, 39, 43, 10, 17

> save1([cat(x, y, z), cat(y, z), cat(z, 6)], [proc() `+`(args)/nargs end proc,59,39], "C:&bsol;TEMP"); Warning, the saving result is in datafile <c:/_temp>

"c:/_temp"

> restart; read("C:&bsol;_Temp"); 2*xyz(1, 2, 3, 4, 5, 6), yz, z6; ⇒ 7, 59, 39

Приведем еще пару процедур, расширяющих предложения save и read по работе с программными модулями пакета. Обе процедуры savem1 и readm1 имеют форматы кодирования следующего вида: