Skip to main content
edited tags
Link
Kuba
  • 137.7k
  • 13
  • 289
  • 751
Update with workable functions
Source Link
Edmund
  • 43.2k
  • 3
  • 53
  • 148

Both of the above can be call on multiple notebooks and notebooks that have not called them will continue to operate with just-in-time variables. These can be placed in a .wl package file to make them easier to use across multiple notebooks.

##To use##

##To use##

Both of the above can be call on multiple notebooks and notebooks that have not called them will continue to operate with just-in-time variables. These can be placed in a .wl package file to make them easier to use across multiple notebooks.

##To use##

Update with workable functions
Source Link
Edmund
  • 43.2k
  • 3
  • 53
  • 148

I am developing a UI for a process that as many user driven event updates. I have a quite a few variables that are holding state of this process and these are all floating about in the notebook context. It is easy to typo one of the variable names and then it is a nightmare to locate it.

Short of wrapping the entire code of the notebook in one giant module where misspelled names would show blue, how do I get some front-end indication or run-time warning that a variable is undeclared?


#Update#

Using @rcollyer answer below that pointed me to $NewSymbol I have constructed the following two functions, declareContext and removeDeclareContext, that enable an OPTION EXPLICIT type environment when the Global setting for CellContext is Notebook (this can be done in the Option Inspector).

ClearAll[declareContext];
declareContext[context_String] :=
 Module[{},
  $NewSymbol::undeclared = "`1``2` was not previously declared.";

  If[ValueQ[$NewSymbol::declarativeContexts] == False,
   $NewSymbol::declarativeContexts = ""
   ];

  $NewSymbol::declarativeContexts = 
   StringJoin[$NewSymbol::declarativeContexts, "|", context];

  $NewSymbol :=
   If[ContainsAny[StringSplit[$NewSymbol::declarativeContexts, "|"], {#2}] &&
      ContainsNone[Names[#2 <> "*"], {#1}],
     Message[$NewSymbol::undeclared, #2, #1]] &;
  ]

declareContext sets up

  • a new message to display for undeclared variables,
  • a repository of contexts that are participating in the option explicit setting by using a new message, $NewSymbol::declarativeContexts,
  • the $NewSymbol to a function that makes use of both its parameters (variable and context) to check the context repository and existing variables in the context.
ClearAll[removeDeclareContext];
removeDeclareContext[context_String] :=
 $NewSymbol::declarativeContexts = 
  StringDelete[$NewSymbol::declarativeContexts, "|" <> context]

removeDeclareContext simply removes the context from the repository.

##To use##

At the start of your notebook declare your variables by evaluating them in a list. Then call declareContext with the Context; this should be the notebook context with either the notebook or global preference CellContext -> Notebook.

{x, y, z};
declareContext@Context[]

You may now assign values to the declared variables but new variables will error.

In:= x = 4
Out= 4

but

w = 1
$NewSymbol::undeclared: Notebook$$15$56114`w was not previously declared. >>

Turn off declarative variables by calling removeDeclareContext@Context[].

##Issues##

The functions above prevent declaring scoped variables as in Module and DynamicModule. Therefore they are too restrictive.

Module[{w},
 w = 1
]
$NewSymbol::undeclared: Notebook$$15$56114`w was not previously declared. >>

You can work around this by using a sub-context for scoped variables.

Module[{m`w},
 m`w = 1
]
1

Any ideas to loosen up the functions so that you do not need a sub-context for scoped variables are very welcome

I developing a UI for a process that as many user driven event updates. I have a quite a few variables that are holding state of this process and these are all floating about in the notebook context. It is easy to typo one of the variable names and then it is a nightmare to locate it.

Short of wrapping the entire code of the notebook in one giant module where misspelled names would show blue, how do I get some front-end indication or run-time warning that a variable is undeclared?

I am developing a UI for a process that as many user driven event updates. I have a quite a few variables that are holding state of this process and these are all floating about in the notebook context. It is easy to typo one of the variable names and then it is a nightmare to locate it.

Short of wrapping the entire code of the notebook in one giant module where misspelled names would show blue, how do I get some front-end indication or run-time warning that a variable is undeclared?


#Update#

Using @rcollyer answer below that pointed me to $NewSymbol I have constructed the following two functions, declareContext and removeDeclareContext, that enable an OPTION EXPLICIT type environment when the Global setting for CellContext is Notebook (this can be done in the Option Inspector).

ClearAll[declareContext];
declareContext[context_String] :=
 Module[{},
  $NewSymbol::undeclared = "`1``2` was not previously declared.";

  If[ValueQ[$NewSymbol::declarativeContexts] == False,
   $NewSymbol::declarativeContexts = ""
   ];

  $NewSymbol::declarativeContexts = 
   StringJoin[$NewSymbol::declarativeContexts, "|", context];

  $NewSymbol :=
   If[ContainsAny[StringSplit[$NewSymbol::declarativeContexts, "|"], {#2}] &&
      ContainsNone[Names[#2 <> "*"], {#1}],
     Message[$NewSymbol::undeclared, #2, #1]] &;
  ]

declareContext sets up

  • a new message to display for undeclared variables,
  • a repository of contexts that are participating in the option explicit setting by using a new message, $NewSymbol::declarativeContexts,
  • the $NewSymbol to a function that makes use of both its parameters (variable and context) to check the context repository and existing variables in the context.
ClearAll[removeDeclareContext];
removeDeclareContext[context_String] :=
 $NewSymbol::declarativeContexts = 
  StringDelete[$NewSymbol::declarativeContexts, "|" <> context]

removeDeclareContext simply removes the context from the repository.

##To use##

At the start of your notebook declare your variables by evaluating them in a list. Then call declareContext with the Context; this should be the notebook context with either the notebook or global preference CellContext -> Notebook.

{x, y, z};
declareContext@Context[]

You may now assign values to the declared variables but new variables will error.

In:= x = 4
Out= 4

but

w = 1
$NewSymbol::undeclared: Notebook$$15$56114`w was not previously declared. >>

Turn off declarative variables by calling removeDeclareContext@Context[].

##Issues##

The functions above prevent declaring scoped variables as in Module and DynamicModule. Therefore they are too restrictive.

Module[{w},
 w = 1
]
$NewSymbol::undeclared: Notebook$$15$56114`w was not previously declared. >>

You can work around this by using a sub-context for scoped variables.

Module[{m`w},
 m`w = 1
]
1

Any ideas to loosen up the functions so that you do not need a sub-context for scoped variables are very welcome

Tweeted twitter.com/StackMma/status/827241452375830529
Source Link
Edmund
  • 43.2k
  • 3
  • 53
  • 148
Loading