# Using a Global symbol inside a package [duplicate]

## Part I - Without package

I have created a function to compute a bridge score.

computeScore[level_, denomination_, vul_, dbl_, tricks_] := Module[
{
trickScore = 0,
trickMultiplier = 2^dbl,
numberEffectiveTricks,
trickValue = {20, 30, 30},
gameBid,
partialBonus = 0,
gameBonus = 0,
gameValue = {300, 500},
gameTricks = {5, 4, 3},
slamBonus = 0,
slamValue = {500, 750},
insult = 0,
overtrickScore = 0,
overtrickValue = {100, 200}, (* doubled overtricks non-vul/vul *)
undertrickScore = 0,
undertrickValue = {50, 100},
doubled = False,
redoubled = False,
suitIndex,
total
},

(* Convert the denomination argument into an index into a suit array *)

suitIndex = Which[
SameQ[denomination, $c] || SameQ[denomination,$d],
1,
SameQ[denomination, $h] || SameQ[denomination,$s],
2,
SameQ[denomination, $nt], 3 ]; (* Take two paths depending upon whether the contract made or was set *) If[tricks >= level, (* contract made *) numberEffectiveTricks = 2^dbl*level; trickScore = numberEffectiveTricks*trickValue[[suitIndex]] + 10*trickMultiplier*Floor[suitIndex/3]; overtrickScore = (tricks - level)* (UnitStep[-dbl]*trickValue[[suitIndex]] + dbl*overtrickValue[[vul + 1]]); insult = 50*dbl; gameBid = UnitStep[numberEffectiveTricks - gameTricks[[suitIndex]]]; partialBonus = (1 - gameBid)*50; gameBonus = gameBid*gameValue[[vul + 1]]; slamBonus = (level - 5)*UnitStep[level - 5]*slamValue[[vul + 1]]; total = trickScore + overtrickScore + insult + partialBonus + gameBonus + slamBonus , (* contract was set *) undertrickScore = With[ { undertricks = level - tricks }, If[dbl == 0, -50*undertricks*(vul + 1), dbl*If[vul == 0, -100 - 200*(undertricks - 1)*UnitStep[undertricks - 2] - 100*(undertricks - 3)*UnitStep[undertricks - 4], -200 - 300*(undertricks - 1)*UnitStep[undertricks - 2] ] ] ] ] ]  It works fine. Here is an example where the contract is 3 spades, not vulnerable, not doubled, making 3. computeScore[3,$s, 0, 0, 3]
140


Note that I am using a set of undefined symbols inside the module, $c thru $nt to represent clubs through notrump.

## Part II - Inside package

Now close Mathematica and start a new notebook.

Use the same function inside a package. To save space I won't re-copy the function. The new notebook looks like:

BeginPackage["bridgeScore"]

computeScore::usage =
"Returns the score given the level, suit, vulnerability (0/1),\n\
doubled status (0/1/2) and the number of tricks";

Begin["Private"]

Copy computeScore code here ...

End[]

EndPackage[]


Now when I execute I get an error

computeScore[3, $s, 0, 0, 3] Part::pkspec1: The expression Null cannot be used as a part specification.  I have traced it down to the statement where denomination is tested suitIndex = Which[ SameQ[denomination,$c] || SameQ[denomination, $d], 1, SameQ[denomination,$h] || SameQ[denomination, $s], 2, SameQ[denomination,$nt],
3
];


For some reason this works fine until you place it in a package.

I don't have a clue why, can any one help?

• Why use a dollar sign at all? – David G. Stork Oct 4 '16 at 22:08
• Also, where you use Which, you might be able to shorten your code by using Switch. – Jason B. Oct 4 '16 at 22:09
• at least closely related: Derivative in my package return 0 – Kuba Oct 5 '16 at 5:25

The issue is that you are calling the function with Global$s, but the function definition uses the private version of the symbol $s. Notice it works if you provide the context manually,

computeScore[3, bridgeScorePrivate$s, 0, 0, 3] (* 140 *)  So your issue doesn't really have anything to do with the dollar sign. All you need to do is put this line before the line containing Begin["Private"] {$s,$c,$d,$h,$nt}


This puts all of these variables in the correct context. But be aware that if someone puts the same value to two of these constants, your function breaks.

computeScore[3, $s, 0, 0, 3]$s = $c = 3; computeScore[3,$s, 0, 0, 3]
(* 140 *)
(* 110 *)


One way around this would be to use strings for the suit tokens. You can substitute "hearts" for \$h, and so on, directly in your code and it will work the same. You won't have to worry about context or whether they have numeric values.

• Thank you, I understand perfectly my mistake. Yes, using strings appears to be the safest course. – Jack LaVigne Oct 5 '16 at 8:01