Break[] inside ColorFunction

18

4

Bug introduced in 8.0 or earlier and persisting through 11.0.1 or later


f[x_?NumericQ]:= (Do[Break[],{i,1,2}];x)
Plot[x,{x,0,1},ColorFunction->(ColorData["Rainbow"][f[#]]&)]

Break::nofwd: No enclosing For, While, or Do found for Break[].

What's going on here? I've tried setting HoldFirst attribute on f and I've also tried using Unevaluated which gives surprising results:

(* Works fine, gives plot colored as expected *)
Plot[x, {x, 0, 1}, 
 ColorFunction -> (Unevaluated[ColorData["Rainbow"][f[#1]]] &)]

(* Gives a black and white plot with error:
   "Unevaluated is not a Graphics primitive or directive" *)
ListContourPlot[IdentityMatrix[3],
  ColorFunction->(Unevaluated[ColorData["Rainbow"][f[#1]]]&)]

Edit This on the other hand works:

Plot[x,{x,0,1},ColorFunction->Function[c,ColorData["Rainbow"][f[c]]]]

Which only difference is that it uses Function[c,ColorData["Rainbow"][f[c]]]] instead of Function[ColorData["Rainbow"][f[Slot[1]]]]]

ssch

Posted 2012-12-17T19:16:47.223

Reputation: 16 150

4If I am not mistaken, this behavior is a consequence of a bad interaction of Break with AbortProtect, which in turn is probably used in some Plot code. It's an area that is receiving some attention in recent development work. I'm not sure what is the prognosis though. – Daniel Lichtblau – 2016-10-16T15:54:19.083

@NasserM.Abbasi if you don't like getting into the internals I think you chose the wrong question. I think this behaviour is quiiite weird – Rojo – 2012-12-17T20:34:49.647

I have no idea what's going on. It seems like Return and Break just don't work properly when running a ColorFunction. The Unevaluated might fix it because the ColorFunction doesn't actually evaluate the Break statement while inside the function – Rojo – 2012-12-17T20:43:46.937

1Perhaps, ColorFunction does some checking on the structure of the option (see that it can receive a string, a number, a function, and treat those cases differently). And, for some reason, when it's a function, Break and Return die. However, not when it's a function in the form Function[Null, ...]. Nonsense – Rojo – 2012-12-17T20:46:00.683

Another interesting observation is that Plot[x, {x, 0, 1}, ColorFunction -> Composition[ColorData["Rainbow"], f]] does not give an error, but it does not colour the plot either. The simpler Plot[x, {x, 0, 1}, ColorFunction -> Composition[ColorData["Rainbow"], # &]] doesn't work either. However, if I wrap it like this, Composition[ColorData["Rainbow"], # &], then use ColorFunction -> z, it does work. – Szabolcs – 2012-12-17T20:52:46.707

@NasserM.Abbasi Yes, but also After a Break the value Null is returned from the enclosing control structure. and Do[Break[],{1}]===Null is True :)

– ssch – 2012-12-17T21:03:43.963

@Szabolcs Can you clarify how you wrap it when it works? Edit: I presume you mean Function[z,...], at least that works too – ssch – 2012-12-17T21:13:05.493

This also has to do with the anonymous functions, since Plot[x, {x, 0, 1}, ColorFunction -> (Function[c, ColorData["Rainbow"][f[c]]])] works fine. Perhaps, @Rojo is right, and it tries some destructuring of the function and isn't careful enough about it. – Leonid Shifrin – 2012-12-17T21:17:12.033

@ssch Like this: z[x_] := Composition[ColorData["Rainbow"], # &][x]. It failed to paste properly. There's an annoying copy/paste problem on Mac I just can't get used to ... I always end up not copying the expression I want! – Szabolcs – 2012-12-17T22:11:26.037

No answers