Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I'm trying to modify Plus but am running into trouble with it being Listable:

ClearAll[f, g, h]
Attributes[f] = {Listable};
h /: f[x_h, l_List] := 0
h /: g[x_h, l_List] := 0
f[h[1], {1, 1}]   (* {f[h[1], 1], f[h[1], 1]}, not OK I want 0 *)
g[h[1], {1,1}]    (* 0 as expected *)

How can I make the UpValue (or equivalent) have higher priority than the listability?

EDIT: I ended up wanting to do this again and figured I'd fix the Plus properly. Here it is working using Sashas answer and Mr.Wizards $Pre method:

    $Pre =.
    ClearAll[myPlus]; Attributes[myPlus] = {Orderless};
    Unprotect[InterpolatingFunction]; UpValues[InterpolatingFunction] = {};
    InterpolatingFunction /: 
     myPlus[y_InterpolatingFunction[t_Symbol], l_List] := 
     Interpolation[
       MapThread[List, {y["Grid"], l + # & /@ y["ValuesOnGrid"]}], 
       InterpolationOrder -> First[y["InterpolationOrder"]]][t]
    myPlus[other__] := +other
    $Pre = Function[x, Unevaluated@x /. Plus -> myPlus, HoldAllComplete];
    Protect[InterpolatingFunction];

    y = Interpolation[Table[{i, RandomReal[{0, 1}, 2]}, {i, 1, 10}]];
    ParametricPlot[{y[t], y[t] - {1, 1}}, {t, 1, 10}]
share|improve this question
    
You can't do that, or I'll be very surprised. Change your design somehow. It's hard to help in that without knowing a little bit about the bigger picture. Perhaps for your case adding the "listability" as e:f[_, l_List]:=Thread@Unevaluated@e or something similar, but that depends on the case at hand –  Rojo Feb 5 '13 at 13:55
    
Oh, f is Plus, my bad. –  Rojo Feb 5 '13 at 13:57
    
Yes, I agree. Not possible (I even tried with $Pre and $Post to fool the evaluator, but you cannot do that). Just program Listable like f[x_, l_List] := Thread[f, {x, l}]; and all is good. –  Rolf Mertig Feb 5 '13 at 14:01
    
@Rojo Updated with bigger picture –  ssch Feb 5 '13 at 15:37
1  
I think this is one of these things which are really hard to make different generally and consistently, since one would have to explicitly go against the standard evaluation sequence. I would reconsider the design of whatever you try to achieve with this. While I will be the first to suggest workarounds which change system's behavior in many cases, I also think that admitting and accepting certain limitations of the system can sometimes be more productive. –  Leonid Shifrin Feb 5 '13 at 20:48

2 Answers 2

up vote 3 down vote accepted

This seems disgusting, but here it goes

h /: Plus[x_h, l_List] :=
 withPlusListability[True][

  blabla; 0
  ]

withPlusListability[bool_: True | False] := Function[code,
   Internal`InheritedBlock[{Plus},
    Unprotect[Plus];
    If[bool, SetAttributes, ClearAttributes][Plus, Listable];
    code
    ], HoldFirst];

withH = withPlusListability[False];

So

withH[
  Print[h[3] + {4, 5}];
  Print[h[3] + 7];
 ];

prints

(*
0
7+h[3]
*)

While you evaluate code iniside withPlusListability[True|False], it takes care that Plus has|doesn't have the Listable attribute, without changing it globally. h's definition will only have a chance of matching with an unlistable Plus.

Plus is one of those symbols that are so special you really try not to mess with. As @Mr.Wizard warned, this will likely break for packed arrays, because it probably has been optimized to cut some corners.

share|improve this answer
    
@MrWizard, surprisingly, h[3] + RandomReal[{-1, 1}, 10]; works. Could you try it in v7? –  Rojo Feb 5 '13 at 14:31
    
Cool, didn't know about Internal`InheritedBlock –  ssch Feb 5 '13 at 15:56
    
Rojo: yes, it works. I need to take a closer look at this. –  Mr.Wizard Feb 6 '13 at 1:28

Contrary to Rolf Mertig's comment I believe $Pre does work.

First define your function:

h /: myPlus[_h, _List] := 0
myPlus[other__] := +other

Then set $Pre:

$Pre = Function[x, Unevaluated@x /. Plus -> myPlus, HoldAllComplete];

Test:

h[1] + {4, 5, 6}
0
z[1] + {4, 5, 6}
{4 + z[1], 5 + z[1], 6 + z[1]}
share|improve this answer
    
@RolfMertig is pessimistic (comments) these days –  Rojo Feb 5 '13 at 14:36
2  
+other!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! HAAAAAAAAAAA +1 –  Rojo Feb 5 '13 at 14:39
    
You make it look so easy, thanks! –  ssch Feb 5 '13 at 15:59
    
@Rojo I'm afraid I don't understand your outburst. Unintentional humor? Does "plus other" mean something in contemporary parlance? –  Mr.Wizard Feb 5 '13 at 16:36
    
@ssch Glad I could help. :-) –  Mr.Wizard Feb 5 '13 at 16:37

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.