# Help understanding overloading of Atomics within Block

Usually h @@@ {f[1, 2], f[3, 4]} === {h[1, 2], h[3, 4]} but this is not the case when f is Complex: h @@@ {1 + 2I, 3 + 4I } === {1 + 2 I, 3 + 4 I} Since Complexis an atomic and as documentation for Apply states: Applying to atomic objects that do not have subparts effectively does nothing

Using Block to replace Complex with complex gives result as expected for non-atomic case:

Block[{Complex = complex},
List @@@ {Complex[1, 2], Complex[3, 4]}
]
(* {{1, 2}, {3, 4}} *)


But then how come replacing Complex with List while not Apply-ing does not give the same result?

Block[{Complex = List},
{Complex[1, 2], Complex[3, 4]}
]
(* {Complex[1, 2], Complex[3, 4]} *)


As it would have for a non-atomic head:

Block[{f = List},
{f[1, 2], f[3, 4]}
]
(* {{1, 2}, {3, 4}} *)

• Funnily enough, if I use TracePrint[Block[{Complex = List}, {Complex[1, 2], Complex[3, 4]}]], the replacement happens. Quite odd, this evaluation... Commented Jun 19, 2013 at 16:19
• With[{Complex = List}, {Complex[1, 2], Complex[3, 4]}] works, but still does not explain the behavior. Block[{Complex = complex}, {Complex[1, 2], Complex[3, 4]}] does not work either, so Applying seems to be the key Commented Jun 19, 2013 at 16:32
• This is a very strange behavior. For example, this works: Block[{Complex}, Complex := List; {Complex[1, 2], Complex[3, 4]}], and after that, the original example works too. Looks like some changes are not propagated properly. Commented Jun 19, 2013 at 16:33
• As one might expect, this general technique also doesn't work if the head Complex exists only by implication, as in a packed array. Commented Jun 19, 2013 at 16:45
• Apparently Complex[1, 2] is not equivalent to 1 + 2I. Block[{Complex = f}, List @@@ {Complex[1, 2], 3 + 4 I}] gives {{1, 2}, 3 + 4I} I thought that was just a syntactic difference
– ssch
Commented Jun 19, 2013 at 18:44

## 1 Answer

This is hardly a complete answer but I suspect this is the result of special handling of the symbol Complex, much as there is special handling of packed arrays.

Remember that Block only affects things that evaluate, e.g. Block[{a = 1}, Hold[a, b, c]] returns Hold[a, b, c]. I believe that Complex may be passed over when it comes to evaluation. Consider this example outside of Block:

Unprotect[Complex];
Complex = ff;
Complex[1, 2]
Quit[]

1 + 2 I


The head Complex is never evaluated to ff here. Interestingly, with a delayed definition it is:

Unprotect[Complex];
Complex := ff
Complex[1, 2]
Quit[]

ff[1, 2]


I cannot think of a reason within the normal evaluation process for this to be, hence my suspicion of special handling.

• Try immediate evaluation after you try the delayed one. I also made all these experiments you present here, but somehow I feel that this is not the whole story. Commented Jun 19, 2013 at 16:49
• @Leonid Surely this is not the whole story, as stated. Do you agree that there appears to be special handling taking place? Commented Jun 19, 2013 at 16:51
• I am not sure about it. Commented Jun 19, 2013 at 16:54
• It should probably be noted that even Unprotect[Complex]; Complex = hh; Complex -> Complex. Same goes for Integer. Commented Jun 19, 2013 at 20:33
• @JacobAkkerboom This is not so simple. Check this: Unprotect[Complex];Complex := hh;Complexand then Complex =.;Complex = hh;Complex. Commented Jun 19, 2013 at 21:10