7

In a notebook with a new kernel, execute the following in an Input cell:

$Context
Begin["Test`"];
$Context
f = x \[Function] x*x;
f[2]
End[];
$Context
f[2]  (* why is this recognized 2nd time?? *)
Test`f[2]

The result is as expected (i.e., f[2] is unevaluated in the Global context). But now evaluate the same Inpute cell, without any changes. The contexts are reported as before, but this time f[2] evaluates to 4 in the Global context. Why?

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
Alan
  • 13,686
  • 19
  • 38
  • The f[2] that is followed by the comment returns unevaluated, as it should. Then, Test f[2] returns evaluated, as it should. What is the issue? – bbgodfrey Sep 13 '16 at 03:51
  • 2
    The second evaluation is different from the first, because Global`f is already created, so you are assigning to it, instead of Test`f. – ilian Sep 13 '16 at 04:20

1 Answers1

8

There are two things that influence symbol lookup: $ContextPath and $Context. This is described in:

In short: $ContextPath controls where the system looks for existing symbols. This search is done first. $Context controls where new symbols are created if a name was not found in $ContextPath any contexts.

Begin changes only $Context. BeginPackage changes both $ContextPath and $Context.

You are only using Begin, but not BeginPackage. This means that $Context will be set to "Test`" but $ContextPath will stay what it was before.

When you mention a symbol name such as f, the first thing Mathematica does is that it looks for it in the contexts contained in $ContextPath. If it is found there, it uses that instance. This is what happens during the second evaluation: f is found in Global`, so f now refers to Global`f, not Test`f.

Why does f exist in Global`? Because you mentioned it when evaluating f[2]. Note the distinction between the fact that a symbol exists and that a symbol has associated definitions. Just evaluating sym alone will create that symbol.

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
  • So do you think I should retract a close vote? – Kuba Sep 13 '16 at 09:46
  • @Kuba As you wish, I am uncertain. The information there was necessary, but I thought it wasn't quite sufficient ... but then I notice that ilian explained this (very tersely) in this comment, so maybe that would have been enough? – Szabolcs Sep 13 '16 at 09:48
  • We can do both, with this answer we can mark this topic as a duplicate in future anyway. In case where original one isn't clearly answering OP. – Kuba Sep 13 '16 at 09:50
  • While your answer is simple and helpful, the existing situation is complex and confusing. Iiuc, the behavior I expected matches the current documentation (both online and the documentation that ships with Mma v11) of $ContextPath, and indeed was the actual behavior until v6. Am I correct that due to this behavior change one should effectively never use Begin .. End without nesting it in BeginPackage .. EndPackage? – Alan Sep 13 '16 at 12:20
  • @Alan What does "Iiuc" mean? Whether you should use Begin .. End on their own depends on what you want to achieve ... Any use outside of the standard package structure would be fairly unusual. But I'm sure that there are some good uses for it I just can't think of one right now (at least not one outside BeginPackage ... – Szabolcs Sep 13 '16 at 12:26
  • Presumably the behavior change achieved some goal, but I'm not seeing what it is. One used to be able to safely change context with Begin .. End. Now that seems only to be true relative to an encompassing BeginPackage .. EndPackage. PS "Iiuc" means "If I understand correctly". – Alan Sep 13 '16 at 12:39
  • @Alan Maybe there was a good reason. What's more annoying that such small but fundamental changes are made from time to time, yet they are almost never documented. For any other programming language such a change would be a major point in the release notes. I see this as a symptom of Wolfram ignoring developers. Mma is meant to be used interactively from a notebook. There's much less support for writing and distributing packages and there's no help for package authors to ensure compatibility with multiple Mathematica versions. I have 5 versions of Mathematica on my computer just for this. – Szabolcs Sep 13 '16 at 12:42
  • @Alan Yet I don't have all of them and I still get surprises due to small but fundamental changes ... Some of these changes may be fairly arbitrary ... – Szabolcs Sep 13 '16 at 12:43
  • 1
    @Alan a workaround is to use `f, as it forces f to be in the local context. – rcollyer Sep 13 '16 at 13:38
  • @rcollyer That would be worth an answer if the question weren't closed! I didn't know this. – Szabolcs Sep 13 '16 at 13:43
  • @Szabolcs Here's the relevant table in the docs which describes it, and it also discusses how to reference relative contexts, which can be useful. However, as you point out, the last item should read: "a symbol found in the current context path, or local context". – rcollyer Sep 13 '16 at 13:56