2
$\begingroup$

Consider the following simplified code snippet:

line=Line[{#, 2 #} & /@ Range[10]]  (* arbitrary line *)
line /. {Line[x_List] -> Line[Most@x]}

Mathematica reports of the second line that

Most::normal: Nonatomic expression expected at position 1 in Most[x].

  • Please explain why I get this warning. Is my approach incorrect?
  • Can I do this replacement without raising a warning?
  • Why does this code still provide the desired output, despite the warning?
$\endgroup$
  • 4
    $\begingroup$ You should use RuleDelayed (i.e. :>) instead of a simple Rule (i.e. ->) to delay evaluation of the right-hand-side of your replacement rule until a value has been assigned to x. Otherwise Most will be applied to x when this doesn't have a value, and will return the error you saw. $\endgroup$ – MarcoB Jan 30 '17 at 6:03
  • $\begingroup$ @MarcoB Ah of course. Thanks. But now I am puzzled why the substitution I used did in fact work ... $\endgroup$ – Alan Jan 30 '17 at 6:34
  • 1
    $\begingroup$ Alan, rather than mark your question as a duplicate I chose to answer the implied question why does the substitution still work despite the warning? May I edit your question to include that in the bulleted points? $\endgroup$ – Mr.Wizard Jan 30 '17 at 9:55
3
$\begingroup$

This question is partially a duplicate of Unexpected behavior of rule matching a pattern but I would like to focus on the third point, i.e.

Ah of course. Thanks. But now I am puzzled why the substitution I used did in fact work ...

Your replacement line /. {Line[x_List] -> Line[Most@x]} works, despite issuing a warning, so long as x is unassigned, because like most Mathematica functions Most returns its unevaluated form in the case of bad input.

Most["foo"]

Most::normal: Nonatomic expression expected at position 1 in Most[foo]. >>

Most["foo"]

If this expression is later transformed into valid input the function will operate as normal:

% /. "foo" -> {1, 2, 3}
{1, 2}

In this example (using %, shorthand for Out) no Message is issued as once the unevaluated form is returned it is not evaluated again until it is modified; this is to prevent infinite recursion.

If x is assigned a value the code breaks:

x = 7;
{1, 2, 3} /. x_List -> Most[x]

Most::normal: Nonatomic expression expected at position 1 in Most[7]. >>

Most[7]

If x is non-zero-length you get seemingly errant output without even a warning message:

x = {7, 8};

{1, 2, 3} /. x_List -> Most[x]
{7}

This evaluation sequence where evaluation will continue if possible even after an "error" is both a strength of and a danger in Mathematica. A savvy programmer can understand these warning messages as what they are and may even intentionally write code that would issue them if not for the application of Quiet. However it also means that coding mistakes unravel in a strange and seemingly unpredictable way sometimes.

Incidentally you may wish to provide such warning messages for your own functions rather than explicitly returning $Failed on any bad input. For an approach to this please see:

|improve this answer|||||
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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