Error invalid subscript selector maple

Error, invalid subscript selector Description Examples Description This error occurs when you use the selection operation incorrectly when selecting from a list or sequence . For more details, see Selection Operation . Errors due to invalid subscripts...

Example 1


L≔a,b,c,d,e

L:=a,b,c,d,e

(2.1)

L7

Error, invalid subscript selector

Five elements are assigned to list L. This error occurred because the index (subscript in 2-D Math) of the selection operation is out of range for the number of elements in the given list.

Solution:

To fix this error, the index should be within the range of the number of list elements.


L2

b

(2.2)

Note: Indices are notated using either subscript or square brackets. Both methods will return the same results.


L2

b

(2.3)

Example 2


S≔w,x,y,z

S:=w,x,y,z

(2.4)

S−6

Error, invalid subscript selector

In this example, four elements are assigned to sequence S. Negative values can be used for the index, and are used to count the elements starting from the end of the sequence, with -1 being the last item, -2 the second-last item, and so on. This error occurred because the negative index is out of the range of the given number of sequence elements.

Solution:

To fix the error, ensure the index (whether positive or negative) is within the range of the number of sequence elements.


S−2

y

(2.5)

Example 3


L3..8

Error, invalid subscript selector

Ranges (a..b) can be used for selecting elements, but they must be within range of the number of list elements. This error occurred because the range endpoint (8) of the index is out of range of the number of list elements.

Solution:


L3..5

c,d,e

(2.6)

Example 4


L4..2

Error, invalid subscript selector

If the index is a range of positive integers, the lower bound must be less than or equal to one more than the upper bound. Specifically, A3..3 selects a single element, A3..2 produces an empty selection, and A3..1 is not permitted. Negative integers in a range are first converted to equivalent positive integers, then this requirement is imposed.

Solution:


L5..5

e

(2.7)

L4..3

(2.8)

L−1..−2

(2.9)

Example 5


S1.2

Error, invalid subscript selector

The index of the selection operation must evaluate to an integer, a range, or NULL. This error occurred because the index is a non-integer. This could also be a syntax error; ranges must include two periods.

Solution:


S1

w

(2.10)

S1..2

w,x

(2.11)

S

w,x,y,z

(2.12)

pmi432 / LR05 / Books / Аладьев — Основы программирования в Maple, 2006

4.2. Формальные и фактические аргументы Maple —

Формальный аргумент процедуры в общем случае имеет вид Id > :: Тип >, т. е. Id -идентифи- катор с приписанным ему типом , который не является обязательным. В случае определения типированного формального аргумента при передаче процедуре в момент ее вызова фактического аргумента, последний проверяется на соответствие типу формального аргумента. При несовпадении типов идентифицируется ошибочная ситуация с выводом соответствующей диагностики. Совершенно иная ситуация имеет место при несовпадении числа передаваемых процедуре фактических аргументов числу ее формальных аргументов: ( 1 ) в случае числа фактических аргументов, меньшего определенного для процедуры числа формальных аргументов, как правило, идентифицируется ошибочная ситуация типа “ Error, (in Proc ) Proc uses a n th argument Id >, which is missing ” , указывающая на то, что Proc -процедуре было передано меньшее число фактических аргументов, чем имеется формальных аргументов в ее определении; где Id — идентификатор первого недостающего n -го фактического аргумента; ( 2 ) в случае числа фактических аргументов, большего определенного для процедуры числа формальных аргументов, ошибочной ситуации не идентифицируется и лишние аргументы игнорируются. Между тем, и в первом случае возможен корректный вызов. Это будет в том случае, когда в теле процедуры не используются формальные аргументы явно . Следующий простой фрагмент хорошо иллюстрирует вышесказанное:

nargs, [args] end proc: Proc(5, 6, 7, 8, 9, 10), Proc(5), Proc(), Proc(5, 6, 7);

6, [5, 6, 7, 8, 9, 10], 1, [5], 0, [], 3, [5, 6, 7]

a*b*c end proc: Proc(5, 6, 7), Proc(5, 6, 7, 8, 9, 10); 210, 210

Error, (in Proc) Proc uses a 2nd argument, b, which is missing

> AVZ:= proc(x::integer, y, z::float) evalf(sqrt(x^3 + y^3)/(x^2 + y^2)*z) end proc:

Error, AVZ expects its 1st argument, x, to be of type integer, but received 20.06

Error, (in AVZ) AVZ uses a 3rd argument, z (of type float), which is missing

> [ AVZ (64, 42, 19.42), AVZ (59, 42, 19.42, 78, 52)]; [1.921636024, 1.957352295]

В момент вызова процедуры с передачей ей фактических выражений для ее соответствующих формальных аргументов первые предварительно вычисляются и их значения передаются в тело процедуры для замещения соответствующих им формальных аргументов, после чего производится вычисление составляющих тело Maple -предложений с возвратом значения последнего вычисленного предложения, если не было указано противного. В случае наличия в определении процедуры типированных формальных аргументов элементы последовательности передаваемых при ее вызове фактических значений проверяются на указанный тип и в случае несовпадения инициируется ошибочная ситуация, в противном случае выполнение процедуры продолжается. В качестве типов формальных аргументов процедуры используются любые из допустимых языком и тестируемых функцией type и процедурой whattype . В случае использования нетипированного формального аргумента рекомендуется все же указывать для него anything -тип, информируя других пользователей процедуры о том, что для данного формального аргумента допускаются значения любого типа, например, кодированием заголовка процедуры в виде proc (X:: integer , Y:: anything ) .

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

Тип может быть как простым, так и сложным. При обнаружении в точке вызова процедуры фактического аргумента , типом отличающегося от заданного для соответствующего ему фор — мального аргумента, возникает ошибочная ситуация с возвратом через lasterror -переменную соответствующей диагностики и с выводом ее в текущий документ, например:

> A:=proc(a::integer, b::float) a*b end proc: A(64, 42);

Error, invalid input: A expects its 2nd argument, b, to be of type float, but received 42

«invalid input: %1 expects its %-2 argument, %3, to be of type %4, but received %5»

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

> A1:=proc(a::numeric, b::numeric) local a1, b1; assign(a1=a, b1=b); if not type(a, ‘integer’) then a1:=round(a) end if; if not type(b, ‘float’) then b1:=float(b) end if; a*b end proc: A1(64, 42), 17*A1(10/17, 59); 2688, 590

Большинство процедур нашей библиотеки [103] использует именно подобный подход программной обработки получаемых фактических аргументов на их допустимость и, по возможности, производятся допустимые корректировки. Это существенно повышает устойчивость процедур относительно некорректных фактических аргументов.

При организации процедур роль типированных формальных аргументов не ограничивается только задачами проверки входной информации, но несет и ряд других важных нагрузок. В частности, использование uneval -типа для формального аргумента позволяет вне процедуры проводить его модификацию ( т.е. обновлять на « месте » Maple — объект, определенный вне тела процедуры под этим идентификатором ) как это иллюстрирует нижеследующий фрагмент:

A := proc ( L :: list , a :: anything ) assign(‘ L ‘ = subs( a = NULL , L )) end proc

> L:=[64, 59, 39, 44, 10, 17]; A(L, 64); L := [64, 59, 39, 44, 10, 17] Error, (in assign) invalid arguments

