5
$\begingroup$

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}] 
$\endgroup$
5
  • $\begingroup$ 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 $\endgroup$ Commented Feb 5, 2013 at 13:55
  • $\begingroup$ Oh, f is Plus, my bad. $\endgroup$ Commented Feb 5, 2013 at 13:57
  • $\begingroup$ 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. $\endgroup$ Commented Feb 5, 2013 at 14:01
  • $\begingroup$ @Rojo Updated with bigger picture $\endgroup$ Commented Feb 5, 2013 at 15:37
  • 1
    $\begingroup$ 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. $\endgroup$ Commented Feb 5, 2013 at 20:48

2 Answers 2

3
$\begingroup$

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.

$\endgroup$
3
  • $\begingroup$ @MrWizard, surprisingly, h[3] + RandomReal[{-1, 1}, 10]; works. Could you try it in v7? $\endgroup$ Commented Feb 5, 2013 at 14:31
  • $\begingroup$ Cool, didn't know about Internal`InheritedBlock $\endgroup$ Commented Feb 5, 2013 at 15:56
  • $\begingroup$ Rojo: yes, it works. I need to take a closer look at this. $\endgroup$ Commented Feb 6, 2013 at 1:28
3
$\begingroup$

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]} 
$\endgroup$
8
  • $\begingroup$ @RolfMertig is pessimistic (comments) these days $\endgroup$ Commented Feb 5, 2013 at 14:36
  • 2
    $\begingroup$ +other!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! HAAAAAAAAAAA +1 $\endgroup$ Commented Feb 5, 2013 at 14:39
  • $\begingroup$ @Rojo I'm afraid I don't understand your outburst. Unintentional humor? Does "plus other" mean something in contemporary parlance? $\endgroup$ Commented Feb 5, 2013 at 16:36
  • $\begingroup$ @ssch Glad I could help. :-) $\endgroup$ Commented Feb 5, 2013 at 16:37
  • $\begingroup$ Yeye, act cool, as if +something is everyday notation to you, terseness master $\endgroup$ Commented Feb 5, 2013 at 16:44

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.