Tell me more ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I need to use If but with only one option that is if "a" then do "b", else do nothing. So I wrote If[a,b] but the problem is that if it is not a it returns Null in my output. How to avoid this?

Here is the specific example I was working on.

I am looking for the number of comparisons performed by the quick sort algorithm. Here is the code from Rosetta code with my additions

QuickSort[x_List] := 
 Module[{pivot, aa = 0, bb = 0}, If[Length@x <= 1, Return[x]];
  pivot = First[x];
  aa = If [Length[Cases[x, j_ /; j < pivot]] > 1, 
    Length[Cases[x, j_ /; j < pivot]] - 1 , Sequence[]];
  bb = If [Length[Cases[x, j_ /; j < pivot]] > 1, 
    Length[Cases[x, j_ /; j > pivot]] - 1 , Sequence[]]; 
  count = count + aa + bb;
  Flatten@{QuickSort[Cases[x, j_ /; j < pivot]], 
    Cases[x, j_ /; j == pivot], 
    QuickSort[Cases[x, j_ /; j > pivot]]} ; Return[count] ]

now if you run QuickSort[{4, 3, 2, 1, 5}] you will get 2+2 Null instead of 4

share|improve this question
3  
What is the problem with that, returning Null is usually no problem, the FrontEnd will usually not even create an output cell for that return value... – Albert Retey Mar 30 '12 at 8:43
ok i my case i could just add 0, in the "else" case. but i wonder why proposal of "kguler" and "ruebenko" that i also tested didn't work in my case – Raph Mar 30 '12 at 9:33
And welcome to Mathematica.SE! – Sjoerd C. de Vries Mar 30 '12 at 17:09
possible duplicate of How to "ignore" an element of Map or MapIndexed – rm -rf Mar 30 '12 at 19:46
@R.M looks like a duplicate to me, also, yet this is likely to be the one searched for. – rcollyer Mar 31 '12 at 3:23

5 Answers

up vote 8 down vote accepted

It depends what you consider nothing, but you could try something like this

If[a, b, Unevaluated[Sequence[]]]

for example

3 + If[False, 1, Unevaluated[Sequence[]]]

returns 3. Wrapping an argument of a function in Unevaluated is effectively the same as temporarily setting the attribute Hold for that argument meaning that the argument isn't evaluated until after it's inserted in the definition of that function.

By the way, in your definition of QuickSort you're calling Cases[x, j_ /; j < pivot] six times. It's probably more efficient to assign Cases[x, j_ /; j < pivot] to a dummy variable and use that instead.

share|improve this answer
Cases[x, j_ /; j < pivot] 4 times, Cases[x, j_ /; j == pivot] and Cases[x, j_ /; j > pivot] each once. But, a variable is definitely needed. – rcollyer Mar 30 '12 at 11:24
@rcollyer you're right, I was a bit hasty in scanning the code. – Heike Mar 30 '12 at 11:36

If does not have the attribute SequenceHold; use the "vanishing function" ##&[] instead of Sequence[]:

If[# > 5, #, ## &[]] & /@ Range[10]
{6, 7, 8, 9, 10}

See this and this for other uses, and SlotSequence if you are confused by ##.

share|improve this answer
If you look at it with Trace, you will see that you are just hiding it: If[# > 5, #, ## &[]] & /@ Range[10] // Trace. In have a year you will not remember what your code does. – ruebenko Mar 30 '12 at 10:24
3  
@ruebenko I really don't understand what you are trying to say. Using & effectively prevents (holds) evaluation in If. In a year I most certainly will remember what this code does, barring traumatic brain injury. What's your point? – Mr.Wizard Mar 30 '12 at 10:28
I have the feeling this is in essence replacing the Null with a Sequence; and subjectively makes it harder to read. – ruebenko Mar 30 '12 at 12:24
@ruebenko re: "in essence replacing the Null with a Sequence" -- isn't that the idea? The OP has If[. . ., Sequence[]] but it undesirably evaluates to If[. . ., Null]. Using ##&[] fixes it. What am I still missing? – Mr.Wizard Mar 30 '12 at 12:50
you are not missing anything - I just find that neither Null nor Sequence should be inserted into the list. I find If[cond, a=result]; a cleaner (a little off the track: it can work with packed arrays). That's all I am trying to say. – ruebenko Mar 30 '12 at 13:00

I note that all answers so far try to solve the problem of assigning a potential Null value by manipulating the return value. I feel it would be more appropriate to make the whole assignment conditional. Like this:

If[condition, aa = value]

There's also a small bug in your program (count isn't initialized), and, of course, it doesn't sort at the moment. I assume that you aware of that and that the Return value is used for testing.

The code would then be:

QuickSort[x_List] := 
 Module[{pivot, aa = 0, bb = 0, count = 0}, 
  If[Length@x <= 1, Return[x]];
  pivot = First[x];
  If[Length[Cases[x, j_ /; j < pivot]] > 1,
     aa = Length[Cases[x, j_ /; j < pivot]] - 1
  ];
  If[Length[Cases[x, j_ /; j < pivot]] > 1, 
     bb = Length[Cases[x, j_ /; j > pivot]] - 1
  ];
  count = count + aa + bb;
  Flatten@{QuickSort[Cases[x, j_ /; j < pivot]], 
    Cases[x, j_ /; j == pivot], QuickSort[Cases[x, j_ /; j > pivot]]};
   Return[count]] 

Remove ;Return[count] to let it sort again.

I'm not sure about the j < pivot test in the second If. It depends on your intention with bb, but I guess the test should be j > pivot.

share|improve this answer

The semantics for if is If[cond,t,f] if f (False) is not given Null is returned.

I am guessing that you need this in a pattern, then you can use Condition:

f[x_] := ppp[x] /; x > 0
f[5]
f[-6]

OK, here is a different version of quick sort (I found on my disk - I am not sure how the author is...)

ClearAll[quickSort1]
quickSort1[lst0_] := 
 Block[{left, right, pivot, lst, $RecursionLimit = 10^6},
  pivot = First[lst0];
  lst = Rest[lst0];
  left = Select[lst, # <= pivot &];
  If[left =!= {}, left = quickSort1[left]];
  right = Select[lst, # > pivot &];
  If[right =!= {}, right = quickSort1[right]];
  Join[left, {pivot}, right]
  ]

If someone feels like adding the counter... my brain feels like gum this morning... please go ahead. The point in the above code is to not use the return value of If but to set it to a variable.

share|improve this answer

In Mathematica, “not returning anything” is not possible. An expression that does not return anything has a value of Null, even though you only actually see this Null in certain circumstances:

Null
    is a symbol used to indicate the absence of an expression or a result. It is not displayed in ordinary output.

When Null appears as a complete output expression, no output is printed.

So, Null is always returned, but whether it's displayed depend on what you do with this returned value. For example:

In[1]:= If[x > 0, 1]; /. x -> -1
(* nothing is output *)
In[2]:= {If[x > 0, 1]; /. x -> -1, 42}
Out[2]= {Null, 42}
share|improve this answer

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.