MkDir4 := proc(F::{string, symbol}) local a b c f g, , , , ; assign(f = Path(F), g = ":/_avzagnvsv424767ArtKr1710_" ;) try return MkDir(op subs(( "A:" = NULL, [args]))) catch "permission denied" := : a sort [( Adrive( )]) catch "file or directory does not exist": a := sort([Adrive( )]) catch "file I/O error": a := sort [( Adrive( )]) end try ; assign(c = cat [(f 2 .. -1]), ' 'a = `if`(member "A:", {( args}), ,a {op(a)} minus {"A"} );) for b in a do if adftest cat( ,( b g)) then return MkDir(cat(b c, ), `if`(1 < nops({args} minus {"A:"}), 1, NULL)) end if end do; error `if`(member("A:", {args}), "accessible disk drives do not exist", "accessible disk drives excluding <A> do not exist)" end proc > MkDir4("D:/Work\Grodno/Vilnius\Tallinn.2006",10); "f:\work\grodno\vilnius\tallinn.2006" > MkDir4("C:/Grodno/Grsu/Maple.avz","A:",10); Error, in (MkDir4) accessible disk drives do not exist |
Наряду с представленными выше нами создан ряд других процедур общего назначения для работы с файловой системой компьютера. В частности, нами введены три новых типа выражений, а именно: dir, file и path, определяющие соответственно каталог, файл и полный путь. Так, представленная ниже процедура `type/dir` служит для тестирования выражения на предмет быть каталогом. Вызов type(F, 'dir') возвращает true-значение, если аргумент F определяет каталог, и false-значение в противном случае.
type/dir := proc(F::anything) local a b c d k u, , , , , , ω, ,t ν, ,h p n, ; `if`(type(eval(F), {name string symbol, , }), NULL, RETURN(false)), assign(h = currentdir( )); ω, u := ( ) → ERROR("<%1> is invalid path to a directory or a file", F), interface(warnlevel); `if`(Red_n(cat " ",( F), " " 2, ) = " " or member( ,F {``, ""}), ω( ), NULL), null interface(( warnlevel = 0)); assign(a = Red_n(Subs_All("/" = "\" Case(, cat "",( F)), 1), "\" 2 ,, ) ν = (( ) → null(interface(warnlevel = u)))); |
if length(a) = 1 then assign('a' = cat(a, ":\")) elif length(a) = 2 and a[2] = ":" then assign(' 'a = cat(a, "\")) elif length(a) = 3 and a[2 .. 3] = ":\" or a[2 .. 3] = ":/" then NULL end if; `if`(a[2] = ":" `if` member(, ( a[1], map(Case, {Adrive( )})), NULL, RETURN(ν( ), false)), NULL); if length(a) < 4 then try p := currentdir(a) catch "directory exists and is not empty": NULL catch "file or directory does not exist": NULL catch "file or directory, %1, does not exist": NULL catch "permission denied": currentdir(h); RETURN(ν( ), true) catch "file I/O error": currentdir(h); RETURN(ν( ), true) end try ; `if`(p = NULL or p = h, RETURN(ν( ), null currentdir(( h)), true), NULL) end if; `if`(a[-1] = "\" assign(, ' 'a = a[1 .. -2]), NULL); if a[2 .. 3] ≠ ":\"then assign(b = iostatus( ), d = CF currentdir( )( ), n = cat "\",( a), c = map(CF, [libname])); `if`(search(d, n) or {op(map(search, c, n))} ≠ {false}, [ν( ), RETURN(true)], 158); `if`(nops(b) = 3 1, , seq `if` search( ( (CF(b k[ ][2]), cat("\", a, "\")), [ν( ), RETURN(true)], NULL), k = 4 .. nops(b))) end if; `if`(type(holdof(hold), set(integer)), NULL, assign(t = 7)); try close fopen( ,( a READ)) catch "file or directory does not exist": `if`(t = 7, holdof(restore, 7), NULL), ν( ), RETURN(ν( ), false) catch "file or directory, %1, does not exist": `if`(t = 7, holdof(restore, 7), NULL), ν( ), RETURN(ν( ), false) catch "file I/O error": `if`(t = 7, holdof(restore, 7), NULL), ν( ), RETURN(true) catch "permission denied": `if`(t = 7, holdof(restore, 7), NULL), ν( ), RETURN(true) end try ; `if`(t = 7, holdof(restore, 7), NULL), ν( ), false end proc > type( "C:/Temp", 'dir'), type( "C:/", 'dir'), type( "C:/Program files/Maple 10/lib", 'dir'); true, true, true |
При этом, следует иметь в виду, что возврат false-значения говорит лишь о том, что тестируемый каталог F (точнее последний элемент F-цепочки) отсутствует в: (1) цепочке, определенной F, (2) цепочках, определенных предопределенной переменной libname, (3) цепочке, определенной вызовом currentdir() и (4) цепочках, определенных открытыми файлами данных текущего сеанса. Тогда как, вообще говоря, данный каталог F может быть элементом файловой системы компьютера. Детальнее с представленными средствами работы с файловой системой компьютера можно ознакомиться в [41,103,108,109].
Предложения Maple-языка сохраняются во внутренних файлах пакета в одном из двух форматов (входном Maple-формате и внутреннем m-формате; оба являются ASCII-файлами) на основе save-предложения одного из следующих двух форматов:
save {Id1, Id2, ..., Idn,} <СФ> или save({Id1, Id2, ..., Idn,}<СФ>)
По формату save <СФ> в указанный спецификатором (СФ) файл помещаются все определенные идентификаторы текущего сеанса, т.е. идентификаторы, которым производились присвоения по (:=)-оператору или assign-процедуре. Однако следует иметь в виду, что корректное сохранение по данному формату save производится только для случая принимающего файла внутреннего формата, т.е. m-файла (имя файла завершается символами «.m»). Иначе идентифицируется ошибочная ситуация. При этом, это относится ко всем Maple-документам, открытым в текущем сеансе, т. е. в m-файле сохраняется состояние текущего сеанса. Между тем, данный формат допустим только для Maple 6 и для релизов 7 и выше он отсутствует.
Тогда как по формату save Id1, ..., Idn, <СФ> в указанный СФ-спецификатором файл выгружаются только те определения идентификаторов, чьи имена закодированы в последовательности перед СФ-аргументом. При этом, если в СФ определено m-расширение имени, то файл сохраняется во внутреннем m-формате, в противном случае используется входной формат Maple-языка (в этом формате производится ввод информации в Mapleдокумент с консоли). В случае указания в save неопределенных Id-идентификаторов, они сохраняются в виде Id:='Id' с выводом соответствующих предупреждающих сообщений. Успешное завершение save-предложения возвращает NULL-значение. Следующий простой фрагмент иллюстрирует использование save-предложения для создания файлов обоих указанных форматов:
> A:= 64: B:= [64,59,39,44,10,17]: P:= () -> `+`(args)/nargs: M:= module () export sr; sr:= () -> `+`(args)/nargs end module: S:= 2006: > save(A, B, P, M, S, "C:/Temp/Tallinn"); save(A, B, P, M, S, "C:/Temp/Tallinn.m"); > restart; read("C:/Temp/tallinn"): %; ⇒ 2006 > A, B, 6*P(64,59,39,44,10,17), 6*M:- sr(1,2,3,4,5,6); ⇒ 64, [64, 59, 39, 44, 10, 17], 233, 21 > restart; read "C:/Temp/tallinn.m"; %; ⇒ 10 (A) > A, B, 6*P(64,59,39,44,10,17), 6*M:- sr(1,2,3,4,5,6); ⇒ [64,59,39,44,10,17], 233, 6 sr(1,2,3,4,5,6) |
В данном фрагменте определяются переменные и по save-предложению сохраняются в Tallinn-файлах в форматах входного Maple-языка и внутреннем. На небольшого объема файлах не ощущается преимущества от того или иного формата, однако при возрастании объема предпочтение внутреннего m-формата становится все ощутимее, позволяя создавать более компактные файлы и быстрее их загружать в память.
Загрузка сохраненного по save файла производится по предложению read форматов: read <СФ> или read(<СФ>)
но результат его выполнения зависит от формата загружаемого файла. Общим является тот факт, что после загрузки файла содержащиеся в нем определения становятся доступными в текущем сеансе, если впоследствии не определяется противного. Однако, если загружается файл входного формата Maple-языка, то в случае завершения предложения read (;)-разделителем на дисплей выводится содержимое файла, а результат выполнения read-предложения возвращает значение последнего предложения файла. Тогда как по (:)-разделителю информации не выводится, но также возвращается значение последнего предложения загруженного файла. В случае же загрузки m-файла информации не выводится и возвращается NULL-значение. Пример (А) предыдущего фрагмента иллюстрирует применение read-предложения для загрузки m-файла. Однако, в этом месте может возникнуть недопонимание в связи с возвратом %-вызовом значения 10. А дело здесь обстоит следующим образом. Как известно, такой вызов возвращает значение выполнения предыдущего ему предложения. Но так как перед read мы выполнили restart, а вызов read возвратил NULL-значение (т.е. ничего), то %-вызов после restart либо после загрузки пакета в зависимости от релиза и его клона возвращает следующие значения, а именно: результат вызова последней процедуры, определенной в инициализационном файле «Maple.ini» (Maple 6/7 и Maple 9-10 standard-клона), 10 (Maple 8 и Maple 9/ 9.5 standard-клона) и -1 (Maple 10 standard-клона).
На первых порах работы с пакетом средства доступа к внутренним m-файлам наиболее полезны при необходимости создания различного рода библиотек пользовательских функций и/или процедур, а также часто используемых Maple-конструкций. Однако, здесь имеется одна весьма существенная проблема, а именно. Программные модули в такого типа файлах сохраняются некорректно (точнее, не сохраняются их тела), как это хорошо иллюстрирует последний пример предыдущего фрагмента. Поэтому нами был создан ряд процедур как обобщающих, так и расширяющих стандартные предложения save и read относительно работы с файлами внутреннего Maple-формата [41,103,108,109]. Так, в частности, пара нижеследующих процедур Save2 и Read1 обеспечивает корректное сохранение всех типов Maple-объектов в файлах внутреннего m-формата с последующим чтением в текущий сеанс. Их исходные тексты и примеры приводятся ниже.