       Flat: Problems & Workarounds

• To: mathgroup at smc.vnet.net
• Subject: [mg8451] Flat: Problems & Workarounds
• From: Johan Gunnarsson <johan at isy.liu.se>
• Date: Sat, 30 Aug 1997 00:43:05 -0400
• Organization: Automatic Control. Linköping University, Sweden.
• Sender: owner-wri-mathgroup at wolfram.com

```This is the result from my work trying to construct a associative
function.
Assume I want a associative function h[] which treats numerical
arguments
specially. Starting from the template in Roman Maeders "Programming in
Mathematica", 3rd ed. I define h[] as

In:= SetAttributes[h,{Flat,OneIdentity}]
h[x_,y_?NumericQ] := f[y,x]
h[x_?NumericQ,y_] := f[x,y]
h[x_] := x
h[] = 1

Now we try this out by

In:= h[2,a,3]

Out= f[3,f[2,a]]

which is what I want, but if none of the arguments are numeric we get

In:= h[a,b]
\$IterationLimit::"itlim": "Iteration limit of \!\(20\) exceeded."
Out= Hold[h[a,b]]

This result is reasonable since none of the binary definitions match in
this
case and we therefore get an infinite loop from the rule h[x_]:=x
since the Flat attribute makes h[h[a,b]] equal to h[a,b]. To call this
a longstanding bug might be wrong, even though this is certainly a
problem.

Roman Maeder suggest to move the attribute definition after the rules.
The
way I understood this was the following

In:= ClearAll[h]
h[x_,y_?NumericQ] := f[y,x]
h[x_?NumericQ,y_] := f[x,y]
h[x_] := x
h[] = 1
SetAttributes[h,{Flat,OneIdentity}]

This gives the following results

In:= h[2,a,3]

Out= h[2,a,3]

Surprisingly enough it seems that by putting the SetAttributes at the
end
makes the attributes inactive. Is this the correct behavior?
The second test shows that the infinite loop is gone.

In:= h[a,b]

Out= h[a,b]

Good!

By searching for my workaround, I found the peculiar behavior
of Mathematica conditions which I use in the following

In:= ClearAll[h]
SetAttributes[h,{Flat,OneIdentity}]
h[x_,y_?NumericQ] := f[y,x]
h[x_?NumericQ,y_] := f[x,y]
h[] /; True= 1

This gives the following results

In:= h[2,a,3]

Out= f[3,f[2,a]]

In:= h[a,b]

Out= h[a,b]

which is the behavior I want.
The defintion
h[] /; True = 1
which seams to be nonsense, prevents the pattern matcher from the
infinite loop. Otherwise we would get the tests
h[a,b], h[1,a,b], h[1,1,a,b], h[1,1,1,a,b] and so on since
h[] is interpreted as the neutral element.

Note that the condition must be placed outside the list of arguments.
The reason for this is exemplified by the following.

In:=SetAttributes[test,{HoldAll}]
test[___] := False

In:= SetAttributes[g,{Flat,OneIdentity}]
g[args__] /; test[args] := foo[args]

In:= Trace[g[a,b,c],test[___]]

Out= {{test[a,b,c]}}

In the case above the condition is outside the arguments
and the pattern matcher try once with all the arguments.
If we place the condition inside we get

In:= ClearAll[g]
SetAttributes[g,{Flat,OneIdentity}]
g[args__ /; test[args]] := foo[args]

In:= Trace[g[a,b,c],test[___]]

Out={{test[a,b,c]},{test[a,b]},{test[b,c]},{test[a]},{test[b]},{test[c]}}

which shows that all combinations of the arguments are tested. This is
not
only giving bad performance. It is also a completely different behavior
of the
pattern matcher.

Is this a feature or a bug?
Is it documented?
Is it possible to make a nice design of an associative function?

Sincerely

--
_____________________________________________________
|     Division of Automatic Control
/|\    Dept. of EE, Linkoping University