1
$\begingroup$

To demonstrate my problem, let's create a little function:

fun[var_] := 
 Which[var == "a", {"a", "a"}, var[[1]] == "a", {"a", "b"}]

For the input "a", I expect output {"a", "a"}. That works:

fun["a"]
{"a", "a"}

For input {"a", 3.14} I expect output {"a","b"}. However, what I get back is...

fun[{"a", 3.14}]
Which[{"a", 3.14} == "a", {"a", "a"}, {"a", 3.14}[[1]] == "a", {"a", "b"}]

Note, that if I just copy the last part of the output ({"a", 3.14}[[1]] == "a") and evaluate it myself, I get True. So Mathematica is doing something very weird here, refusing to evaluate its own statement. Namely, it refuses to take a Part [[]] of a list when it's in Which (or If, I tried). This happens even if I very explicitly replace var[[1]] with Part[var,1].

What exactly is going on here and why?

$\endgroup$
6
  • 4
    $\begingroup$ The statement {"a", 3.14} == "a" does not evaluate to True or False; that's why Which doesn't evaluate any further. == (Equal) is for mathematical equations, try using === (SameQ) instead. Or use TrueQ to force an equation to force anything that isn't manifestly True to False. $\endgroup$ Apr 9, 2023 at 20:20
  • $\begingroup$ {"a", 3.14} == "a" returns True on my system. Is it not supposed to? Anyway, triple equal sign works here. $\endgroup$
    – user16320
    Apr 9, 2023 at 20:24
  • $\begingroup$ Second bullet under "Details" of the docs: "If any of the Subscript[test, i] evaluated by Which give neither True nor False, then a Which object containing these remaining elements is returned unevaluated." {"a", 3.14} == "a" gives neither True nor False for me. $\endgroup$
    – Michael E2
    Apr 9, 2023 at 20:35
  • $\begingroup$ Sorry, I wasn't talking about {"a", 3.14}=="a", it was {"a", 3.14`}[[1]] == "a". The former doesn't return anything, latter returns True and is used in the function. $\endgroup$
    – user16320
    Apr 9, 2023 at 20:38
  • 1
    $\begingroup$ @user16320 the problem is not your second check (which does indeed work as you describe), but that the first check doesn't evaluate in the first place (therefore, the second condition is never considered) $\endgroup$
    – Lukas Lang
    Apr 9, 2023 at 21:14

2 Answers 2

3
$\begingroup$

@user16320, Thanks to the comment from Lukas Lang, I came up with the following that does what you want.

fun[var_] := Which[
  TrueQ[var == "a"], {"a", "a"},
  var[[1]] == "a", {"a", "b"}
]

Note: if all tests in Which are False, the Which expression evaluates to Null. When Null is the final result of evaluating an input cell, no Output cell is created.

$\endgroup$
1
  • $\begingroup$ I really like this answer (though I'm now using the triple equal sign since it's shorter), so I accepted it :) $\endgroup$
    – user16320
    Apr 10, 2023 at 5:02
2
$\begingroup$

Another way to do this is the following:

fun[var_] := Which[
    And[Equal[ListQ[var], False], Equal[var, "a"]],
        {"a", "a"},
    And[Equal[ListQ[var], True], Equal[var[[1]], "a"]],
        {"a", "b"}
   ];
$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.