Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Question on Unevaluated

39 views
Skip to first unread message

Alexey

unread,
Mar 13, 2011, 6:31:10 AM3/13/11
to
Hello,

I am puzzled a bit by the Documentation for Unevaluated. Under "More
information" field we read:

"f[Unevaluated[expr]] effectively works by temporarily setting
attributes so that f holds its argument unevaluated, then evaluating
f[expr].".

After reading this I expect that

f[Unevaluated[1 + 1]; 2 + 1]

will be returned completely unevaluated as it is when I set HoldFirst
attribute to f:

In[2]:= SetAttributes[f, HoldFirst]
f[Unevaluated[1 + 1]; 2 + 1]

Out[3]= f[Unevaluated[1 + 1]; 2 + 1]

But in really we get

In[1]:= f[Unevaluated[1 + 1]; 2 + 1]

Out[1]= f[3]

This leads me to a question: what is implied in documentation? Which
attributes are temporarily set and to which function?

Daniel Lichtblau

unread,
Mar 14, 2011, 6:59:38 AM3/14/11
to

In your example the "funtion" in question would be CompoundExpression. So Mathematica is indeed acting as documented here.

By way of contrast, note the effect for the examples below.

In[18]:= f[Unevaluated[1 + 1], 2 + 1]
Out[18]= f[Unevaluated[1 + 1], 3]

In[19]:= f[Unevaluated[1 + 1; 2 + 1]]
Out[19]= f[Unevaluated[1 + 1; 2 + 1]]

You can have Mathematica show the structure simply by wrapping with FullForm[Hold[...]]

In[22]:= Hold[f[Unevaluated[1 + 1]; 2 + 1]] // FullForm
Out[22]//FullForm= FullForm[Hold[f[Unevaluated[1 + 1]; 2 + 1]]]

Daniel Lichtblau
Wolfram Research

Leonid Shifrin

unread,
Mar 14, 2011, 7:02:13 AM3/14/11
to
Alexey,

You forgot about the CompoundExpression (;). You only attempted to prevent
the evaluation of 1+1 inside
(1+1;3), but not the total result for CompoundExpression, which is the value
of the last statement
(2+1 in this case). This is what you probably had in mind:

In[9]:= f[Unevaluated[(1 + 1; 2 + 1)]]

Out[9]= f[Unevaluated[1 + 1; 2 + 1]]

What is perhaps less obvious is that you did not prevent the evaluation of
1+1 either. Here is
a simple way to check it:

In[14]:= f[Unevaluated[Print["*"]]; 2 + 1]

During evaluation of In[14]:= *

Out[14]= f[3]

The problem is that Unevaluated is only effective once. To totally prevent
something from evaluation,
you have to know the exact number of sub-evaluations (which is generally
impossible to know since
it can be data-dependent), and wrap in as many levels of Unevaluated. In
this case, the following will do:

In[13]:= f[Unevaluated[Unevaluated[Print["*"]]]; 2 + 1]

Out[13]= f[3]

But as I said, this is not a robust approach, and in such cases you will be
better to use Hold or similar for
a persistent holding wrapper, stripping it off later when needed. You may
want to check out e.g. this thread

http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/bfd67e9122b1fdec

(my second post there), where I elaborate on these issues.

HTH.

Regards,
Leonid

Alexey Popkov

unread,
Mar 14, 2011, 7:02:35 AM3/14/11
to
Leonid,

Is it possible to imitate the behavior of Unevaluated by setting Attributes in this case:

f[Print[1], Unevaluated[Print[2]], Print[3]]

?

I am wondering, what attributes are temporarily set when we use Unevaluated and how could I imitate this?

Alexey

JJ

unread,
Mar 14, 2011, 7:07:43 AM3/14/11
to
Hi,

I am not sure, but maybe the problem is that you wrote f[a;b] instead of
f[a,b] or f[{a,b}] (if it is listable).
The ";" is telling to output only f[b].

2011/3/13 Alexey <leh...@gmail.com>

Leonid Shifrin

unread,
Mar 14, 2011, 7:10:57 AM3/14/11
to
Alexey,

Doing what you request is generally not possible or at least extremely hard
(emulating exact behavior of Unevaluated in all cases), since Unevaluated is
one of the "magic symbols" (together with Evaluate and Sequence), wired deep
into the system. I discuss this a bit more here:

http://stackoverflow.com/questions/4856177/preventing-evaluation-of-mathematica-expressions/4856721#4856721

Regarding your particular request: it is an interesting exercise in working
with held expressions. Assuming
that we can only use Hold attributes, but neither Unevaluated nor Evaluate,
the following function will
(hopefully) work as if you had an attribute HoldN (that is, n-th argument
held, others not):

joinHeld[a__Hold] :=
Hold @@ Replace[Hold[a], Hold[x___] :> Sequence[x], {1}];

splitHeldSequence[Hold[seq___], f_: Hold] := List @@ Map[f, Hold[seq]];

Clear[makeHoldN];
Module[{keepOnTop},
makeHoldN[f_, n_Integer] :=
(SetAttributes[f, HoldAll];
f[args___] /; (! TrueQ[! keepOnTop]) :=
Block[{keepOnTop = False},
With[{result =
If[n > Length[Hold[args]],
f @@ {args},
Apply[f,
joinHeld @@
Flatten[{Hold[##] & @@@ Take[#, n - 1], #[[n]],
Hold[##] & @@@ Drop[#, n]}] &[
splitHeldSequence@Hold[args]]]]},
result /; Hold[result] =!= Hold[f[args]]]]) /;
FreeQ[DownValues[f], keepOnTop]]

Here are some examples of use:

ClearAll[f]
makeHoldN[f, 2];
f[1^2, 2^2, 3^2]

f[1, 2^2, 9]


In[22]:= ClearAll[ff];
ff[args___] := Hold[args];
makeHoldN[ff, 3];
ff[1^2, 2^2, 3^2]

Out[25]= Hold[1, 4, 3^2]

One can rather easily generalize this to hold an arbitrary subsequence of
arguments (specified by
a list of their indices) while evaluating the rest. The implementation
employs a number of tricks.
One that needs a bit of clarification is the f[args___] /; (! TrueQ[!
keepOnTop]) line, since it serves
2 purposes. The one related to Block trick is well-known to you. The other
is that the presence of
condition involving a user-defined symbol makes it impossible for
Mathematica rule ordering
system to make conclusions about the generality of the rule, and therefore
the rule does not go
to the bottom of the rule list. This is needed because we want this rule to
stay at the top, to intercept
all calls to the function. For the same reason, makeHoldN should be called
already after all the
definitions have been given to the function, or the function will not work
properly.

As you see, this is sort of possible, but complex and error-prone. In
practice, it is best to avoid
this sort of trickery, by changing the design of your functions. In my
experience, having HoldFirst,
HoldRest and HoldAll is quite enough. To evaluate any held argument, you can
also wrap it in
Evaluate. So, you particular question can be answered quite easily also as

SetAttributes[f,HoldAll];
f[Evaluate[Print[1]], Print[2], Evaluate[Print[3]]]

Note also, that I don't claim to reproduce exactly the behavior of
Unevaluated with my function above.
It is just an illustration of a possible poor man's device to accomplish the
specific goal of holding
n-th argument without the help of Evaluate and Unevaluated.

HTH

Regards,
Leonid


On Mon, Mar 14, 2011 at 1:06 AM, Alexey Popkov <leh...@gmail.com> wrote:

> Leonid,
>
> Is it possible to imitate the behavior of Unevaluated by setting Attributes
> in this case:
>
> f[Print[1], Unevaluated[Print[2]], Print[3]]
>
> ?
>
> I am wondering, what attributes are temporarily set when we use Unevaluated
> and how could I imitate this?
>
> Alexey
>
>
>
> ----- Original Message -----

> *From:* Leonid Shifrin <lsh...@gmail.com>
> *To:* Alexey <leh...@gmail.com> ; math...@smc.vnet.net
> *Sent:* Monday, March 14, 2011 1:39 AM
> *Subject:* Re: Question on Unevaluated

Alexey Popkov

unread,
Mar 15, 2011, 7:07:32 AM3/15/11
to
Leonid,

Thank you for interesting example. I have two quesions regarding your function makeHoldN:

1) It works well in simplest cases even if makeHoldN is called before defining a function:

In[13]:= ClearAll[ff];
makeHoldN[ff,3];
ff[args___]:=Hold[args];
ff[1^2,2^2,3^2]
Out[16]= Hold[1,4,3^2]

Probably conflicts are only possible when the target function has definitions for which Mathematica's rule ordering
system cannot make conclusions about their generality? Does calling makeHoldN after making all definitions always guarantee that the new definition will be on top? How it could be checked?

2) I do not well understand for what

/; Hold[result] =!= Hold[f[args]]]]) /;
FreeQ[DownValues[f], keepOnTop]]

