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

Do we need a When function?

129 views
Skip to first unread message

David Bailey

unread,
Mar 8, 2014, 2:42:24 AM3/8/14
to
Dear All,

Recently I wanted to create an expression that only evaluated when x was
a number. Obviously, one way to do that is to write something like:

If[x<1000000000000,f[x]]

This will stay unevaluated until x is assigned to a number - as required
- but it is very ugly because it makes it hard to understand what is
going on.

More generally, it would be nice to write an expression that will only
evaluate when an expression is true. I solved that by writing a function
When:

SetAttributes[When, HoldAll];
When[cond_, val_] := val /; cond

However, my point is that this construction is sufficiently useful that
it should be built in to Mathematica, and my solution might not be
obvious to all users.

Am I missing a simpler solution?

Do others agree that this is an omission in the language?

David Bailey
http://www.dbaileyconsultancy.co.uk

Itai Seggev

unread,
Mar 10, 2014, 4:37:32 AM3/10/14
to
On Sat, Mar 08, 2014 at 02:42:31AM -0500, David Bailey wrote:
> Dear All,
>
> Recently I wanted to create an expression that only evaluated when x was
> a number. Obviously, one way to do that is to write something like:
>
> If[x<1000000000000,f[x]]
>
> This will stay unevaluated until x is assigned to a number - as required
> - but it is very ugly because it makes it hard to understand what is
> going on.

Why isn't this simply

If[NumericQ[x], f[x]] (*are NumberQ, if want an actual number type*)

But I'm further confused by your statement that it stays unevlauate until x is
assigned a number. That's not true, it will evaluate to Null unless x is
numeric prior to the start of evaluation.

> More generally, it would be nice to write an expression that will only
> evaluate when an expression is true. I solved that by writing a function
> When:
>
> SetAttributes[When, HoldAll];
> When[cond_, val_] := val /; cond
>
> However, my point is that this construction is sufficiently useful that
> it should be built in to Mathematica, and my solution might not be
> obvious to all users.
>
> Am I missing a simpler solution?
>
> Do others agree that this is an omission in the language?

I'm not sure what your use case is. F[x] will of course stay unevluated until
x has some value which F knows what to do with...

--
Itai Seggev
Mathematica Algorithms R&D
217-398-0700

Szabolcs Horvát

unread,
Mar 10, 2014, 4:38:12 AM3/10/14
to
I see where you are coming from with this.

I think this comes up most often in cases like this:

http://support.wolfram.com/kb/3820

When[] would make it unnecessary to define a separate function.

However one might argue that in situations like this it is better
practice to define that function anyway, if not for anything else then
just for structuring the code better (which could avoid errors).

Do you see other common use cases for it?


Bob Hanlon

unread,
Mar 10, 2014, 4:40:54 AM3/10/14
to

You can use PatternTest ( p?test ) or Condition ( patt /; test )


Clear[f1, f2, f3, f4]


f1[x_?NumericQ] = "success";


f1 /@ {x, 1, Pi, Infinity}


{f1[x], "success", "success", f1[=E2=88=9E]}