A1 := proc ( L :: uneval , a :: anything ) if not type( L , ‘ symbol ‘) then

error «1st argument must be symbol but had received %1» , whattype( L ) elif type(eval( L ), <‘ list ‘, ‘ set ‘>) then assign(‘ L ‘ = subs(

[`if`( not type( a , <‘ list ‘, ‘ set ‘>), a = NULL , seq( k = NULL , k = a ))],

else error «1st argument must has type but had received %1-type» , whattype(eval( L ))

end if end proc

> A1(L, 64), L, A1(L, 59), L, A1(L, <59, 39, 44, 10, 17>), L; [59, 39, 44, 10, 17], [39, 44, 10, 17], [] > A1(AVZ, 64), AVZ;

Error, (in A1) 1st argument must has type but had received symbol-type

> A1([1, 2, 3, 4, 5, 6], 64);

Error, (in A1) 1st argument must be symbol but had received list

Попытка определить такую операцию для стандартно типированного L -аргумента в А -про- цедуре вызывает ошибку выполнения, тогда как, определив этот же L -аргумент как аргумент uneval -типа и использовав в дальнейшем обращение к нему через eval -функцию, получаем вполне корректную А1 -процедуру, обеспечивающую обновление « на месте » списка/множест-

ва L путем удаления его элементов, определенных вторым a -аргументом, в качестве которого может выступать как отдельный элемент, так и их список/множество. Проверка же на тип фактического L -аргумента производится уже программного в самой процедуре; при этом, проверяется не только на тип < list , set >, но и на получение идентификатора объекта, а не его значения ( т.е. в качестве фактического L -аргумента должно выступать имя списка/множества ). Данный прием может оказаться весьма полезным в практическом программировании, именно он используется рядом процедур нашей библиотеки [103].

Для организации процедуры наряду с предложениями, описывающими непосредственный алгоритм решаемой задачи ( а в ряде случаев и для обеспечения самого алгоритма ), Maple -язык предоставляет ряд важных средств, обеспечивающих функции, управляющие выполнением процедуры. В первую очередь, к ним можно отнести переменные args и nargs , возвращающие соответственно последовательность переданных процедуре фактических аргументов и их коли — чество . Оба эти средства имеют смысл только в рамках процедуры, а по конструкциям вида args <| [n] | [n..m] >можно получать < последовательность фактических аргументов | n — й аргумент |

аргументы с n — го по m — й включительно > соответственно. Тогда как nargs -переменная возвращает количество полученных процедурой фактических аргументов. Назначение данных средств достаточно прозрачно и обусловливает целый ряд их важных приложений при разработке пользовательских процедур. В первую очередь, это относится к обработке получаемых процедурой фактических аргументов. В частности, nargs -переменная необходима с целью обеспечения определенности выполнения вычислений в случае передачи процедуре неопределенного числа аргументов. Следующий простой фрагмент иллюстрирует сказанное:

> SV:= proc() product(args[k], k= 1 .. nargs)/sum(args[k], k= 1 .. nargs) end proc: > 137*SV(42, 47, 62, 67, 89, 96, 350, 39, 44, 59, 64); 22698342960272179200

> GN:= proc() [nargs, [args]] end proc: GN(V, G, S, A, Art, Kr);

[6, [V, G, S, A, Art, Kr]]

> map(whattype, [59, 17/10, ln(x), 9.9, «RANS»]);

[integer, fraction, function, float, string]

> Arg_Type:= proc() map(whattype, [seq(args[k], k= 1 .. nargs)]) end proc:

> Arg_Type(59, 17/10, ln(x), 9.9, «RANS»);

[integer, fraction, function, float, string]

> Arg_Type:= proc() map(whattype, [args[k]$k= 1 .. nargs]) end proc:

> Arg_Type(59, 17/10, ln(x), 9.9, «RANS»);

[integer, fraction, function, float, string]

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

что оказывается весьма удобным механизмом для организации процедур, ориентированных, в первую очередь, на задачи символьных вычислений и обработки [9-14,39].

Дополнительно к переменным args и nargs можно отметить еще одну важную переменную procname , возвращающую имя процедуры ее содержащей. В целом ряде случаев данная переменная оказывается весьма полезной, в частности, при возвращении вызова процедуры не — вычисленным . С этой целью используется конструкция формата ‘procname( args )’ . Многие пакетные процедуры возвращают результат именно в таком виде, если не могут решить задачу. Ряд процедур и нашей библиотеки [103] поступают аналогичным образом. Между тем, переменная может procname использоваться и в других полезных приложениях. Следующий фрагмент иллюстрирует применение указанной переменной как для организации возврата вызова процедуры невычисленным, так и для вывода соответствующего сообщения:

if nargs ≤ 6 then

WARNING(«%1(%2)=%3», procname , seqstr(args), `+`(args)/nargs ) else ‘procname (args)’

end if end proc

> AVZ(64, 59, 39, 44, 10, 17);

Warning, AVZ(64, 59, 39, 44, 10, 17)=233/6

> AVZ(64, 59, 39, 44, 10, 17, 6); AVZ(64, 59, 39, 44, 10, 17, 6)

Процедура AVZ при получении не более 6 фактических аргументов выводит соответствующее сообщение, описывающее вызов процедуры и его результат, тогда как в противном случае вызов процедуры возвращается невычисленным . Исходные тексты процедур нашей библиотеки, прилагаемой к книге [103], предоставляют неплохой иллюстративный материал по использованию переменных args , nargs и procname процедуры в различных ситуациях.

4.3. Локальные и глобальные переменные Maple —

Используемые в теле процедуры переменные по области определения делятся на две группы: глобальные ( global ) и локальные ( local ). Глобальные переменные определены в рамках всего текущего сеанса работы с ядром пакета и их значения доступны как для использования, так и для модификации в любой момент и в любой Maple -конструкции, где их применение корректно. Для указания переменной глобальной ее идентификатор кодируется в global -секции определения процедуры, обеспечивая процедуре доступ к данной переменной. В этой связи во избежание возможной рассинхронизации вычислений и возникновения ошибочных ситуаций рекомендуется в качестве глобальных использовать в процедурах только те переменные, значения которых ими не модифицируются, а только считываются. В противном случае не исключено возникновение отмеченных ситуаций, включая и непредсказуемые. Следующий пример иллюстрирует некорректность определения в процедуре глобальной х -переменной:

> x:=64: proc(y) global x; x:=0; y^(x+y) end proc(10); evalf(2006/x); 10000000000 Error, numeric exception: division by zero

> x:=64: proc(y) global x; x:=0; y^(x+y) end proc: evalf(2006/x); 31.34375000

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

Если для переменных, используемых в определении процедуры, не определена область их действия ( local , global ), то Maple -язык классифицирует их следующим образом. Каждая переменная, получающая в теле процедуры определение по ( := )-оператору либо переменная цикла, определяемая функциями < seq , add , mul >полагается локальной ( local ), остальные полагаются глобальными ( global ) переменными. При этом, если переменные for -цикла не определены локальными явно, то выводится предупреждающее сообщение вида “ Warning, `k` is implicitly declared local to procedure `P` ” , где k и P – переменная цикла в процедуре P соответственно. Тогда как для функций sum и product переменные цикла рассматриваются глобаль — ными , не выводя каких-либо сообщений, что предполагает их явное определение в local -сек- ции. Однако вне зависимости от наличия предупреждающих сообщений рекомендуется яв — но указывать локальные и глобальные переменные, что позволит не только избегать ошибок выполнения, но и более четко воспринимать исходный текст процедуры. Следующий фрагмент иллюстрирует вышесказанное:

> G:= 2: A:= proc(n) V:=64: [args, assign(‘G’, 5), assign(‘V’, 9), assign(cat(H, n), `h`)] end proc:

Warning, `V` is implicitly declared local to procedure `A`

> [A(99), G, V, A(10), whattype(H9), H9]; [[99], 5, 9, [10], symbol, H9]

> k:= 64: H:= proc() product(args[k], k=1 .. nargs)/sum(args[k], k=1 .. nargs) end proc:

> [k, H(42, 47, 62, 67, 96, 89, 10, 17, 4), k];

Error, (in H) invalid subscript selector

> k:= 64: H:= proc() local k; product(args[k], k=1 .. nargs)/sum(args[k], k=1 .. nargs) end proc: > [k, H(42, 47, 62, 67, 96, 89, 10, 17, 4), k]; [64, 109772628480, 64]

> G:=proc() [seq(args[k],k=1..nargs), mul(args[n], n=1..nargs)/add(args[p], p=1..nargs)] end proc:

> k:=64: n:= 95: p:= 99: G(1, 2, 3, 4, 5, 6, 7, 8, 9): [k, n, p];

> k:=64: P:= () -> [seq(args[k], k=1..nargs)]: P(1, 2, 3), k;

> k:=64: P:= () -> [add(args[k], k=1..nargs)]: P(1, 2, 3), k;

> k:=64: P:= () -> [mul(args[k], k=1..nargs)]: P(1, 2, 3), k;

> k:=64: P:= () -> [sum(args[k], k=1..nargs)]: P(1, 2, 3), k;

Error, (in P) invalid subscript selector

> k:=64: P:= () -> [product(args[k], k=1..nargs)]: P(1, 2, 3), k;

Error, (in P) invalid subscript selector

> k:=64: P:=proc() for k to nargs do end do end proc: P(1, 2, 3), k; 64 Warning, `k` is implicitly declared local to procedure `P`

Таким образом, в указанных случаях соответствующие переменные процедуры при ее вычислении неявно декларируются локальными с выводом или без предупреждающих сообщений. С другой стороны, глобальные переменные даже без их явного декларирования в global -сек- ции можно генерировать в рамках процедуры, как это иллюстрирует первый пример предыдущего фрагмента. Делать это позволяет процедура assign . Однако работа с такими глобаль — ными переменными чревата непредсказуемыми последствиями. Таким образом, практика программирования в среде Maple -языка рекомендует следовать следующим двум правилам определения области действия переменных:

( 1 ) глобальными определять переменные лишь используемые в режиме ” чтения ” ; ( 2 ) локальные переменные определять явно в local — секции процедуры.

Использование данных правил позволит избежать многих ошибок, возникающих лишь в момент выполнения M aple -программ, синтаксически и семантически корректных, но не учитывающих специфики механизма использования языком глобальных и локальных переменных. А именно: если глобальная переменная имеет областью определения весь текущий сеанс работы с пакетои, включая тело процедуры ( глобально переопределять ее можно внутри любой Maple — кон — струкции ), то локальная переменная областью определения имеет лишь тело процедуры и вне процедуры она полагается неопределенной, если до того не была определена вне процедуры глобально переменная с тем же идентификатором. Данный механизм имеет глубокий смысл, ибо позволяет локализовать действия переменных рамками процедуры ( в общем случае черного ящика ), не влияя на общий вычислительный процесс текущего сеанса работы с пакетом. Примеры предыдущего фрагмента наглядно иллюстрируют практическую реализацию описанного механизма локализации переменных в Maple- процедурах.

По assign -процедуре в теле процедур можно назначать выражения как локальным ( заданным явно ), так и глобальным ( заданным явно либо неявно ) переменным. Однако, здесь имеется одно весьма существенное отличие. Как известно, пакет не допускает динамического генерирования имен в левой части ( := )-оператора присваивания, тогда как на основе assign -процедуры это возможно делать. Это действительно существенная возможность, весьма актуальная в целом ряде задач практического программирования [103]. Между тем, если мы по процедуре assign в теле процедуры будем присваивать выражения локальным переменным и сгенерированным одноименным с ними переменным, то во втором случае присвоения производятся именно глобальным переменным, не затрагивая локальных . Нижеследующий пример весьма наглядно иллюстрирует вышесказанное.

> restart; V42, G47:= 10, 17: proc() local V42, G47; assign(V42=64, G47=59); assign(cat(V, 42)=100, cat(G, 47)=200); [V42, G47] end proc(), [V42, G47]; [64, 59], [100, 200]

Таким образом, данное обстоятельство следует учитывать при работе с динамически генерируемыми переменными в теле процедур.

Следует еще раз отметить, что для предложений присвоения в процедурах в целом ряде случаев использование assign -процедуры является единственно возможным подходом. Однако, при таком подходе в общем случае требуется, чтобы левая часть уравнения x=a в assign(x=a) была неопределенным именем, т.е. для нее должно выполняться соотношение type (x, ‘symbol’) = true . И здесь вполне допустимо использование конструкций следующего общего формата:

assign(op([unassign(‘ Имя > ‘), Имя > ]) = Выражение > )

При этом, для таких объектов как процедуры, модули, таблицы и массивы ( включая матрицы и векторы в смысле Maple , а не NAG ) кодирование их имен в невычисленном формате необяза —

Источник

I have a list of numbers and I want to add them and then multiply them by a constant.

addList := proc(a::list,b::integer)::integer;
local x,i,s;
description "add a list of numbers and multiply by a constant";
x:=b;
s:=0;
for i in a do
    s:=s+a[i];
end do;
s:=s*x;
end proc;

sumList := addList([2, 2, 3], 2) works fine but at the same time sumList := addList([20, 20, 30], 2) gives an error.
Can somebody point out the error ?

asked Jun 3, 2013 at 0:11

Pradit's user avatar

In the for loop you do s:=s+a[i] but i is set to one of the values in a already — not the index of a value. A first pass fix would be to just change the statement above to s:=s+i.

You could also write the function as

proc(a::list,b::integer)::integer; 
   convert(a,`+`)*b; 
end;

answered Jun 3, 2013 at 3:53

DrC's user avatar

DrCDrC

7,5351 gold badge21 silver badges37 bronze badges

Even shorter, there is

addList:= (a,b)-> `+`(a[])*b;

answered Jun 4, 2013 at 0:30

Carl Love's user avatar

Carl LoveCarl Love

1,4618 silver badges7 bronze badges

Tags are words are used to describe and categorize your content. Combine multiple words with dashes(-), and seperate tags with spaces.

I have my maple code as follows. I don’t see why I got «Error, invalid subscript selector»? can anybody help me? Thanks in advance!!

>a := [2, 2, 3, 3, 3, 5];

b := [2, 2, 2, 3, 7];

for k to 10 do

  for j to 10 do

       c := b[k]; d := a[j];

if c = d then a := subsop(j = NULL, a);

    print(a);

     print(k);

    print(j);

     break

else print(k);

      print(j);

     print(-1)

end if

end do

end do;

print(a);
                             [2, 2, 3, 3, 3, 5]
                               [2, 2, 2, 3, 7]
                               [2, 3, 3, 3, 5]
                                      1
                                      1
                                [3, 3, 3, 5]
                                      2
                                      1
                                      3
                                      1
                                     -1
                                      3
                                      2
                                     -1
                                      3
                                      3
                                     -1
                                      3
                                      4
                                     -1
Error, invalid subscript selector
                                [3, 3, 3, 5]
 

4.2. Формальные и фактические аргументы Maple

процедуры

Формальный аргумент процедуры в общем случае имеет вид <Id>::<Тип>, т. е. Id-идентифи- катор с приписанным ему типом, который не является обязательным. В случае определения типированного формального аргумента при передаче процедуре в момент ее вызова фактического аргумента, последний проверяется на соответствие типу формального аргумента. При несовпадении типов идентифицируется ошибочная ситуация с выводом соответствующей диагностики. Совершенно иная ситуация имеет место при несовпадении числа передаваемых процедуре фактических аргументов числу ее формальных аргументов: (1) в случае числа фактических аргументов, меньшего определенного для процедуры числа формальных аргументов, как правило, идентифицируется ошибочная ситуация типа “Error, (in Proc) Proc uses a nth argument <Id>, which is missing, указывающая на то, что Proc-процедуре было передано меньшее число фактических аргументов, чем имеется формальных аргументов в ее определении; где Id — идентификатор первого недостающего n-го фактического аргумента; (2) в случае числа фактических аргументов, большего определенного для процедуры числа формальных аргументов, ошибочной ситуации не идентифицируется и лишние аргументы игнорируются. Между тем, и в первом случае возможен корректный вызов. Это будет в том случае, когда в теле процедуры не используются формальные аргументы явно. Следующий простой фрагмент хорошо иллюстрирует вышесказанное:

> Proc:= proc(a, b, c)

nargs, [args] end proc: Proc(5, 6, 7, 8, 9, 10), Proc(5), Proc(), Proc(5, 6, 7);

6, [5, 6, 7, 8, 9, 10], 1, [5], 0, [], 3, [5, 6, 7]

> Proc:= proc(a, b, c)

a*b*c end proc: Proc(5, 6, 7), Proc(5, 6, 7, 8, 9, 10); 210, 210

> Proc(645);

Error, (in Proc) Proc uses a 2nd argument, b, which is missing

>AVZ:= proc(x::integer, y, z::float) evalf(sqrt(x^3 + y^3)/(x^2 + y^2)*z) end proc:

>AVZ(20.06, 59, 64);

Error, AVZ expects its 1st argument, x, to be of type integer, but received 20.06

> AVZ(2006, 456);

Error, (in AVZ) AVZ uses a 3rd argument, z (of type float), which is missing

> [AVZ(64, 42, 19.42), AVZ(59, 42, 19.42, 78, 52)]; [1.921636024, 1.957352295]

Вмомент вызова процедуры с передачей ей фактических выражений для ее соответствующих формальных аргументов первые предварительно вычисляются и их значения передаются в тело процедуры для замещения соответствующих им формальных аргументов, после чего производится вычисление составляющих тело Maple-предложений с возвратом значения последнего вычисленного предложения, если не было указано противного. В случае наличия в определении процедуры типированных формальных аргументов элементы последовательности передаваемых при ее вызове фактических значений проверяются на указанный тип и в случае несовпадения инициируется ошибочная ситуация, в противном случае выполнение процедуры продолжается. В качестве типов формальных аргументов процедуры используются любые из допустимых языком и тестируемых функцией type и процедурой whattype. В случае использования нетипированного формального аргумента рекомендуется все же указывать для него anything-тип, информируя других пользователей процедуры о том, что для данного формального аргумента допускаются значения любого типа, например, кодированием заголовка процедуры в виде proc(X::integer, Y::anything).

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

<Переменная>::<Тип>

171

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

> A:=proc(a::integer, b::float) a*b end proc: A(64, 42);

Error, invalid input: A expects its 2nd argument, b, to be of type float, but received 42

> lasterror;

«invalid input: %1 expects its %-2 argument, %3, to be of type %4, but received %5»

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

> A1:=proc(a::numeric, b::numeric) local a1, b1; assign(a1=a, b1=b); if not type(a, ‘integer’) then a1:=round(a) end if; if not type(b, ‘float’) then b1:=float(b) end if; a*b end proc: A1(64, 42), 17*A1(10/17, 59); 2688, 590

Большинство процедур нашей библиотеки [103] использует именно подобный подход программной обработки получаемых фактических аргументов на их допустимость и, по возможности, производятся допустимые корректировки. Это существенно повышает устойчивость процедур относительно некорректных фактических аргументов.

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

A := proc (L::list, a::anything ) assign(‘L= subs(a = NULL, L)) end proc

> L:=[64, 59, 39, 44, 10, 17]; A(L, 64); L := [64, 59, 39, 44, 10, 17] Error, (in assign) invalid arguments

A1 := proc (L::uneval, a::anything ) if not type(L, ‘symbol‘) then

error «1st argument must be symbol but had received %1» , whattype(L) elif type(eval(L), {‘list‘, ‘set‘}) then assign(‘L= subs(

[`if`( not type(a, {‘list‘, ‘set‘}), a = NULL, seq(k = NULL, k = a))],

eval(L)))

else error «1st argument must has type {list, set} but had received %1-type» , whattype(eval(L))

end if end proc

> A1(L, 64), L, A1(L, 59), L, A1(L, {59, 39, 44, 10, 17}), L; [59, 39, 44, 10, 17], [39, 44, 10, 17], [] > A1(AVZ, 64), AVZ;

Error, (in A1) 1st argument must has type {list, set} but had received symbol-type

> A1([1, 2, 3, 4, 5, 6], 64);

Error, (in A1) 1st argument must be symbol but had received list

Попытка определить такую операцию для стандартно типированного L-аргумента в А-про- цедуре вызывает ошибку выполнения, тогда как, определив этот же L-аргумент как аргумент uneval-типа и использовав в дальнейшем обращение к нему через eval-функцию, получаем вполне корректную А1-процедуру, обеспечивающую обновление «на месте» списка/множест-

172

ва L путем удаления его элементов, определенных вторым a-аргументом, в качестве которого может выступать как отдельный элемент, так и их список/множество. Проверка же на тип фактического L-аргумента производится уже программного в самой процедуре; при этом, проверяется не только на тип {list, set}, но и на получение идентификатора объекта, а не его значения (т.е. в качестве фактического L-аргумента должно выступать имя списка/множества). Данный прием может оказаться весьма полезным в практическом программировании, именно он используется рядом процедур нашей библиотеки [103].

Для организации процедуры наряду с предложениями, описывающими непосредственный алгоритм решаемой задачи (а в ряде случаев и для обеспечения самого алгоритма), Maple-язык предоставляет ряд важных средств, обеспечивающих функции, управляющие выполнением процедуры. В первую очередь, к ним можно отнести переменные args и nargs, возвращающие соответственно последовательность переданных процедуре фактических аргументов и их количество. Оба эти средства имеют смысл только в рамках процедуры, а по конструкциям вида args{|[n]|[n..m]} можно получать {последовательность фактических аргументов|nй аргумент|

аргументы с nго по mй включительно} соответственно. Тогда как nargs-переменная возвращает количество полученных процедурой фактических аргументов. Назначение данных средств достаточно прозрачно и обусловливает целый ряд их важных приложений при разработке пользовательских процедур. В первую очередь, это относится к обработке получаемых процедурой фактических аргументов. В частности, nargs-переменная необходима с целью обеспечения определенности выполнения вычислений в случае передачи процедуре неопределенного числа аргументов. Следующий простой фрагмент иллюстрирует сказанное:

> SV:= proc() product(args[k], k= 1 .. nargs)/sum(args[k], k= 1 .. nargs) end proc: > 137*SV(42, 47, 62, 67, 89, 96, 350, 39, 44, 59, 64); 22698342960272179200

> GN:= proc() [nargs, [args]] end proc: GN(V, G, S, A, Art, Kr);

[6, [V, G, S, A, Art, Kr]]

> map(whattype, [59, 17/10, ln(x), 9.9, «RANS»]);

[integer, fraction, function, float, string]

>Arg_Type:= proc() map(whattype, [seq(args[k], k= 1 .. nargs)]) end proc:

>Arg_Type(59, 17/10, ln(x), 9.9, «RANS»);

[integer, fraction, function, float, string]

>Arg_Type:= proc() map(whattype, [args[k]$k= 1 .. nargs]) end proc:

>Arg_Type(59, 17/10, ln(x), 9.9, «RANS»);

[integer, fraction, function, float, string]

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

proc() <ТЕЛО> {Ψ(args[1], args[2], …, args[n])|n = nargs} end proc {;|:}

что оказывается весьма удобным механизмом для организации процедур, ориентированных, в первую очередь, на задачи символьных вычислений и обработки [9-14,39].

Дополнительно к переменным args и nargs можно отметить еще одну важную переменную procname, возвращающую имя процедуры ее содержащей. В целом ряде случаев данная переменная оказывается весьма полезной, в частности, при возвращении вызова процедуры невычисленным. С этой целью используется конструкция формата ‘procname(args)’. Многие пакетные процедуры возвращают результат именно в таком виде, если не могут решить задачу. Ряд процедур и нашей библиотеки [103] поступают аналогичным образом. Между тем, переменная может procname использоваться и в других полезных приложениях. Следующий фрагмент иллюстрирует применение указанной переменной как для организации возврата вызова процедуры невычисленным, так и для вывода соответствующего сообщения:

173

AVZ := proc ()

if nargs 6 then

WARNING(«%1(%2)=%3», procname , seqstr(args), `+`(args)/nargs ) else ‘procname (args)’

end if end proc

> AVZ(64, 59, 39, 44, 10, 17);

Warning, AVZ(64, 59, 39, 44, 10, 17)=233/6

> AVZ(64, 59, 39, 44, 10, 17, 6); AVZ(64, 59, 39, 44, 10, 17, 6)

Процедура AVZ при получении не более 6 фактических аргументов выводит соответствующее сообщение, описывающее вызов процедуры и его результат, тогда как в противном случае вызов процедуры возвращается невычисленным. Исходные тексты процедур нашей библиотеки, прилагаемой к книге [103], предоставляют неплохой иллюстративный материал по использованию переменных args, nargs и procname процедуры в различных ситуациях.

174

4.3. Локальные и глобальные переменные Maple

процедуры

Используемые в теле процедуры переменные по области определения делятся на две группы: глобальные (global) и локальные (local). Глобальные переменные определены в рамках всего текущего сеанса работы с ядром пакета и их значения доступны как для использования, так и для модификации в любой момент и в любой Maple-конструкции, где их применение корректно. Для указания переменной глобальной ее идентификатор кодируется в global-секции определения процедуры, обеспечивая процедуре доступ к данной переменной. В этой связи во избежание возможной рассинхронизации вычислений и возникновения ошибочных ситуаций рекомендуется в качестве глобальных использовать в процедурах только те переменные, значения которых ими не модифицируются, а только считываются. В противном случае не исключено возникновение отмеченных ситуаций, включая и непредсказуемые. Следующий пример иллюстрирует некорректность определения в процедуре глобальной х-переменной:

> x:=64: proc(y) global x; x:=0; y^(x+y) end proc(10); evalf(2006/x); 10000000000 Error, numeric exception: division by zero

> x:=64: proc(y) global x; x:=0; y^(x+y) end proc: evalf(2006/x); 31.34375000

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

Если для переменных, используемых в определении процедуры, не определена область их действия (local, global), то Maple-язык классифицирует их следующим образом. Каждая переменная, получающая в теле процедуры определение по (:=)-оператору либо переменная цикла, определяемая функциями {seq, add, mul} полагается локальной (local), остальные полагаются глобальными (global) переменными. При этом, если переменные for-цикла не определены локальными явно, то выводится предупреждающее сообщение вида Warning, `k` is implicitly declared local to procedure `P`, где k и P переменная цикла в процедуре P соответственно. Тогда как для функций sum и product переменные цикла рассматриваются глобальными, не выводя каких-либо сообщений, что предполагает их явное определение в local-сек- ции. Однако вне зависимости от наличия предупреждающих сообщений рекомендуется явно указывать локальные и глобальные переменные, что позволит не только избегать ошибок выполнения, но и более четко воспринимать исходный текст процедуры. Следующий фрагмент иллюстрирует вышесказанное:

> G:= 2: A:= proc(n) V:=64: [args, assign(‘G’, 5), assign(‘V’, 9), assign(cat(H, n), `h`)] end proc:

Warning, `V` is implicitly declared local to procedure `A`

> [A(99), G, V, A(10), whattype(H9), H9]; [[99], 5, 9, [10], symbol, H9]

>k:= 64: H:= proc() product(args[k], k=1 .. nargs)/sum(args[k], k=1 .. nargs) end proc:

>[k, H(42, 47, 62, 67, 96, 89, 10, 17, 4), k];

Error, (in H) invalid subscript selector

> k:= 64: H:= proc() local k; product(args[k], k=1 .. nargs)/sum(args[k], k=1 .. nargs) end proc: > [k, H(42, 47, 62, 67, 96, 89, 10, 17, 4), k]; [64, 109772628480, 64]

> G:=proc() [seq(args[k],k=1..nargs), mul(args[n], n=1..nargs)/add(args[p], p=1..nargs)] end proc:

> k:=64: n:= 95: p:= 99: G(1, 2, 3, 4, 5, 6, 7, 8, 9): [k, n, p];

[64, 95, 99]

> k:=64: P:= () -> [seq(args[k], k=1..nargs)]: P(1, 2, 3), k;

[1, 2, 3], 64

> k:=64: P:= () -> [add(args[k], k=1..nargs)]: P(1, 2, 3), k;

[6], 64

> k:=64: P:= () -> [mul(args[k], k=1..nargs)]: P(1, 2, 3), k;

[6], 64

> k:=64: P:= () -> [sum(args[k], k=1..nargs)]: P(1, 2, 3), k;

Error, (in P) invalid subscript selector

175

> k:=64: P:= () -> [product(args[k], k=1..nargs)]: P(1, 2, 3), k;

Error, (in P) invalid subscript selector

> k:=64: P:=proc() for k to nargs do end do end proc: P(1, 2, 3), k; 64 Warning, `k` is implicitly declared local to procedure `P`

Таким образом, в указанных случаях соответствующие переменные процедуры при ее вычислении неявно декларируются локальными с выводом или без предупреждающих сообщений. С другой стороны, глобальные переменные даже без их явного декларирования в global-сек- ции можно генерировать в рамках процедуры, как это иллюстрирует первый пример предыдущего фрагмента. Делать это позволяет процедура assign. Однако работа с такими глобальными переменными чревата непредсказуемыми последствиями. Таким образом, практика программирования в среде Maple-языка рекомендует следовать следующим двум правилам определения области действия переменных:

(1) глобальными определять переменные лишь используемые в режиме чтения; (2) локальные переменные определять явно в localсекции процедуры.

Использование данных правил позволит избежать многих ошибок, возникающих лишь в момент выполнения Maple-программ, синтаксически и семантически корректных, но не учитывающих специфики механизма использования языком глобальных и локальных переменных. А именно: если глобальная переменная имеет областью определения весь текущий сеанс работы с пакетои, включая тело процедуры (глобально переопределять ее можно внутри любой Mapleкон струкции), то локальная переменная областью определения имеет лишь тело процедуры и вне процедуры она полагается неопределенной, если до того не была определена вне процедуры глобально переменная с тем же идентификатором. Данный механизм имеет глубокий смысл, ибо позволяет локализовать действия переменных рамками процедуры (в общем случае черного ящика), не влияя на общий вычислительный процесс текущего сеанса работы с пакетом. Примеры предыдущего фрагмента наглядно иллюстрируют практическую реализацию описанного механизма локализации переменных в Maple-процедурах.

По assign-процедуре в теле процедур можно назначать выражения как локальным (заданным явно), так и глобальным (заданным явно либо неявно) переменным. Однако, здесь имеется одно весьма существенное отличие. Как известно, пакет не допускает динамического генерирования имен в левой части (:=)-оператора присваивания, тогда как на основе assign-процедуры это возможно делать. Это действительно существенная возможность, весьма актуальная в целом ряде задач практического программирования [103]. Между тем, если мы по процедуре assign в теле процедуры будем присваивать выражения локальным переменным и сгенерированным одноименным с ними переменным, то во втором случае присвоения производятся именно глобальным переменным, не затрагивая локальных. Нижеследующий пример весьма наглядно иллюстрирует вышесказанное.

> restart; V42, G47:= 10, 17: proc() local V42, G47; assign(V42=64, G47=59); assign(cat(V, 42)=100, cat(G, 47)=200); [V42, G47] end proc(), [V42, G47]; [64, 59], [100, 200]

Таким образом, данное обстоятельство следует учитывать при работе с динамически генерируемыми переменными в теле процедур.

Следует еще раз отметить, что для предложений присвоения в процедурах в целом ряде случаев использование assign-процедуры является единственно возможным подходом. Однако, при таком подходе в общем случае требуется, чтобы левая часть уравнения x=a в assign(x=a) была неопределенным именем, т.е. для нее должно выполняться соотношение type(x, ‘symbol’) = true. И здесь вполне допустимо использование конструкций следующего общего формата:

assign(op([unassign(‘<Имя>‘), <Имя>]) = <Выражение>)

При этом, для таких объектов как процедуры, модули, таблицы и массивы (включая матрицы и векторы в смысле Maple, а не NAG) кодирование их имен в невычисленном формате необяза

176

тельно, что может существенно облегчать программирование. Следующий весьма простой фрагмент иллюстрирует вышесказанное:

> x:= 64: assign(op([unassign(x), x]) = 59); x; 64

Error, (in unassign) cannot unassign ’64’ (argument must be assignable)

> P:= proc() end proc: M:= module() end module: T:= table([]): A:= array([]): > map(whattype, map(eval, [P, M, T, A])); [procedure, module, table, array]

> seq(assign(op([unassign(k), k])=59), k=[P,M,T,A]); [P,M,T,A], map(type, [P,M,T,A], ‘odd’);

[59, 59, 59, 59], [true, true, true, true]

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

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

Процедура

(1)

global (x = a)

global (x = a)

global (x = a)

(2)

global (x = a)

local (x = b)

global (x = a)

(3)

x true

local (x = b)

x::{name|symbol}

type(x, {name|symbol})

(4)

(x = a) false

Errorситуация

x = a

Вслучае (1) явно либо неявно определенная х-переменная процедуры на всем протяжении текущего сеанса сохраняет свое значение до его переопределения вне или в самой процедуре.

Вслучае (2) определенная локально в теле процедуры х-переменная в рамках процедуры может принимать значения, отличные от ее глобальных значений вне ее, т.е. в процедуре временно подавляется действие одноименной с ней глобальной х-переменной. Однако здесь имеют место и особые случаи (3, 4), не охватываемые стандартным механизмом. Для ряда функций, использующих ранжированные переменные (например, sum, product), возможны две ситуации, если такие переменные не декларировались в процедуре явно. Прежде всего, как отмечалось выше, не выводится предупреждающих сообщений о том, что они предполагаются локальными. Следовательно, они согласно трактовке Maple-языка должны рассматриваться глобальными. Между тем, если на момент вызова процедуры, содержащей такие функции, ранжированная х-переменная была неопределенной (случай 3), то получая значения в процессе выполнения процедуры, после выхода из нее она вновь становится неопределенной, т.е. имеет место глобальное поведение переменной. Если же на момент вызова процедуры х-переменная имела значение, то выполнение процедуры инициирует ошибочную ситуацию, а значение х— переменной остается неизменным (случай 4). Рассмотренные ситуации еще раз говорят в пользу явного определения входящих в процедуру переменных.

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

> y:= 64: GS:= proc(p) local y, F; F:= y -> sum(y^k, k= 0 .. n); diff(F(y), y$p) end proc: > [y, simplify(GS(2))];

y( n + 1 ) n2 − 2 yn n2 + y(n 1 ) n2 − y(n + 1 ) n + y( n 1 ) n + 2 yn − 2

64,

3

(y − 1)

Данный фрагмент иллюстрирует использование локальной y-переменной в качестве ведущей переменной F(y)-полинома от одной переменной. Вне области действия процедуры глобальная y-переменная имеет конкретное числовое значение, т.е. их области не пересекаются.

177

Следующий простой фрагмент иллюстрирует взаимосвязь локальных и глобальных переменных, когда вторые определяются как явно в global-секции, так и неявно через assign-процеду- ру. Второй же пример фрагмента иллюстрирует механизм действия uneval-типированного формального аргумента, когда (в отличие от стандарта) ему могут присваиваться выражения на уровне глобальных переменных. Применение подобного весьма полезного приема уже иллюстрировалось в предыдущем разделе.

> P:=proc() local a; global b; x:= 56; assign(‘m’=67); a:= proc(x) m:= 47; assign(‘n’= 89); x end proc; x*a(3) end proc:

Warning, `x` is implicitly declared local to procedure `P` Warning, `m` is implicitly declared local to procedure `a` > n, m:= 100, 100: P(), n, m; 168, 89, 67

> P1:= proc(m::uneval) local a, x; global b; a, x:= 59, 39; b:= 64; assign(‘m’=42) end proc: > m:= 64: P1(m), a, x, b, m; a, x, 64, 42

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

> W:= y^4;

W := y4

(1)

> y:= z^3;

y := z3

> z:= h^2;

z := h2

> h:= 3;

h := 3

> W;

282429536481

> [eval(W, 1), eval(W, 2), eval(W, 3), eval(W, 4)]; [y4, z12, h24, 282429536481]

(2)

> G:= proc() local W, y, z, h; W:= y^4; y:= z^3; z:= h^2; h:= 2; W end proc:

(3)

> [G(), eval(G()), evala(G()), evalf(G())]; [y4, 16777216, y4, y4]

в котором представлена простая рекурсивная цепочка выражений, вычисление которой реализует полностью рекурсивную подстановку и обеспечивает возврат конечного числового значения, т.е. производится полное вычисление для W-выражения, идентификатор которого полагается глобальным. С другой стороны, вызов функции eval(B, n) обеспечивает nуровневое вычисление заданного ее первым фактическим В-аргументом выражения, что иллюстрирует второй пример фрагмента.

Для полного вычисления произвольного В-выражения используется вызов eval(B)-функции. Однако в первом примере фрагмента W-переменная является глобальной, что и определяет ее полное вычисление, если (как это иллюстрирует второй пример) не определено противного. Наконец, третий пример фрагмента иллюстрирует результат вычисления той же рекурсивной цепочки выражений, но уже составляющих тело процедуры и идентификаторы которых определены в ней локальными. Из примера следует, что если не определено противного, то процедура возвращает только первый уровень вычисления W-выражения и для его полного вычисления требуется использование функции eval, как это иллюстрирует последний пример фрагмента. Данное обстоятельство следует всегда иметь в виду, ибо оно не имеет аналогов в традиционных языках программирования и наряду с требованием особого внимания обеспечивает целый ряд весьма интересных возможностей программирования в различных приложениях.

178

4.4. Определяющие параметры и описания Maple

процедур

Прежде всего, представим секцию описания (description), завершающую описательную часть определения процедуры и при ее наличии располагающуюся между секциями {local, global, options} и непосредственно телом процедуры. При отсутствии данных секций description— секция располагается непосредственно за заголовком процедуры и кодируется в следующем формате:

description <Строчная конструкция> {:|;}

Определенная в данной секции строчная конструкция не влияет на выполнение процедуры и используется в качестве комментирующей ее компоненты, т.е. она содержит текстовую информацию, предназначенную, как правило, для документирования процедуры. При этом, в отличие от обычного комментария языка, которое игнорируется при чтении процедуры, описание ассоциируется с процедурой при ее выводе даже тогда, когда ее тело не выводится по причине использования рассматриваемой ниже опции Copyright. Более того, определяемый description-секцией комментарий может быть одного из типов {name, string, symbol}, как это иллюстрирует следующий простой фрагмент:

>REA:= proc() description `Average`; sum(args[k], k= 1 .. nargs)/nargs end proc:

>REA(19.42, 19.47, 19.62, 19, 67, 19, 89, 20.06), eval(REA);

34.07125000, proc () description Average; sum(args[k],k = 1 .. nargs)/nargs end proc

>REA:= proc() option Copyright; description «Average of real arguments»; sum(args[k], k= 1 .. nargs)/nargs end proc:

>eval(REA); proc () description «Average of real arguments» … end proc

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

Рассмотрев секции local, global и description, несколько детальнее остановимся на {options| option}-секции, которая должна кодироваться непосредственно за двумя первыми (или быть первой при их отсутствии) в описательной части определения процедуры. В качестве параметров (опций) данной секции допускаются следующие: builtin, Copyright, trace, arrow, operator, remember и call_external. При этом, перечень опций может зависеть от релиза пакета.

Пакет располагает тремя типами процедур: встроенными непосредственно в ядро пакета, библиотечными и определяемыми самим пользователем. Параметр builtin определяет встроенную функцию пакета и при наличии он должен кодироваться первым в списке параметров option-секции. Данный параметр визуализируется при полном вычислении процедуры посредством eval-функции либо по print-функции, например:

> print(eval), eval(readlib);

proc () option builtin; 169 end proc proc () options builtin, remember; 237 end proc

Каждая встроенная функция идентифицируется уникальным номером (зависящим от номера релиза пакета) и пользователь не имеет прямой возможности определять собственные встроенные функции. В приведенном примере первым выводится результат вызова printфункции, а вторым — evalфункции, из чего следует, что встроенные функции eval и readlib имеют соответственно номера 98 и 152 (Maple 8, тогда как уже для Maple 10 эти номера соответственно будут 117 и 274), а вторая процедура имеет дополнительно и rememberопцию.

179

Для проверки процедур могут быть полезны и наши процедуры ParProc, ParProc1 и Sproc [103], обеспечивающие возврат как основных параметров процедур, модулей и пакетов, так и их местоположение в библиотеках Maple, как это иллюстрирует следующий фрагмент:

> ParProc(MkDir), ParProc(came); map(ParProc, [‘add’, march, goto, iostatus, seq]);

Arguments = (F::{symbol, string })

Arguments = (E::anything

)

locals = (f, h )

,

locals = (cd, r, k, h, z, K, L, Λ, t, d, ω, ω1, u, f, s)

globals = (__Art_Kr_ )

[builtin function, 91, iolib function, 31, builtin function, 193, iolib function, 13, builtin function, 101]

> ParProc(DIRAX);

DIRAX is module with exports [new, replace, extract, empty, size, reverse, insert, delete, sortd, printd, conv]

> ParProc(process); inert_function

process is module with exports [popen, pclose, pipe, fork, exec, wait, block, kill, launch]

> ParProc(Int);

Warning, <Int> is inert version of procedure/function <int>

> ParProc1(ParProc1, ‘h’), h;

Warning, procedure ParProc1 is in library [Proc, User, {«c:/program files/maple 8/lib/userlib»}]

Arguments = (M::{procedure , module })

locals = (a, b, c, d, p, h, t, z, cs, L, R, N, ω, ν) ,

globals = (_62, ParProc, Sproc )

[Proc, User, {«c:/program files/maple 8/lib/userlib» }]

> ParProc1(Sockets, ‘t’), t;

Warning, module Sockets is in library [package, Maple, {«C:\Program Files\Maple 8/lib»}]

[exports = (socketID , Open, Close, Peek, Read, Write, ReadLine , ReadBinary , WriteBinary , Server, Accept, Serve, Address, ParseURL, LookupService , GetHostName , GetLocalHost , GetLocalPort , GetPeerHost , GetPeerPort, GetProcessID , HostInfo , Status , Configure , _pexports )]

[locals = (defun, trampoline , soPath, solib, passign , setup, finalise )]

[options = (package , noimplicit , unload = finalise , load = setup )] [description = («package for connection oriented TCP/IP sockets» )], [package , Maple, {«C:Program FilesMaple 8/lib» }]

>Sproc(MkDir, ‘h’), h; true, [Proc, User, {«c:/program files/maple 9/lib/userlib»}]

>Sproc(`type/package`, ‘h’), h;

true, [Proc, Maple&User, {«C:Program FilesMaple 9/lib», «c:/program files/maple 9/lib/userlib»}]

С описанием данных процедур можно ознакомиться в [103], тогда как сами они находятся в прилагаемой к книге библиотеке. Там же можно получить и их исходные тексты.

Параметр Copyright определяет авторские права процедуры, ограничивая возможности вывода ее определения на печать. В качестве такого параметра пакет рассматривает любую конструкцию option-секции, начинающуюся с Copyrightслова. Все библиотечные Maple-проце- дуры определены с параметром Copyright, требуя для вывода на печать их определений установки опции verboseproc=n (n={2|3}) в interface-процедуре. Типичное содержимое option— секции библиотечных процедур имеет следующий вид:

option `Copyright (c) 1997 Waterloo Maple Inc. All rights reserved.`;

option {system,} `Copyright (c) 1992 by the University of Waterloo. All rights reserved.`;

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

interface(verboseproc=3): {print|eval}(<Idпроцедуры>);

как это иллюстрирует следующий достаточно простой пример:

180

Соседние файлы в папке Books

  • #
  • #

    18.03.201519.23 Mб35Дьяконов_maple_9.5-10.djvu

Have a look below at lda3-ds.hk. Calling
hk-maple -c Simplify lda3-ds.hk | hk-maple -c Summarize -
gives a result, but fails to collapse the difference of summates.

To try to help it, I Kronecker-expanded s, yielding the commented-out block. But this throws a Maple error:

$ hk-maple -c Simplify lda3-ds.hk | hk-maple -c Summarize -
hk-maple: MapleException:
Error, (in KB:-kb_assuming_mb) when calling 'Apply'. Received: 'invalid
subscript selector'

after sending to Maple:
use Hakaru, NewSLO in timelimit(90, RoundTrip(lam(`nTopics`, HInt(Bound(`>=`,0)), lam(`nTokens`, HInt(Bound(`>=`,0)), lam(`z`, HArray(HInt(Bound(`>=`,0))), lam(`wordUpdate0`, HInt(Bound(`>=`,0)), lam(`zNewh0`, HInt(Bound(`>=`,0)), lam(`wordUpdate1`, HInt(Bound(`>=`,0)), lam(`zNewh1`, HInt(Bound(`>=`,0)), eval(eval(eval(case(And(`zNewh1` < `nTopics`, `zNewh0` < `nTopics`), Branches(Branch(PDatum(true, PInl(PDone)), (app(app(app(`s`, `z1`), `wordUpdate1`), `zNewh1`) + (-(app(app(app(`s`, `z0`), `wordUpdate0`), `zNewh0`))))), Branch(PDatum(false, PInr(PInl(PDone))), 0))), `s`=(lam(`zee`, HFunction(HInt(Bound(`>=`,0)), HInt(Bound(`>=`,0))), lam(`wordUpdate`, HInt(Bound(`>=`,0)), lam(`zNewh`, HInt(Bound(`>=`,0)), (Sum(case((`zNewh` = app(`zee`, `dB`)), Branches(Branch(PDatum(true, PInl(PDone)), 1), Branch(PDatum(false, PInr(PInl(PDone))), 0))), `dB`=0..(`nTokens`)-1) + (-(case((`zNewh` = app(`zee`, `wordUpdate`)), Branches(Branch(PDatum(true, PInl(PDone)), 1), Branch(PDatum(false, PInr(PInl(PDone))), 0))))))))))), `z1`=(lam(`j`, HInt(Bound(`>=`,0)), case((`j` = `wordUpdate1`), Branches(Branch(PDatum(true, PInl(PDone)), `zNewh1`), Branch(PDatum(false, PInr(PInl(PDone))), app(`z0`, `j`))))))), `z0`=(lam(`j`, HInt(Bound(`>=`,0)), case(`j` < `nTokens`, Branches(Branch(PDatum(true, PInl(PDone)), idx(`z`, `j`)), Branch(PDatum(false, PInr(PInl(PDone))), 0))))))))))))), HFunction(HInt(Bound(`>=`,0)), HFunction(HInt(Bound(`>=`,0)), HFunction(HArray(HInt(Bound(`>=`,0))), HFunction(HInt(Bound(`>=`,0)), HFunction(HInt(Bound(`>=`,0)), HFunction(HInt(Bound(`>=`,0)), HFunction(HInt(Bound(`>=`,0)), HInt()))))))), _command=Simplify)) end use;
"<input>" (line 1, column 1):
unexpected end of input
expecting "import" or expression

lda3-ds.hk

fn nTopics nat:
  fn nTokens nat: 
    fn z array(nat): 
      fn wordUpdate0 nat: 
        fn zNewh0 nat:
          fn wordUpdate1 nat: 
            fn zNewh1 nat:
              def z0(j nat): 
                if (j < nTokens): z[j]
                else: 0
    
              def z1(j nat):
                if (j == wordUpdate1): zNewh1
                else: z0(j)
    
              def s(zee (nat -> nat), wordUpdate nat, zNewh nat):
                (summate dB from 0 to nTokens: 
                  (match (dB == wordUpdate): 
                    true: 0
                    false: 
                     (match (zNewh == zee(dB)): 
                       true: 1
                       false: 0)))

              # def s(zee (nat -> nat), wordUpdate nat, zNewh nat):
              #   ((summate dB from 0 to nTokens: 
              #     (match (zNewh == zee(dB)): 
              #       true: 1
              #       false: 0))
              #   - (match (zNewh == zee(wordUpdate)): 
              #          true: 1
              #          false: 0))

              if (zNewh1 < nTopics && zNewh0 < nTopics):
                s(z1, wordUpdate1, zNewh1) - s(z0, wordUpdate0, zNewh0)
              else: 0

Недопустимая проблема селектора нижнего индекса в списке функций для цикла

Эта ошибка вывода eval (subs (x = 0, test [i]) ^ 2), недопустимый селектор подстрочного индекса в проблеме Maple — это test [i] в ​​цикле for, как избежать этой ошибки?

evolf := proc(z, f)
h1 := z + f;
h2 := z - f;
h3 := z*f;
h4 := z+diff(f,x);
h5 := z-diff(f,x);
h6 := z*diff(f,x);
h7 := subs(x=z, f);
test := [h1, h2, h3, h4, h5, h6, h7];
temp := 0;
for i from 1 to 9 do
    eval(subs(x=0,test[i])^2);
end do;
evalf(temp)
end proc;

Вы зацикливаетесь на 1 в 9, но в вашем массиве всего семь элементов. Вы пытаетесь получить доступ к элементам за пределами массива.

Создан 25 июн.

Не тот ответ, который вы ищете? Просмотрите другие вопросы с метками

arrays
maple

or задайте свой вопрос.

Понравилась статья? Поделить с друзьями:
  • Error invalid request squid
  • Error invalid request error description this application has no right to use messages
  • Error invalid request error description security error перевод
  • Error invalid request error description sdk options is undefined
  • Error invalid request error description sdk fingerprint is incorrect standoff