is added. In simple cases makeHoldN works well wihout it.

Alexey
----- Original Message -----

From: Leonid Shifrin
To: Alexey Popkov ; math...@smc.vnet.net
Sent: Monday, March 14, 2011 2:40 PM
Subject: Re: Question on Unevaluated


Alexey,

Doing what you request is generally not possible or at least extremely hard (emulating exact behavior of Unevaluated in all cases), since Unevaluated is one of the "magic symbols" (together with Evaluate and Sequence), wired deep into the system. I discuss this a bit more here:

http://stackoverflow.com/questions/4856177/preventing-evaluation-of-mathematica-expressions/4856721#4856721

f[1, 2^2, 9]

HTH

Regards,
Leonid

Leonid,

?

Alexey


----- Original Message -----
From: Leonid Shifrin
To: Alexey ; math...@smc.vnet.net

Leonid Shifrin

unread,
Mar 16, 2011, 7:30:05 AM3/16/11
to
Alexey,

I have two quesions regarding your function makeHoldN:
>
> 1) It works well in simplest cases even if makeHoldN is called before
> defining a function:
>
> In[13]:= ClearAll[ff];
> makeHoldN[ff,3];
> ff[args___]:=Hold[args];
>
> ff[1^2,2^2,3^2]
> Out[16]= Hold[1,4,3^2]
>
> Probably conflicts are only possible when the target function has
> definitions for which Mathematica's rule ordering
> system cannot make conclusions about their generality?
>

Yes. Those may end up sitting on top of that added by makeHoldN. The problem
for them will be not only that
calls matching their patterns will not be intercepted, but also that they
will still be evaluated with HoldAll
attribute, which may not be desirable/intended (makeHoldN effectively
releases all arguments except n-th).


> Does calling makeHoldN after making all definitions always guarantee that
> the new definition will be on top?
>


Actually, I made a mistake in that statement - the call must be the first
one, not the last one - sorry about that.
In fact, this is good, since it is always better to set Attributes before we
make definitions, especially for Hold-
attributes. Otherwise, quite often some definitions partially evaluate
during the time they are entered (because Set and SetDelayed partially
evaluate the l.h.s., I think contrary to some statements in the docs), which
may result in very subtle bugs. Regarding the guarantees - I can not give
them, but as far as I know, yes, the new definition will be on top, except
possibly for definitions containing neither patterns nor conditions, such
as memoized definitions like HoldPattern[f[2]]:>4 - they will be higher in
the list. There is a way to force these to also go below the one added by
makeHoldN - for example, when you create them, add a dummy condition like
HoldPattern[f[2]]:>4 /;(someSymbol;True). This will however negatively
impact the performance - without conditions such no-pattern definitions are
stored in a hash table and are (much) more efficient. But, anyway, this is a
rather special case.


> How it could be checked?
>

Well, you can always query the function information with ? and see the order
of the definitions. If your question
is how to ensure the generality of this behavior - I don't know, but I use
this kind of tricks routinely and had no
problems with this. An informal proof of this behavior can go along these
lines:

1. It is necessarily impossible for the Mathematica's rule-ordering system
to determine relative generality of 2 rules where at least one contains a
condition attached, with a user-defined symbol. The reason is that the fact
of the match of such a rule depends on the global state and can only be
determined at run-time.

2. When Mathematica can not determine the relative generality of some rules,
it keeps them in the order they were entered - I think this statement can be
found in the documentation somewhere.

I do not exclude the possibility for some exceptions, but generally this
should work and my experience confirms that.


>
> 2) I do not well understand for what
>
> /; Hold[result] =!= Hold[f[args]]]]) /;
> FreeQ[DownValues[f], keepOnTop]]
>
> is added. In simple cases makeHoldN works well wihout it.
>

