Смекни!
smekni.com

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

Вторым средством, обеспечивающим временной контроль вычислений, служит встроенная функция timelimit(t, V). Если время в сек., затребованное процессором для вычисления V-выражения, не превысило значения, определенного первым фактическим t-аргументом, то возвращается результат вычисления V-выражения. В противном случае генерируется ошибочная ситуация с диагностикой "Error, (in V) time expired", обрабатываемая рассмотренной выше traperror-функцией или try-предложением, рассматриваемым ниже. Однако функция timelimit не используется с функциями машинной арифметики, т.к. не обрабатывает ситуацию исчерпания отведенного временного интервала для вычислений, например:

> S:= proc(n) local k; for k to n do sin(10.3*n) end do end proc: S(10^5), evalhf(S(10^5)), timelimit(3, evalhf(S(10^7)));

-0.5431520991, -0.543152099236042907, 0.764330635010303183

> timelimit(3, S(10^7));

Error, (in sin) time expired

Из фрагмента легко заметить, что на evalhf-функции машинной арифметики timelimitфункция не приводит к желаемому результату, не ограничивая времени вычисления.

Timetest := proc(t::{float, integer}, x::anything, V::symbol, p::evaln) local h z, ; z := time( ); if traperror timelimit( ,( t assign(h = V x( )))) = "time expired"then p := [evalf(time( ) − z, 6), 'undefined ']; false

else p := [evalf(time( ) − z, 6), h]; true end if

end proc

> G:= proc(n) local k; for k to n do k end do end proc:

> Timetest(0.5, 10^6, G, p), p; ⇒ true, [0.234, 1000000]

> Timetest(0.5, 10^7, G, p), p; ⇒ false, [0.516, undefined]

В качестве примера применения timelimit-функции предыдущий фрагмент представляет простую Timetest(t, x, V, p)-процедуру, возвращающую true-значение только в том случае, когда вычисление V(x)-выражения укладывается в отведенный ему интервал в tсекунд, в противном случае ею возвращается false-значение. При этом, через аргумент p процедуры возвращается список, первый элемент которого определяет время вычисления искомого выражения, а второй - результат вычисления либо undefined-значение соответственно. В данном фрагменте Timetest-процедура применяется для временного тестирования вызова простой G-процедуры. При этом, следует иметь в виду, что в общем случае совместное использование функций time и timelimit в одной процедуре может приводить к некорректным результатам [12]. Вместе с тем, при получении определенного навыка использования функциональных средств языка существующих средств обработки особых и аварийных ситуаций оказывается вполне достаточным для создания в среде Maple довольно эффективных пользовательских систем обработки ситуаций такого рода. Более того, на основе знания специфики реализуемого в среде языка алгоритма решаемой задачи функциональные средства Maple-языка дают возможность проводить предварительный программный анализ на предмет предупреждения целого ряда возможных особых и аварийных ситуаций. Рассмотрим теперь вопросы обработки особых и аварийных ситуаций в контексте программирования процедур.

По функции ERROR, имеющей формат кодирования следующего вида:

ERROR({V1, V2, …, Vn})

производится немедленный выход из процедуры в точке ее вызова с возвратом диагностического сообщения следующего вида:

Error, (in {Proc|unknown}) {<V1>, <V2>, ... ,<Vn>}

где Proc - имя процедуры, вызвавшей ERROR-ситуацию, и <Vk> - результат вычисления Vk-выражения (k = 1 .. n); unknown-идентификатор выводится для непоименованной процедуры. Тогда как по предложению error, имеющему формат кодирования вида: error {Msg {, p1, p2, …, pn}} {:|;}

производится немедленный выход из процедуры в точке его выполнения с возвратом диагностического сообщения следующего вида:

Error, (in {Proc|unknown}) { Msg({p1, p2, …, pn})}

где Proc – имя процедуры, вызвавшей error-ситуацию, и <Msg({p1,p2,…,pn})> - результат подстановки pk-параметров в Msg-сообщение; unknown-идентификатор выводится для непоименованной процедуры. Msg - строка текста, определяющая суть ошибочной ситуации. Она может содержать пронумерованные параметры вида «%n», где n – целое число от 0 до 9. Тогда как pk – один или более параметров (Maple-выражений), которые подставляются вместо соответствующих по номеру вхождений '%n', когда возникает ошибочная ситуация. Например:

> error “invalid arguments <%1> and <%2>”, 3, 7; Error, invalid arguments <3> and <7> > 64/0;

Error, numeric exception: division by zero

> error;

Error, numeric exception: division by zero

> restart; error;

Error, unspecified error

При этом, если Msg отсутствует, то выполнение error-предложения в качестве диагностики выводит диагностику последней ошибочной ситуации текущего сеанса, если же и такой нет, то возвращается сообщение о неспецифицированной ошибке. Если параметр имеет вид '%n', то в возвращаемом сообщении он появляется как n-й параметр in lprintнотации, тогда как вид '%-n' обеспечивает его появление в сообщении в обычной нотации, например:

> error “%1 and %2 arguments are invalid”, 3, 7; Error, 3rd and 7th arguments are invalid

