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.

When evaluating functions, including those described in this post, how do Mathematica users handle values returned from a function that are unevaluated? For example (based on 1):

i[{a_, Longest[b__], c__}] := {"a" -> a, "b" -> {b}, "c" -> {c}} /; Length[{a, b, c}] > 3;
test = {{1, 2}, {1, 2, 3, 4, 5}, {1, 2, 3, 4, 5}};
j=i/@test

(* returns {i[{1, 2}], {"a" -> 1, "b" -> {2, 3, 4}, "c" -> {5}}, {"a" -> 1,  "b" -> {2, 3, 4}, "c" -> {5}}}  *)

So the first element of j is i[{1, 2}] - this is neither the original input {1,2} nor in the form of the rest of the output. Two questions:

a) While it is likely to be application specific, what approaches do others use to handle unevaluated values that are returned?

b) Is there a generic way to detect unevaluated 'returns' for additional parsing ?

My current thought is to use Identity and ReplaceAll to eliminate the 'unwanted' function i:

k=j/.i->Identity
(* returns {{1, 2}, {"a" -> 1, "b" -> {2, 3, 4}, "c" -> {5}}, {"a" -> 1,   "b" -> {2, 3, 4}, "c" -> {5}}}  *)

but this approach requires the name of the function (here i) that was evaluated. Are there any other tricks or approaches to handle this? Am I overlooking benefits to retaining the unevaluated output ?

share|improve this question

2 Answers 2

up vote 2 down vote accepted

The only "correct way" is to do what is reasonable for your application. Depending on the use/needs, you have a few options (not an exhaustive list):

  • If you know your input is all going to be of a certain type (e.g. lists), you can tighten your patterns so that you don't end up with invalid input (or what you call "unevaluated output")

    Clear@i1
    i1[{a_, Longest[b__], c__}] := {"a" -> a, "b" -> {b}, "c" -> {c}} /; Length[{a, b, c}] > 3;
    i1[c : {___}] := "Too short" /; Length[c] <= 3;
    i1 /@ test
    (* {"Too short", {"a" -> 1, "b" -> {2, 3, 4}, "c" -> {5}}, {"a" -> 1, "b" -> {2, 3, 4}, "c" -> {5}}} *)
    

    Here the assumption is that "Too short" means something to your application... it could very well be Sequence[].

  • If you don't know what kind of input will be supplied, you can add a down-value/pattern that acts as a default or a fall through pattern. This is generally a good thing to do.

    Clear@i2
    i2[{a_, Longest[b__], c__}] := {"a" -> a, "b" -> {b}, "c" -> {c}} /; 
       Length[{a, b, c}] > 3;
    i2[___] := "Too short";
    i2 /@ test
    (* {"Too short", {"a" -> 1, "b" -> {2, 3, 4},  "c" -> {5}}, {"a" -> 1, "b" -> {2, 3, 4}, "c" -> {5}}} *)
    
  • If you know a priori what type of terms you want or don't want, you can either selectively choose the items or prune the output to get rid of the undesirable terms.

    Cases[i /@ test, {__Rule}]
    (* {{"a" -> 1, "b" -> {2, 3, 4}, "c" -> {5}}, {"a" -> 1,  "b" -> {2, 3, 4}, "c" -> {5}}} *)
    
    i /@ test /. _i -> Sequence[]
    (* {{"a" -> 1, "b" -> {2, 3, 4}, "c" -> {5}}, {"a" -> 1,  "b" -> {2, 3, 4}, "c" -> {5}}} *)
    

    As I said, this is only useful if you have some knowledge of the structure (you often do).

  • Throw an error or a message.

    Clear@i3
    i3::invalid = "Invalid entry!";
    i3[{a_, Longest[b__], c__}] := {"a" -> a, "b" -> {b}, "c" -> {c}} /; Length[{a, b, c}] > 3;
    i3[___] /; Message[i3 : invalid] := Null;
    i3 /@ test
    

    Message::name: Message name i3:invalid is not of the form symbol::name or symbol::name::language. >>

    (* {i3[{1, 2}], {"a" -> 1, "b" -> {2, 3, 4}, "c" -> {5}}, {"a" -> 1, "b" -> {2, 3, 4}, "c" -> {5}}} *)
    
  • Do nothing. (The implicit assumption is that you either don't care or a subsequent step will handle it correctly.)

share|improve this answer
    
Many thanks, I learned a lot. –  PlaysDice Feb 4 at 1:25

Perhaps something like ValueQ[i[#]] & /@ test which returns a vector corresponding the the results being "real" might be of use?

share|improve this answer
1  
thanks. ValueQ is a new one for me. According to reference.wolfram.com/mathematica/ref/ValueQ.html Possible Issues, ValueQ returns True in the case where the value passed is outside the limit, so I dont think it will work –  PlaysDice Feb 1 at 0:43
1  
@PlaysDice:Yes, I assumed your "unevaluated" meant globally. Perhaps combined with rm-rf's excellent suggestions it might still be of use. –  rasher Feb 1 at 0:53

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.