Indeed, the line Hold[result] =!= Hold[f[args]] can be left out - this is a
remnant of my intermediate implementation.
But the reason that we can do this appears quite subtle. Once the function
(say f[1^2,2^2,3^2]) computes into
f[1,2^2,9], a new attempt to compute f is of course made. But now, it is
made from within the Block scope, and
the definition does not match since keepOnTop is now False. The non-trivial
part here is that the new evaluation
is not attempted after we leave the Block scope - this is why there is no
infinite recursion. I think that this, more
subtle part of the trick, I did not realize before (this looks different
from the version of the trick with overloading
the built-ins, where the system definitions *are* used even when the
function ends up being returned "unevaluated" - say due to unknown number
and/or types of arguments).

The line FreeQ[DownValues[f], keepOnTop]] is needed to not add a new
definition more than once.

Regards,
Leonid

>
> Alexey
>
> ----- Original Message -----

> *From:* Leonid Shifrin <lsh...@gmail.com>

> *To:* Alexey Popkov <leh...@gmail.com> ; math...@smc.vnet.net
> *Sent:* Monday, March 14, 2011 2:40 PM
> *Subject:* Re: Question on Unevaluated

>> *From:* Leonid Shifrin <lsh...@gmail.com>
>> *To:* Alexey <leh...@gmail.com> ; math...@smc.vnet.net

>> *Sent:* Monday, March 14, 2011 1:39 AM
>> *Subject:* Re: Question on Unevaluated

Alexey Popkov

unread,
Mar 16, 2011, 7:30:16 AM3/16/11
to
Leonid,

It seems that DownValues can help to ensure that new definition will be on top:

DownValues[f] = Prepend[DownValues[f], < new pattern >];


The non-trivial part here is that the new evaluation
is not attempted after we leave the Block scope - this is why there is no infinite recursion. I think that this, more
subtle part of the trick

Very interesting! I do not understand why this happens at all. How does it work? Is there a way to generalize this for preventing infinite recursion in arbitrary case, say classical
x=x+1
?

Alexey


----- Original Message -----
From: Leonid Shifrin
To: Alexey Popkov ; math...@smc.vnet.net

Sent: Wednesday, March 16, 2011 2:49 AM
Subject: Re: Question on Unevaluated


Alexey,


I have two quesions regarding your function makeHoldN:

1) It works well in simplest cases even if makeHoldN is called before defining a function:

In[13]:= ClearAll[ff];
makeHoldN[ff,3];
ff[args___]:=Hold[args];

ff[1^2,2^2,3^2]

Out[16]= Hold[1,4,3^2]

Probably conflicts are only possible when the target function has definitions for which Mathematica's rule ordering
system cannot make conclusions about their generality?

Yes. Those may end up sitting on top of that added by makeHoldN. The problem for them will be not only that
calls matching their patterns will not be intercepted, but also that they will still be evaluated with HoldAll
attribute, which may not be desirable/intended (makeHoldN effectively releases all arguments except n-th).

Does calling makeHoldN after making all definitions always guarantee that the new definition will be on top?


Actually, I made a mistake in that statement - the call must be the first one, not the last one - sorry about that.
In fact, this is good, since it is always better to set Attributes before we make definitions, especially for Hold-

attributes. Otherwise, quite often some definitions partially evaluate during the time they are entered (because Set and SetDelayed partially evaluate the l.h.s., I think contrary to some statements in the docs), which may result in very subtle bugs. Regarding the guarantees - I can not give them, but as far as I know, yes, the new definition will be on top, except possibly for definitions containing neither patterns nor conditions, such as memoized definitions like HoldPattern[f[2]]:>4 - they will be higher in the list. There is a way to force these to also go below the one added by make HoldN - for example, when you create them, add a dummy condition like HoldPattern[f[2]]:>4 /;(someSymbol;True). This will however negatively impact the performance - without conditions such no-pattern definitions are stored in a hash table and are (much) more efficient. But, anyway, this is a rather special case.



How it could be checked?

Well, you can always query the function information with ? and see the order of the definitions. If your question
is how to ensure the generality of this behavior - I don't know, but I use this kind of tricks routinely and had no
problems with this. An informal proof of this behavior can go along these lines:

1. It is necessarily impossible for the Mathematica's rule-ordering system to determine relative generality of 2 rules where at least one contains a condition attached, with a user-defined symbol. The reason is that the fact of the match of such a rule depends on the global state and can only be determined at run-time.

2. When Mathematica can not determine the relative generality of some rules, it keeps them in the order they were entered - I think this statement can be found in the documentation somewhere.