> error “%-1 and %-2 arguments are invalid”, 3, 7; Error, 3rd and 7th arguments are invalid

> ERROR(“%-1 and %-2 arguments are invalid”, 3, 7);

Error, 3rd and 7th arguments are invalid

Сказанное в полной мере относится и к оформлению ERROR-функции, начиная с релиза 6 Maple. Детальнее с оформлением диагностических сообщений для ERROR-функции (error-предложения) можно ознакомиться в справке по пакету.

При этом, значения Vk-выражений из ERROR-функции (Msg для error-предложения) помещаются в глобальную lasterror-переменную пакета и доступны для последующей обработки возникшей процедурной ошибки, которая с точки зрения Maple-языка в общем случае может и не быть ошибочной, как это иллюстрирует следующий фрагмент:

> restart; lasterror; ⇒ lasterror

> A:= proc() local k; `if`(type(nargs, ‘odd’), ERROR(“odd number of arguments”), `+`(args)) end proc: A(64, 59, 39, 10, 17, 44, 95, 2006); ⇒ 2334

> A(64, 59, 39, 10, 17, 44, 2006);

Error, (in A) odd number of arguments > lasterror; ⇒ "odd number of arguments"

> if lasterror = “odd number of arguments” then `Introduce new arguments` end if;

Introduce new arguments

> proc(x, y) `if`(x > y, ERROR(“for args[1] & args[2]”,args[1] > args[2]), y/x) end proc(17,10); Error, (in unknown) for args[1] & args[2], 10 < 17

> proc(x, y) if x > y then error “for args[1] & args[2]”, args[1] > args[2] else y/x end if end proc(17, 10);

Error, (in unknown) for args[1] & args[2], 10 < 17

В данном фрагменте простая А-процедура предусматривает обработку ошибочной ситуации, определяемой фактом получения процедурой при вызове нечетного числа фактических аргументов. В случае такой ситуации по ERRОR-функции производится выход из процедуры с возвратом соответствующего сообщения. После этого на основе анализа значения lasterror-переменной производится выбор пути дальнейших вычислений. Последний пример фрагмента иллюстрирует возврат ошибочного сообщения, связанного с определенным соотношением между аргументами, для непоименованной процедуры пользователя. При этом, использованы как ERROR-фунция, так и эквивалентное ей error-предложение.

> plot(x);

Plotting error, empty plot

> lasterror, lastexception; ⇒ lasterror, lastexception

> ulibrary(8, `C:/AVZ/AGV&bsol;VSV/Art&bsol;Kr`, MKDIR); Error, During delete of MKDIR - could not open help database

> lasterror, lastexception; ⇒ lasterror, lastexception

Следует отметить, что к сожалению пакет Maple не отражает в переменных lasterror и lastexception целый ряд весьма существенного типа ошибочных ситуаций, связанных, прежде всего, с графическими объектами (а в общем случае со средствами GUI пакета), как это весьма наглядно иллюстрирует предыдущий достаточно простой фрагмент. В свою очередь, это же не позволяет обрабатывать такого типа ошибки средствами пакета. При этом, другого типа недоработки Maple иначе как «чехардой» назвать и вовсе трудно. В частности, доступ к отсутствующему файлу или каталогу для релизов 6–9 пакета инициирует ошибочную ситуацию "file or directory does not exist", тогда как в релизе 10 возвращается несколько иная диагностика такой ситуации "file or directory, %1, does not exist". Диагностика ошибочной ситуации "wrong number (or type) of parameters in function …" релизов 6 – 9 пакета Maple изменена в релизе 10 на диагностику "invalid input: …". Серьезными причинами такие замены объяснить трудно. Указанные моменты потребовали очередной корректировки нашей Библиотеки [41,103], например, путем корректировки try-предложения, а именно:

try …..

………

catch "file or directory does not exist": … catch "file or directory, %1, does not exist": …… (введено дополнительно)

…….... end try

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

Так как механизм ERROR-функции (error-предложения) позволяет производить обработку ситуаций, ошибочных с точки зрения внутренней логики реализуемого процедурой алгоритма, т. е. прогнозируемых ошибок, то для этих же целей может быть использована и функция RETURN (return-предложение), как это иллюстрирует следующий фрагмент:

> WM:= proc() local k; global V; for k to nargs do if whattype(args[k]) <> 'float' then error nargs, [args] end if end do: `End of WM-procedure` end proc: WM(6.4, 350, 10, 17); lasterror;

Error, (in WM) 4, [6.4, 350, 10, 17]

4, [6.4, 350, 10, 17]

> WM1:= proc() local k; global V; for k to nargs do if whattype(args[k]) <> 'float' then return nargs, [args] end if end do: `End of WM1-procedure` end proc: WM1(6.4,350,10,17);

4, [6.4, 350, 10, 17]

> if whattype(%) = exprseq then WM1(op(evalf(lasterror[2]))) end if;

End of WM1-procedure > if whattype(%%) = exprseq then WM1(op(evalf(%%[2]))) end if; End of WM1-procedure

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