f2[x_?(NumericQ[#] &)] = "success";


f2 /@ {x, 1, Pi, Infinity}


{f2[x], "success", "success", f2[=E2=88=9E]}


f3[x_ /; NumericQ[x]] = "success";


f3 /@ {x, 1, Pi, Infinity}


{f3[x], "success", "success", f3[=E2=88=9E]}


f4[x_] := "success" /; NumericQ[x];


f4 /@ {x, 1, Pi, Infinity}


{f4[x], "success", "success", f4[=E2=88=9E]}


The tests or conditions can be any expression that evaluates to True or
False.



Bob Hanlon




On Sat, Mar 8, 2014 at 2:42 AM, David Bailey <da...@removedbailey.co.uk>wrote:

> Dear All,
>
> Recently I wanted to create an expression that only evaluated when x was
> a number. Obviously, one way to do that is to write something like:
>
> If[x<1000000000000,f[x]]
>
> This will stay unevaluated until x is assigned to a number - as required
> - but it is very ugly because it makes it hard to understand what is
> going on.
>
> More generally, it would be nice to write an expression that will only
> evaluate when an expression is true. I solved that by writing a function
> When:
>
> SetAttributes[When, HoldAll];
> When[cond_, val_] := val /; cond
>
> However, my point is that this construction is sufficiently useful that
> it should be built in to Mathematica, and my solution might not be
> obvious to all users.
>
> Am I missing a simpler solution?
>
> Do others agree that this is an omission in the language?
>
> David Bailey
> http://www.dbaileyconsultancy.co.uk
>

Helen Read

unread,
Mar 10, 2014, 4:41:35 AM3/10/14
to
Use NumberQ

For example:

f[x_?NumberQ] := x^3

Helen Read
University of Vermont

David Bailey

unread,
Mar 11, 2014, 3:17:09 AM3/11/14
to
Well my particular use was to stop a ToString expression evaluating
before the argument to ToString is a number.

There are obviously ways to solve this problem, just as there are ways
to substitute for many Mathematica functions - such as Riffle - but it
seems like the sort of function that could make code clearer to
understand - it surprised me that it doesn't exist!

David Bailey
http://www.dbaileyconsultancy.co.uk


Szabolcs Horvát

unread,
Mar 11, 2014, 3:17:50 AM3/11/14
to
Hello Itai,

What (I believe) David means is that

If[NumericQ[x], f[x]]

immediately evaluates to Null if the symbol x has no assigned value.
When[NumericQ[x], f[x]] does not evaluate in this case, so later you can
substitute in a number for x and have f[x] evaluate correctly in case
f[x] only works with numbers, not symbols.

Then you could do something like

FindRoot[
When[NumericQ[a], First@FindMaximum[Exp[-a x] x^2, {x, 1}] - 0.5],
{a, 1}
]

without having to go to the trouble of defining

f[a_?NumericQ] := First@FindMaximum[Exp[-a x] x^2, {x, 1}]

first, and keeping in mind that the symbol f is defined (or Clear[]ing
it afterwards). This is potentially convenient when f would really be a
one-time use function.

Szabolcs

P.S. Personally I am not convinced that When[] is necessary, but I felt
the need to clarify since most responders seem to have missed the point
of the suggestion.


David Bailey

unread,
Mar 13, 2014, 3:11:27 AM3/13/14
to
On 10/03/2014 08:37, Itai Seggev wrote:> On Sat, Mar 08, 2014 at 02:42:31AM
>
> I'm not sure what your use case is. F[x] will of course stay
unevluated until
> x has some value which F knows what to do with...
>
> --
> Itai Seggev
> Mathematica Algorithms R&D
> 217-398-0700
>
A typical use would be an expression like When[NumberQ[x],ToString[x]]

Somehow everyone seems to be missing the point here - of course I can
solve the problem by writing some code - indeed I gave a solution in my
original post - but lots of Mathematica functions can be replaced by
other expressions using more primitive functions, but such functions are
provided for convenience and expressiveness.

Supplying an expression that only evaluates when some condition is true,
seems a pretty useful feature.

The difference between If and When, is obvious:

If[NumberQ[x],f[x]]
Null



When[NumberQ[x],f[x]]

When[NumberQ[x],f[x]]

When delays evaluation until is condition is True.

If you want to hold an expression until (and unless) some condition is
satisfied, When would seem to me to be the most expressive way to write
this.

David Bailey
http://www.dbaileyconsultancy.co.uk




Itai Seggev

unread,
Mar 15, 2014, 3:51:11 AM3/15/14
to
On Thu, Mar 13, 2014 at 03:10:50AM -0400, David Bailey wrote:
> On 10/03/2014 08:37, Itai Seggev wrote:> On Sat, Mar 08, 2014 at 02:42:31AM
> >
> > I'm not sure what your use case is. F[x] will of course stay
> unevluated until
> > x has some value which F knows what to do with...
> >
> > --
> > Itai Seggev
> > Mathematica Algorithms R&D
> > 217-398-0700
> >
> A typical use would be an expression like When[NumberQ[x],ToString[x]]

That isn't very illuminating to me. More below...

> Somehow everyone seems to be missing the point here - of course I can
> solve the problem by writing some code - indeed I gave a solution in my
> original post - but lots of Mathematica functions can be replaced by
> other expressions using more primitive functions, but such functions are
> provided for convenience and expressiveness.
> Supplying an expression that only evaluates when some condition is true,
> seems a pretty useful feature.
>
> The difference between If and When, is obvious:
>
> If[NumberQ[x],f[x]]
> Null
>
> When[NumberQ[x],f[x]]
>
> When[NumberQ[x],f[x]]
>
> When delays evaluation until is condition is True.

Of course. But in fairness, the source of the confusion for me (and perhaps
others) is that you confused the issues in your original email.
--------------------------------------------------------------------------------
> Obviously, one way to do that is to write something like:
>
> If[x<1000000000000,f[x]]
>
> This will stay unevaluated until x is assigned to a number - as required
> - but it is very ugly because it makes it hard to understand what is
> going on.

Why isn't this simply

If[NumericQ[x], f[x]] (*are NumberQ, if want an actual number type*)

But I'm further confused by your statement that it stays unevlauate until x is
assigned a number. That's not true, it will evaluate to Null unless x is
numeric prior to the start of evaluation.
--------------------------------------------------------------------------------
You'll notice you claimed you could acheive what you wanted with If, and then I
point out the difference between If and When.

> If you want to hold an expression until (and unless) some condition is
> satisfied, When would seem to me to be the most expressive way to write
> this.

I still don't understand what your use case is. I agree that When has the
properties stated in your most recent email. But these expressions won't
magically transform themselves. You'll have to reevaluate them from scratch:

In[22]:= ClearAll[When]
SetAttributes[When, HoldAllComplete]
When[cond_, expr_] := expr /; cond

In[25]:= f = When[NumberQ[x], ToString[x]]
Out[25]= When[NumberQ[x], ToString[x]]

In[26]:= x = 5
Out[26]= 5

In[27]:= f
Out[27]= When[NumberQ[x], ToString[x]]

In[28]:= When[NumberQ[x], ToString[x]]
Out[28]= "5"

Okay, so you can define f using SetDelayed and then it would be reevaluate each
time. But then you could have just as easily written f[x_] /; NumberQ[x] :=
ToString[x].

So is your claim that for interactive use, having f evaluate to the explict
condition statement is more useful than simply returning unevluated? I can see
that, but I personally don't feel I have been missing such functionality.

Note also that for interactive use Dynamic may be a better choice, as it will
instantly update (although I suppose it won't actually show the conditions
ever, so may not be what you're looking for).

I hope this helps.

David Bailey

unread,
Mar 17, 2014, 2:27:10 AM3/17/14
to
On 15/03/2014 07:51, Itai Seggev wrote:

>
> If[NumericQ[x], f[x]] (*are NumberQ, if want an actual number type*)
>

The difference, which at least Szabolcs appreciates, can be seen in this
example:

In[3]:= expr = If[NumericQ[x], ToString[x]]

In[4]:= expr /. x -> 2.1

(* The output here is Null *)

In[7]:= SetAttributes[When, HoldAll];
When[cond_, val_] := val /; cond

In[9]:= expr = When[NumericQ[x], ToString[x]]

Out[9]= When[NumericQ[x], ToString[x]]

In[10]:= expr /. x -> 2.1

Out[10]= "2.1"

The effect of When is to delay its evaluation until something is true -
which can be quite useful!

David Bailey
http://www.dbaileyconsultancy.co.uk





Itai Seggev

unread,
Mar 19, 2014, 4:23:10 AM3/19/14
to
David,

Firstly, I would appreciate it if you didn't quote these tiny fragments of my
replies, which suggest I didn't already understand/address points you raise
(or that perhaps you didn't bother to read my email in its entirety).

> On 15/03/2014 07:51, Itai Seggev wrote:
> > If[NumericQ[x], f[x]] (*are NumberQ, if want an actual number type*)
>
> The difference, which at least Szabolcs appreciates, can be seen in this
> example:
>
> In[3]:= expr = If[NumericQ[x], ToString[x]]
>
> In[4]:= expr /. x -> 2.1
>
> (* The output here is Null *)
>
> In[7]:= SetAttributes[When, HoldAll];
> When[cond_, val_] := val /; cond
>
> In[9]:= expr = When[NumericQ[x], ToString[x]]
>
> Out[9]= When[NumericQ[x], ToString[x]]
>
> In[10]:= expr /. x -> 2.1
>
> Out[10]= "2.1"
>
> The effect of When is to delay its evaluation until something is true -
> which can be quite useful!

But on the other hand you have these behaviors:

In[59]:= ClearAll[When]
SetAttributes[When, HoldAllComplete];
When[cond_, val_] := val /; cond

In[62]:= expr = When[NumericQ[x], ToString[x]]

Out[62]= When[NumericQ[x], ToString[x]]

In[64]:= Block[{x = 2.1}, expr ]

Out[64]= When[NumericQ[x], ToString[x]]

In[65]:= x = 2.1; expr

Out[65]= When[NumericQ[x], ToString[x]]

Are these useful?



David Bailey

unread,
Mar 23, 2014, 5:01:38 AM3/23/14
to
They are not useful - but I didn't define When with Attribute
HoldAllComplete, but with HoldAll - so I don't see your point!

David Bailey
http://www.dbaileyconsultancy.co.uk

Szabolcs Horvát

unread,
Apr 11, 2014, 2:09:56 AM4/11/14
to
On 2014-3-8, 2:42 , David Bailey wrote:
Putting aside the question whether this should be a part of the core
language, I got quite convinced that this is a pretty useful function.
I am saying this one month after David's original post, so this opinion
is based on some practical experience. During this month I found myself
remembering and using this function on a number of occasions. (Not very
often, but it does keep coming back.)

Admittedly, in all cases I used it with NumericQ, so I might as well
have hard-coded NumericQ into it ...

SetAttributes[whenNumeric, HoldRest]
whenNumeric[x_?NumericQ, val_] := val

My point is that it seems that this is going to stay in my personal
toolbox permanently, it is indeed a useful function.


To show an example, most recently I used it while experimenting with
this piecewise function:

http://mathematica.stackexchange.com/q/45763/12

NIntegrate[when[NumericQ[x], First@test[x]], {x, -2, 2}]

test[] is a function that returns a vector here. Its implementation
details are irrelevant for my argument.

Using When here was much easier than defining a separate function only
to allow NIntegrate to be used on the first component of the vector.

This When[] function doesn't allow me to do anything I couldn't do
without it. I wouldn't miss it at all when writing a package. But it
is very useful for quick-and-dirty or "improvisational" programming,
i.e. what I do 90% of the time when I use Mathematica interactively. It
saves me time and effort.

Szabolcs

P.S. One thing that bothers me slightly is that I do not yet see clearly
whether Condition caching might interact badly with this function.




David Bailey

unread,
Apr 13, 2014, 5:26:32 AM4/13/14
to
Thanks for your comments - you seem to be the only person to understand
what this function was designed to do!

I did think about simply writing a whenNumeric function, but I felt sure
there would be occasional other interesting applications. For example:

when[StringQ[x],.....]

I also felt When would be obviously analogous to If.

Since When can be constructed out of Mathematica code, I reckon caching
will not be a problem - at least not in typical cases.

David Bailey
http://www.dbaileyconsultancy.co.uk


0 new messages