I have discovered a few annoying problems (bugs?) with ’args’ when deﬁning &-operators. Below I can reproduce two problems, while the third one is elusive and appears randomly. I will address it too although I don’t have a verbatim Maple output to show. I would appreciate any hints how to avoid them, or to understand them.

Let’s deﬁne function ``&t``

as follows:

> `&t`:=proc() local L: L:=[args]; RETURN(L) end: > > K1 := `&t`(e1,e2,e3); K1 := [e1, e2, e3] > type(%,list(name)); true

The above two answers are correct: `[e1, e2, e3]`

is a list of names.

Here is the ﬁrst problem:

> K := e1 &t e2 &t e3; K := [[e1, e2], e3]

Notice, that the output form has changed even though ``&t``

has not: unlike before, now the
output is a list consisting of a list and a name (I suspect that this is a result of any
&-operator being implicitly left-associative in Maple).

Next, Maple conﬁrms that K is of the type [list,name] and that K is not of the type list(name) like K1 was:

> type(K,[list,name]); true > type(K,list(name)); false

Given that the outputs K1 and K are diﬀerent to me is illogical and for sure causes programming problems.

Here comes the second problem. I believe it is even worse than the ﬁrst one: it has to do with
the same type checking except now it will be done inside the procedure, not outside.
For that purpose, I will slightly re-deﬁne ``&t``

and call it ``&T``

for the sake of
discussion:

> `&T`:=proc() local L: L:=[args]; > if type(L,list(name)) then RETURN(list_of_names) elif > type(L,[list,name]) then RETURN(list_and_name) else > ERROR(`wrong types`) fi end: > > `&T`(e1,e2,e3); list_of_names

This answer is correct and it has been expected since `L=[args]`

is a list of name. Now please
take a note of the following surprising result:

> e1 &T e2 &T e3; list_of_names

That is unexpected and diﬀerent than before: K above was of the type [list,name] so why
does Maple think now that [args] inside ``&T``

is of type list(name) when before clearly [args]
was explicitly not of that type? What is going on? Why two diﬀerent results from the type
checking, one done inside and one done outside?

The third problem has to do with Maple returning sometimes `[e1 &t e2, e3]`

instead of
`[[e1,e2],e3]`

in the ﬁrst example. I have no clue why. Has anyone encountered this problem
before?

PS I run Maple V R. 4 patch 4.00b April 16, 1996, under Windows NT and 95.

As I understand it, when you apply ``&t``

as an applicative expression such as

`&t`(e1,e2,e3)

you are applying the procedure to an argument list of three variables but when you do

e1 &t e2 &t e3

you are applying the procedure to an argument list of two arguments (e1,e2) and then repeating the application of the procedure to (again to two arguments) the result of this operation and e3).

I comment further below and hope it helps

| Here is the ﬁrst problem: ...

Your input is a equivalent to

> K:= `&t`(`&t`(e1,e2),e3);

Hence the resulting nested list

| Here comes the second problem. ...

This is like requesting (again)

> `&t`(`&t`(e1,e2),e3);

which results in evaluation of ``&t`(list_of_names,e3)`

which leads to the result you
got.

| Here is the ﬁrst problem: ...

The output has changed because the input has changed. In other words, Maple parses
`e1 &t e2 &t e3`

as `(e1 &t e2) &t e3`

and does not automatically simplify it to
``&t`(e1, e2, e3)`

. Seems reasonable enough to me.

| Given that the outputs K1 and K are diﬀerent to me is illogical ...

I don’t know what’s illogical about it. `e1 &t e2 &t e3`

and ``&t`(e1, e2, e3)`

are diﬀerent,
that’s all. When used in inﬁx form, a `"&"`

operator is a binary operator, not a ternary
operator.

If ``&t`(e1,e2,e3)`

is what you want, then ``&t`(e1,e2,e3)`

is what you have to
say.

| Here comes the second problem. ...

Not at all surprising, and nothing to do with type checking. Remember that Maple parses
the input as `(e1 &T e2) &T e3`

. So ﬁrst it calls `&T`

with arguments e1 and e2. Since [e1,e2] is
a list of names, the result of that is a name, namely `"list_of_names"`

. Then it calls `&T`

with
arguments `list_of_names`

and e3, and since `[list_of_names, e3]`

is a list of names it
returns `list_of_names`

.

