0

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 ?

PlaysDice
  • 804
  • 6
  • 11

2 Answers2

2

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.)

rm -rf
  • 88,781
  • 21
  • 293
  • 472
1

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

ciao
  • 25,774
  • 2
  • 58
  • 139
  • 1
    thanks. ValueQ is a new one for me. According to http://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 01 '14 at 00:43
  • 1
    @PlaysDice:Yes, I assumed your "unevaluated" meant globally. Perhaps combined with rm-rf's excellent suggestions it might still be of use. – ciao Feb 01 '14 at 00:53