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.

Consider these definitions:

own = "OwnValue";
down[_] = "DownValue";
sub[_][_] = "SubValue";
N[n] = 3.14;
_[___, up, ___] ^= "UpValue";

The attribute HoldAllComplete holds an UpValue but it also holds the other Values as well.

Without advance knowledge of the symbol up how can I evaluate everything but the UpValue?

Set and related functions appear to have this evaluation property internally:

f[own, down[1], sub[1][2], N[n], up] = 1;

Definition[f]
f["OwnValue", "DownValue", "SubValue", 3.14, up] = 1

The first idea that comes to mind is to test if a symbol has an UpValue and skip evaluation if it does, but this proves problematic. First, a symbol can have both an OwnValue and an UpValue, and the OwnValue should be used if possible:

x[up3] ^= 2;
up3 = 1;

f[up3]
f[1] (* desired output *)

Second, testing for an UpValue can be difficult:

_[___, up4, ___] ^= {};

UpValues[up4] === UpValues[Plus]

True


To clarify, it is not my intent to return f[. . ., up] as output, which would require Defer or similar. Rather I would like to handle the expression f[. . ., up] as an argument like Set does, or define a function f[args___] := . . . (with attribute HoldAllComplete) that returns e.g. {"OwnValue", "DownValue", "SubValue", 3.14, HoldComplete[up]}

How can this be achieved?

share|improve this question
    
When you write f[up]=1, up appears at the second level. This is the reason why the UpValue does not evaluate. Consider x=up (which is Set[x,up])---this evaluates to "UpValue" right away. Now try SetAttributes[fun, HoldAll] and fun[p[up]]---this one does not evaluate because UpValues are evaluated only in the first level of held heads (just like Unevaluated, Sequence, etc.) –  Szabolcs Jul 21 '12 at 10:03
    
@Szabolcs believe it or not I know this. :^) I guess I didn't formulate my question all that well. Would you join me in Chat to work it out? –  Mr.Wizard Jul 21 '12 at 10:05
add comment

3 Answers

up vote 8 down vote accepted

Does this work as you want to?

SetAttributes[f, HoldAllComplete];
{first, rest___} ^:= HoldComplete[rest]
f[args___] := {first, args}

f[own, down[1], sub[1][2], N[n], up]

HoldComplete["OwnValue", "DownValue", "SubValue", 3.14, up]

share|improve this answer
    
Competing UpValues! Brilliant. –  Mr.Wizard Jul 21 '12 at 22:36
add comment

If I understand it correctly, the gist of your question is going from

HoldComplete[x, y, z, up]

to

HoldComplete[1, y^2, z, up]

assuming the following definitions:

_[___, up, ___] ^= "UpValueEvaluated"
x = 1
f[x_] := x^2

That is, evaluate everything inside the HoldComplete except the UpValue. I managed to do this using the following construction:

Internal`InheritedBlock[
 {RuleCondition},
 Attributes[RuleCondition] = {HoldAllComplete};
 Replace[HoldComplete[x, f[y], z, up], e_ :> RuleCondition[e], {1}]
]

The undocumented RuleCondition is explained here. This construction should be able to emulate the behaviour of Set.

share|improve this answer
1  
Intersting one... –  Rojo Jul 21 '12 at 12:08
    
@Rojo I'm still reading the other solutions. –  Szabolcs Jul 21 '12 at 12:11
2  
+1, clever. If desired, we can avoid using Internal`InheritedBlock by means of a helper identity function: SetAttributes[hci, HoldAllComplete]; hci[x_] := x. Then we can write: Replace[HoldComplete[x, f[y], z, up], e_ :> RuleCondition @ hci @ e, {1}]. –  WReach Jul 21 '12 at 17:57
    
@WReach & Szabolcs I don't understand how this works (both methods). Please enlighten me! –  Mr.Wizard Jul 21 '12 at 22:39
    
@Mr.Wizard Here's the key: stackoverflow.com/questions/6633236/… It's a way to evaluate any subexpression inside a held expression. I take all elements of the HoldComplete and evaluate them one-by-one. I need to take care on the way not to end up with something[up] where something doesn't have HoldAllComplete (this way the challenge). –  Szabolcs Jul 21 '12 at 22:43
show 2 more comments

To answer my own question and further illustrate the kind of operation I am describing, here is a method using Set itself:

SetAttributes[f, HoldAllComplete]

f[args___] :=
  Module[{h},
    h[args] = 1;
    Level[DownValues@h, {4}, HoldComplete]
  ]

f[own, down[1], sub[1][2], N[n], up]
HoldComplete["OwnValue", "DownValue", "SubValue", 3.14, up]
share|improve this answer
add comment

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.