| The third problem has to do with Maple returning sometimes ...

I have no idea why this would happen. It would mean that somehow the `e1 &t e2`

was not
being evaluated. Are you sure that it happens in this example exactly as you gave it to us? I
suspect that it is not "random", but that you have done something in your Maple session
that caused `e1 &t e2`

to return unevaluated.

P.S. One thing that `_is_ a bug`

, in my opinion, is that (if `&q`

is unassigned) Maple prints
both `(a &q b) &q c and a &q (b &q c) as a &q b &q c`

(although the internal
representations are diﬀerent - you can use lprint to see that). For a non-associative operator
this can lead to confusion.

The following procedure does what you want (though I suspect your example was a simple model of the real problem).

`&t` := proc() map(proc(a) if a::list then a[] else a fi end, [args]) end:

| Here comes the second problem....

The reason is that you are returning `list_of_names`

, not an actual list. What you should
have done [to demonstrate the problem] is,

`&T`:=proc() local L: L:=[args]; if type(L,list(name)) then print(list_of_names) else print(list_and_name) fi; L end:

now

a &T b &T c; list_of_names list_and_name [[a, b], c]

which is as expected.

| Here is the ﬁrst problem: ...

A procedure with an `&-name`

is not implicitly assocative. First take an unnassigned operator
name `&A`

. You can write

> x &A y; x &A y instead of > `&A`(x,y); x &A y You also can write > x &A y &A z; x &A y &A z

which is interpreted as ``&A`(`&A(x,y),z)`

which is diﬀerent from ``&A`(x,y,z)`

.

Compare the following.

> eq:=(x &A y) &A z = x &A (y &A z); x &A y &A z = x &A y &A z

The echo on the screen let us thing that the equation is true. Not so.

> evalb(eq); false > op(lhs(eq)); x &A y, z > op(rhs(eq)); x, y &A z

Now you can understand what happends in your second example.

`&T`

is called twice. First with the arguments e1,e2 and second with the arguments
`list_of_names,e3`

. Of cource `&T returns again list_of_names`

.

| The third problem has to do with Maple returning sometimes ...

For example

> 'e1 &t e2' &t e3;

gives

[e1 &t e2, e3]

I think your above operators are only pre-examples and what you really want to do is more complex. May be, I can give you some hints, if you say a bit more about your goals.

| Here is the ﬁrst problem: ...

The result seems to me correct. It prooves that Maple interpret
`"e1 &t e2 &t e3" as "(e1 &t e2) &t e3"`

. Expressions are interpreted from left to
right. The second `"&t" receives [e1,e2]`

as ﬁrst argument and e3 as second
argument.

I assume you want a "concatenation". The following `&t`

returns a sequence instead of a
list

> restart: > `&t`:=proc() local L: L:=args; RETURN(L) end: > K1:=[e1 &t e2]; K1 := [e1, e2] > K2:=[e1 &t e2 &t e3]; K2 := [e1, e2, e3]

| Here comes the second problem. ...

Why surprising ? Maple interpret `"e1 &T e2 &T e3" as "(e1 &T e2) &T e3"`

. The result
of `(e1 &T e2) is the string "list_of_names"`

...

Problem 1:

The diﬀerence between `&t(e1,e2,e2) and e1 &t e2 &t e3`

is that the ﬁrst calls `&t`

once
while the second calls `&t`

twice.

Problem 2:

Try putting a trace into the procedure:

`&T`:=proc() option trace: local L: L:=[args]; if type(L,list(name)) then RETURN(list_of_names) elif type(L,[list,name]) then RETURN(list_and_name) else ERROR(`wrong types`) fi end:

Then you get:

> &T(e1,e2,e3); {--> enter &T, args = e1, e2, e3 L := [e1, e2, e3] <-- exit &T (now at top level) = list_of_names} list_of_names

and

> e1 &T e2 &T e3; {--> enter &T, args = e1, e2 L := [e1, e2] <-- exit &T (now at top level) = list_of_names} {--> enter &T, args = list_of_names, e3 L := [list_of_names, e3] <-- exit &T (now at top level) = list_of_names} list_of_names

Clearly in `e1 &T e2 &T e3`

there were two calls to `&T`

. The ﬁrst time it returned
`"list_of names"`

as it should; the second time `"list_of names"`

was the ﬁrst argument
which is itself a name, so the result `"list_of names"`

is correct.