I do not exclude the possibility for some exceptions, but generally this should work and my experience confirms that.

2) I do not well understand for what

/; Hold[result] =!= Hold[f[args]]]]) /;
FreeQ[DownValues[f], keepOnTop]]

is added. In simple cases makeHoldN works well wihout it.

Indeed, the line Hold[result] =!= Hold[f[args]] can be left out - this is a remnant of my intermediate implementation.
But the reason that we can do this appears quite subtle. Once the function (say f[1^2,2^2,3^2]) computes into
f[1,2^2,9], a new attempt to compute f is of course made. But now, it is made from within the Block scope, and
the definition does not match since keepOnTop is now False. The non-trivial part here is that the new evaluation

is not attempted after we leave the Block scope - this is why there is noinfinite recursion. I think that this, more


subtle part of the trick, I did not realize before (this looks different from the version of the trick with overloading
the built-ins, where the system definitions *are* used even when the function ends up being returned "unevaluated" - say due to unknown number and/or types of arguments).

The line FreeQ[DownValues[f], keepOnTop]] is needed to not add a new definition more than once.

Regards,
Leonid

Alexey
----- Original Message -----

From: Leonid Shifrin
To: Alexey Popkov ; math...@smc.vnet.net


Alexey,

http://stackoverflow.com/questions/4856177/preventing-evaluation-of-mathematica-expressions/4856721#4856721

f[1, 2^2, 9]

One that needs a bit of clarification is the f[args___] /; (! TrueQ[!keepOnTop]) line, since it serves


2 purposes. The one related to Block trick is well-known to you. The other is that the presence of
condition involving a user-defined symbol makes it impossible for Mathematica rule ordering
system to make conclusions about the generality of the rule, and therefore the rule does not go
to the bottom of the rule list. This is needed because we want this rule to stay at the top, to intercept
all calls to the function. For the same reason, makeHoldN should be called already after all the
definitions have been given to the function, or the function will not work properly.

As you see, this is sort of possible, but complex and error-prone. In practice, it is best to avoid
this sort of trickery, by changing the design of your functions. In my experience, having HoldFirst,
HoldRest and HoldAll is quite enough. To evaluate any held argument, you can also wrap it in
Evaluate. So, you particular question can be answered quite easily also as

SetAttributes[f,HoldAll];
f[Evaluate[Print[1]], Print[2], Evaluate[Print[3]]]

Note also, that I don't claim to reproduce exactly the behavior of Unevaluated with my function above.
It is just an illustration of a possible poor man's device to accomplish the specific goal of holding
n-th argument without the help of Evaluate and Unevaluated.

HTH

Regards,
Leonid

On Mon, Mar 14, 2011 at 1:06 AM, Alexey Popkov <leh...@gmail.com> wrote:

Leonid,

Is it possible to imitate the behavior of Unevaluated by setting At tributes in this case:

f[Print[1], Unevaluated[Print[2]], Print[3]]

?

I am wondering, what attributes are temporarily set when we use Unevaluated and how could I imitate this?

Alexey


----- Original Message -----
From: Leonid Shifrin
To: Alexey ; math...@smc.vnet.net

Leonid Shifrin

unread,
Mar 17, 2011, 7:32:06 AM3/17/11
to
Alexey,


> It seems that DownValues can help to ensure that new definition will be on
> top:
>
> DownValues[f] = Prepend[DownValues[f], < new pattern >];
>

Yes, sure, direct manipulations with the DownValues are always an option. I
just prefer to not do this
when it is not necessary, and in our context I believe it is not.


>
> Very interesting! I do not understand why this happens at all. How does it
> work?
>

This must have been a design decision. This also has to do with the
semantics of both Block
(dynamic scoping) and local variables shared between the body and the
condition. My feeling is that
this is a unique language feature, in the sense that it can not be easily
reproduced or imitated
by other means.


> Is there a way to generalize this for preventing infinite recursion in
> arbitrary case, say classical
> x=x+1
> ?
>

Well, this particular one is easy, and you know the trick already:

In[19]:= Clear[x];
Module[{tried}, x := Block[{tried = True}, x + 1] /; ! TrueQ[tried]]

In[21]:= x

Out[21]= 1 + x

Cheers,

Alexey Popkov

unread,
Mar 17, 2011, 7:33:57 AM3/17/11
to
Leonid,

This must have been a design decision. This also has to do with the semantics of both Block
(dynamic scoping) and local variables shared between the body and the condition. My feeling is that
this is a unique language feature, in the sense that it can not be easily reproduced or imitated
by other means.

It seems that the reason is that the evaluator just does not leave Block scope at all:

In[1]:= Clear[x];


x := Block[{tried = True}, x + 1] /; ! TrueQ[tried]

x /; ! TrueQ[tried] := x + 1
x
x /; TrueQ[tried] := x + 1
x

Out[4]= 1 + x

During evaluation of In[1]:= $RecursionLimit::reclim: Recursion depth of 256 exceeded. >>

Out[6]= 254 +
Hold[RuleCondition[$ConditionHold[$ConditionHold[
Block[{tried = True}, x + 1]]], ! TrueQ[tried]]]

This means that the evaluation is completed inside Block. It is unexpected for me. For what aims have the developers created such a peculiarity? In which cases it can be useful? Is Block unique in this sense?


From: Leonid Shifrin
To: Alexey Popkov ; math...@smc.vnet.net
Sent: Thursday, March 17, 2011 4:02 AM
Subject: Re: Re: Question on Unevaluated


Alexey,

It seems that DownValues can help to ensure that new definition will beon top:

In[21]:= x

Cheers,
Leonid


Alexey

To: Alexey Popkov ; math...@smc.vnet.net


Alexey,

ff[1^2,2^2,3^2]

attributes. Otherwise, quite often some definitions partially evaluateduring the time they are entered (because Set and SetDelayed partially evaluate the l.h.s., I think contrary to some statements in the docs), which may result in very subtle bugs. Regarding the guarantees - I can not give them, but as far as I know, yes, the new definition will be on top, except possibly for definitions containing neither patterns nor conditions, such as memoized definitions like HoldPattern[f[2]]:>4 - they will be higher in the list. There is a way to force these to also go below the one added by make HoldN - for example, when you create them, add a dummy condition like HoldPattern[f[2]]:>4 /;(someSymbol;True). This will however negatively impact the performance - without conditions such no-pattern definitions are stored in a hash table and are (much) more efficient. But, anyway, this is a rather special case.


How it could be checked?

Well, you can always query the function information with ? and see theorder of the definitions. If your question

Regards,
Leonid


Alexey,

http://stackoverflow.com/questions/4856177/preventing-evaluation-of-mathematica-expressions/4856721#4856721

f[1, 2^2, 9]

HTH

Regards,
Leonid

Leonid,

?

Alexey


Alexey,

The problem is that Unevaluated is only effective once. To toally prevent something from evaluation,

Leonid Shifrin

unread,
Mar 18, 2011, 6:59:16 AM3/18/11
to
Alexey,

Was about to answer when I saw your analogous question of stackoverflow, so,
as you know,
I placed the answer there. For the record, the link is

http://stackoverflow.com/questions/5337026/how-mathematica-determines-that-evaluation-should-be-finished

Generally, these things are very interesting and possibly useful. One of the
most useful things
about the shared local variables is IMO the ability to break from infinite
recursion or iteration
and return some function unevaluated, even after some evaluation has been
actually attempted
- which is also what we were discussing here. With the Block trick, I can
imagine there can be
more possibilities, but I am not ready at the moment to offer a useful
example. One thing I find
very useful about the Block is that it allows for (non-local in a way) ways
of evaluation control
which are completely different from the normally used ones (those based on
Hold attributes,
Evaluate, Unevaluated etc). I can imagine that shared local variables can
find their place in that
scheme to help achieve something non-trivial.

Cheers,
Leonid

magma

unread,
Mar 18, 2011, 6:59:48 AM3/18/11
to

> In[19]:= Clear[x];
> Module[{tried}, x := Block[{tried = True}, x + 1] /; ! TrueQ[tried]]

This kind of trick seems to me a bit problematic.
It is true that it works in this case:

In[45]:= x

Out[45]= 1 + x

and also works with

In[54]:= x + a

Out[54]= 1 + a + x


but if you just slightly change the input, it stops working:

In[55]:= x + 2

During evaluation of In[55]:= $IterationLimit::itlim: Iteration limit
of 4096 exceeded. >>

Out[55]= Hold[4097 + x]

Any suggestions why is that?


0 new messages