(* Content-type: application/mathematica *) (*** Wolfram Notebook File ***) (* http://www.wolfram.com/nb *) (* CreatedBy='Mathematica 6.0' *) (*CacheID: 234*) (* Internal cache information: NotebookFileLineBreakTest NotebookFileLineBreakTest NotebookDataPosition[ 145, 7] NotebookDataLength[ 139307, 3939] NotebookOptionsPosition[ 126166, 3516] NotebookOutlinePosition[ 126548, 3533] CellTagsIndexPosition[ 126505, 3530] WindowFrame->Normal ContainsDynamic->False*) (* Beginning of Notebook Content *) Notebook[{ Cell[CellGroupData[{ Cell[TextData[{ "Protecting functions from inappropriate options with \t\t\t", StyleBox["PackageOptionChecks`", FontWeight->"Bold", FontSlant->"Italic"] }], "Subtitle", CellChangeTimes->{{3.441615231458573*^9, 3.4416152651069565`*^9}, { 3.4416153789406414`*^9, 3.441615402594654*^9}}], Cell[CellGroupData[{ Cell["\<\ Author: \t\t\tLeonid B. Shifrin \t\t\t \t\t\tleonid@mathprogramming-intro.org, \t\t\tshifrinl@hotmail.com\ \>", "Subsection", CellChangeTimes->{{3.4416153043333616`*^9, 3.441615358240877*^9}, { 3.4416175573931026`*^9, 3.441617572254472*^9}}, FontWeight->"Plain"], Cell["Package version 1.0 - January 2009", "Subsubsection", CellChangeTimes->{{3.441703718150744*^9, 3.441703747372763*^9}}, FontWeight->"Plain"], Cell[TextData[{ StyleBox["Mathematica", FontSlant->"Italic"], " version 5.0+ " }], "Subsubsection", CellChangeTimes->{{3.4417037513885374`*^9, 3.4417037599107924`*^9}, { 3.441703818074427*^9, 3.4417038219600143`*^9}, 3.4418064057502337`*^9}, FontWeight->"Plain"] }, Open ]], Cell[CellGroupData[{ Cell["Introduction", "Section", CellChangeTimes->{{3.4414485562917566`*^9, 3.441448559446293*^9}}, FontWeight->"Plain"], Cell[TextData[{ "The functionality of the present package allows one to \"protect\" a given \ set of option - taking functions from passed options which are either \ \"unknown\" to the function or set to inappropriate values. It does this by \ modifying the behavior of the functions of interest in such a way that they \ issue an error - message and execute arbitrary (specified) code upon \ receiving an \"inappropriate\" option or options. \n\nThe present package \ builds on functionality, but allows to \"protect\" entire \ packages, and has a simpler interface. Generally, it is better suited to help \ with package development.\n \n At present, the main pre - requisite for \ this to work is that all option - taking functions to be protected have in \ their signature (s) options declared as ", StyleBox["opts___?OptionQ", FontWeight->"Bold", FontSlant->"Italic"], " (name < opts > can be arbitrary). The constructs ", StyleBox["OptionPattern", FontWeight->"Bold", FontSlant->"Italic"], " - ", StyleBox["OptionValue", FontWeight->"Bold", FontSlant->"Italic"], ", introduced in v.6.0, are not yet covered. The work to incorporate them is \ underway.\n \n The package can be used as a bulletproofing/debugging tool \ when dealing with packages written for earlier versions of ", StyleBox["Mathematica", FontSlant->"Italic"], " (where still ", StyleBox["opts___?OptionQ", FontWeight->"Bold", FontSlant->"Italic"], " pattern was used), or if one still prefers to use this pattern in newer \ versions of ", StyleBox["Mathematica.", FontSlant->"Italic"] }], "Text", CellChangeTimes->{{3.4414485609584675`*^9, 3.441448821583227*^9}, { 3.4416164927121663`*^9, 3.441616504739461*^9}, 3.4416172154914722`*^9, { 3.4417976760775805`*^9, 3.441797943091528*^9}, {3.441812584995552*^9, 3.441812704387229*^9}}] }, Open ]], Cell[CellGroupData[{ Cell["A toy package example for illustration", "Section", CellChangeTimes->{{3.4411025582147665`*^9, 3.4411025908116384`*^9}}, FontWeight->"Plain"], Cell[TextData[{ "To best illustrate the workings of the present package, we will \ interactively create a toy package that can answer a few simple statistical \ questions about the letter content of the first 5000 words in the English \ dictionary built in ", StyleBox["Mathematica", FontSlant->"Italic"], ". It will have 2 public functions : one (", StyleBox["LetterFrequenciesInWord", FontSlant->"Italic"], ") returns frequencies of all letters in a given word, and takes an option \ ", StyleBox["CaseSensitive", FontSlant->"Italic"], " which can be set ", StyleBox["True", FontSlant->"Italic"], " or ", StyleBox["False", FontSlant->"Italic"], ", and the other (", StyleBox["AllWordsWithLetterFrequency", FontSlant->"Italic"], ") finds all words with at least 1 letter having a specified frequency, and \ takes options ", StyleBox["CaseSensitive", FontSlant->"Italic"], " and additionally, ", StyleBox["MaxWordLength", FontSlant->"Italic"], ", which limits the size of the found words. The second function uses the \ first one internally.\n\nWe will see that it is rather easy to get an \ inconsistent behavior as a result of passing inappropriate options, and use \ the functionality of the present package to restrict the option values and \ remove this inconsistent behavior. All of the functionality of the present \ package will be demonstrated." }], "Text", CellChangeTimes->{{3.4414485450756288`*^9, 3.441448547459056*^9}, { 3.441448844816635*^9, 3.4414488755107713`*^9}, {3.4414489211163487`*^9, 3.441449328832616*^9}, 3.4416172202082543`*^9, {3.441617644788771*^9, 3.4416176740107903`*^9}}], Cell[CellGroupData[{ Cell["An \"unprotected\" version of the package", "Subsection", CellChangeTimes->{{3.4411025490616045`*^9, 3.4411025744080515`*^9}}, FontWeight->"Plain"], Cell["\<\ This is our package. The code is pretty self - explanatory (you have to \ execute this cell to load it).\ \>", "Text", CellChangeTimes->{{3.4414493522663116`*^9, 3.4414493950177855`*^9}}], Cell[BoxData[{ RowBox[{ RowBox[{ RowBox[{"BeginPackage", "[", "\"\\"", "]"}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"LetterFrequenciesInWord", "::", "usage"}], " ", "=", " ", "\[IndentingNewLine]", "\"\\""}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "::", "usage"}], " ", "=", " ", "\[IndentingNewLine]", "\"\ occurs with the frequency \>\""}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"CaseSensitive", "::", "usage"}], " ", "=", " ", "\"\\""}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"MaxWordLength", "::", "usage"}], " ", "=", "\"\\""}], ";"}], " ", "\[IndentingNewLine]", "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"Begin", "[", "\"\<`Private`\>\"", "]"}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"Options", "[", "LetterFrequenciesInWord", "]"}], "=", RowBox[{"{", RowBox[{"CaseSensitive", "\[Rule]", " ", "True"}], "}"}]}], ";"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"Options", "[", "AllWordsWithLetterFrequency", "]"}], "=", RowBox[{"{", RowBox[{ RowBox[{"CaseSensitive", "\[Rule]", " ", "True"}], ",", RowBox[{"MaxWordLength", "\[Rule]", " ", "10"}]}], "}"}]}], ";"}], "\n"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"UseOption", "[", RowBox[{"optname_Symbol", ",", "function_", ",", RowBox[{"opts___", "?", "OptionQ"}]}], "]"}], ":=", "\n", "\t", RowBox[{ RowBox[{"optname", "/.", RowBox[{"Flatten", "[", RowBox[{"{", "opts", "}"}], "]"}]}], "/.", RowBox[{"Options", "[", "function", "]"}]}]}], ";"}], "\[IndentingNewLine]"}], "\n", RowBox[{ RowBox[{ RowBox[{"With", "[", RowBox[{ RowBox[{"{", RowBox[{"earlyVersion", "=", RowBox[{ RowBox[{"ToExpression", "[", RowBox[{"StringTake", "[", RowBox[{"$Version", ",", "1"}], "]"}], "]"}], "<", "6"}]}], "}"}], ",", RowBox[{"allWords", "=", "\[IndentingNewLine]", RowBox[{"If", "[", RowBox[{"earlyVersion", ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"Needs", "[", "\"\\"", "]"}], ";", "\[IndentingNewLine]", RowBox[{"Take", "[", RowBox[{ RowBox[{ "Miscellaneous`Dictionary`FindWords", "[", "\"\<*\>\"", "]"}], ",", "5000"}], "]"}]}], ",", "\[IndentingNewLine]", RowBox[{"(*", "else", "*)"}], "\[IndentingNewLine]", RowBox[{"Take", "[", RowBox[{ RowBox[{"DictionaryLookup", "[", "\"\<*\>\"", "]"}], ",", "5000"}], "]"}]}], "]"}]}]}], "]"}], ";"}], "\n"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"frequencies", "[", "x_List", "]"}], ":=", "\[IndentingNewLine]", "\t", RowBox[{ RowBox[{ RowBox[{"{", RowBox[{ RowBox[{"First", "[", "#", "]"}], ",", RowBox[{"Length", "[", "#", "]"}]}], "}"}], "&"}], "/@", RowBox[{"Split", "[", RowBox[{"Sort", "[", "x", "]"}], "]"}]}]}], ";"}], "\n", "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"LetterFrequenciesInWord", "[", RowBox[{"word_String", ",", RowBox[{"opts___", "?", "OptionQ"}]}], "]"}], ":=", "\[IndentingNewLine]", RowBox[{"With", "[", RowBox[{ RowBox[{"{", RowBox[{"fn", "=", " ", "\[IndentingNewLine]", "\t", RowBox[{ RowBox[{"If", "[", RowBox[{ RowBox[{"UseOption", "[", RowBox[{ "CaseSensitive", ",", "LetterFrequenciesInWord", ",", "opts"}], "]"}], ",", "\[IndentingNewLine]", "\t\t", "#", ",", "\[IndentingNewLine]", "\t\t", RowBox[{"ToLowerCase", "[", "#", "]"}]}], "]"}], "&"}]}], "}"}], ",", "\[IndentingNewLine]", "\t", RowBox[{"frequencies", "[", RowBox[{"Characters", "[", RowBox[{"fn", "[", "word", "]"}], "]"}], "]"}]}], "]"}]}], ";"}], "\[IndentingNewLine]"}], "\n", RowBox[{ RowBox[{ RowBox[{ RowBox[{"frequentLettersExistQ", "[", RowBox[{"word_String", ",", "freq_Integer", ",", RowBox[{"letters", ":", RowBox[{"(", RowBox[{"_String", "|", RowBox[{"{", "__String", "}"}]}], ")"}]}], ",", RowBox[{"opts___", "?", "OptionQ"}]}], "]"}], ":=", "\[IndentingNewLine]", RowBox[{ RowBox[{"Intersection", "[", "\[IndentingNewLine]", RowBox[{ RowBox[{"Cases", "[", "\[IndentingNewLine]", "\t", RowBox[{ RowBox[{"LetterFrequenciesInWord", "[", RowBox[{"word", ",", "opts"}], "]"}], ",", "\[IndentingNewLine]", "\t", RowBox[{ RowBox[{"{", RowBox[{"let_String", ",", "freq"}], "}"}], "\[RuleDelayed]", "let"}]}], "]"}], ",", "\[IndentingNewLine]", RowBox[{"Flatten", "[", RowBox[{"{", "letters", "}"}], "]"}]}], "\[IndentingNewLine]", "]"}], "=!=", RowBox[{"{", "}"}]}]}], ";"}], "\[IndentingNewLine]", "\[IndentingNewLine]", RowBox[{"(*", " ", RowBox[{ "The", " ", "test", " ", "for", " ", "the", " ", "word", " ", "size", " ", "has", " ", "been", " ", "deliberately", " ", "written", " ", "in", " ", "a", " ", "way", " ", "that", " ", "produces", " ", "all", " ", "words", " ", "if", " ", "the", " ", "value", " ", "of", " ", "MaxWordLength", " ", "option", " ", "is", " ", "inappropriate", " ", RowBox[{"(", RowBox[{"say", ",", " ", RowBox[{"not", " ", "numerical"}]}], ")"}]}], "*)"}], "\n"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{ RowBox[{"letters", ":", RowBox[{"(", RowBox[{"_String", "|", RowBox[{"{", "__String", "}"}]}], ")"}]}], ",", "freq_Integer", ",", RowBox[{"opts___", "?", "OptionQ"}]}], "]"}], ":=", "\[IndentingNewLine]", RowBox[{"With", "[", RowBox[{ RowBox[{"{", RowBox[{"maxLen", " ", "=", " ", "\[IndentingNewLine]", "\t\t", RowBox[{"UseOption", "[", RowBox[{ "MaxWordLength", ",", "AllWordsWithLetterFrequency", ",", "opts"}], "]"}]}], "}"}], ",", "\[IndentingNewLine]", "\t", RowBox[{"Select", "[", "\[IndentingNewLine]", "\t", RowBox[{ RowBox[{"Select", "[", RowBox[{"allWords", ",", RowBox[{ RowBox[{"!", RowBox[{"TrueQ", "[", RowBox[{ RowBox[{"StringLength", "[", "#", "]"}], ">", " ", "maxLen"}], "]"}]}], "&"}]}], "]"}], ",", "\[IndentingNewLine]", "\t", RowBox[{ RowBox[{"frequentLettersExistQ", "[", RowBox[{"#", ",", "freq", ",", "letters", ",", "opts"}], "]"}], "&"}]}], "]"}]}], "\[IndentingNewLine]", "]"}]}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"End", "[", "]"}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{"EndPackage", "[", "]"}], ";"}]}], "Input", CellFrame->True, CellChangeTimes->{{3.4411010962926254`*^9, 3.441101162517853*^9}, { 3.4411017126789455`*^9, 3.441101853962101*^9}, {3.441101894480363*^9, 3.4411020214629555`*^9}, {3.441439257777328*^9, 3.441439287890629*^9}, { 3.4414494244100494`*^9, 3.4414495795230913`*^9}, 3.441556418099995*^9, 3.4416095005178847`*^9}, FontWeight->"Plain"] }, Open ]], Cell[CellGroupData[{ Cell["Some checks with appropriate option setting:", "Subsection", CellChangeTimes->{{3.4411023181195264`*^9, 3.441102326892141*^9}, { 3.441102621295472*^9, 3.44110263167039*^9}}, FontWeight->"Plain"], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"LetterFrequenciesInWord", "[", "\"\\"", "]"}]], "Input", CellChangeTimes->{{3.4411010693538895`*^9, 3.4411010826630273`*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{ RowBox[{"{", RowBox[{"\<\"e\"\>", ",", "4"}], "}"}], ",", RowBox[{"{", RowBox[{"\<\"h\"\>", ",", "1"}], "}"}], ",", RowBox[{"{", RowBox[{"\<\"l\"\>", ",", "1"}], "}"}], ",", RowBox[{"{", RowBox[{"\<\"n\"\>", ",", "1"}], "}"}], ",", RowBox[{"{", RowBox[{"\<\"r\"\>", ",", "1"}], "}"}], ",", RowBox[{"{", RowBox[{"\<\"s\"\>", ",", "2"}], "}"}], ",", RowBox[{"{", RowBox[{"\<\"t\"\>", ",", "1"}], "}"}], ",", RowBox[{"{", RowBox[{"\<\"v\"\>", ",", "1"}], "}"}]}], "}"}]], "Output", CellChangeTimes->{3.4417245974447794`*^9, 3.4417246396154175`*^9, 3.4418066775710926`*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3"}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{{3.4411012030861874`*^9, 3.441101240910576*^9}, { 3.4411012900812798`*^9, 3.441101290662115*^9}}], Cell[BoxData[ TagBox[ RowBox[{"{", RowBox[{"\<\"aardvark\"\>", ",", "\<\"aardvarks\"\>", ",", "\<\"acacia\"\>", ",", "\<\"acacias\"\>", ",", "\<\"academia\"\>", ",", "\<\"academical\"\>", ",", "\<\"actuarial\"\>", ",", "\<\"adamant\"\>", ",", RowBox[{"\[LeftSkeleton]", "78", "\[RightSkeleton]"}], ",", "\<\"Atahualpa\"\>", ",", "\<\"Atalanta\"\>", ",", "\<\"ataxia\"\>", ",", "\<\"Athabasca\"\>", ",", "\<\"Athabaskan\"\>", ",", "\<\"attachable\"\>", ",", "\<\"attainable\"\>", ",", "\<\"attractant\"\>"}], "}"}], Short[#, 5]& ]], "Output", CellChangeTimes->{3.4417245989469395`*^9, 3.4417246404365983`*^9, 3.4418066791633825`*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "False"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{{3.441101267328563*^9, 3.441101302238762*^9}}], Cell[BoxData[ TagBox[ RowBox[{"{", RowBox[{"\<\"Aaliyah\"\>", ",", "\<\"aardvark\"\>", ",", "\<\"aardvarks\"\>", ",", "\<\"Abraham\"\>", ",", "\<\"acacia\"\>", ",", "\<\"acacias\"\>", ",", "\<\"academia\"\>", ",", "\<\"academical\"\>", ",", RowBox[{"\[LeftSkeleton]", "139", "\[RightSkeleton]"}], ",", "\<\"ataxia\"\>", ",", "\<\"Atlanta\"\>", ",", "\<\"attachable\"\>", ",", "\<\"attainable\"\>", ",", "\<\"attractant\"\>", ",", "\<\"Australia\"\>", ",", "\<\"Australian\"\>"}], "}"}], Short[#, 5]& ]], "Output", CellChangeTimes->{3.4417246016307983`*^9, 3.441724641257779*^9, 3.4418066808458014`*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "False"}], ",", RowBox[{"MaxWordLength", "\[Rule]", "6"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{{3.4411013545539875`*^9, 3.4411013650991507`*^9}}], Cell[BoxData[ TagBox[ RowBox[{"{", RowBox[{"\<\"acacia\"\>", ",", "\<\"Acadia\"\>", ",", "\<\"Adana\"\>", ",", "\<\"Adhara\"\>", ",", "\<\"Agana\"\>", ",", "\<\"Agatha\"\>", ",", "\<\"Aglaia\"\>", ",", "\<\"Alana\"\>", ",", "\<\"Alaska\"\>", ",", "\<\"alpaca\"\>", ",", RowBox[{"\[LeftSkeleton]", "4", "\[RightSkeleton]"}], ",", "\<\"Arabia\"\>", ",", "\<\"Arafat\"\>", ",", "\<\"Ararat\"\>", ",", "\<\"Arawak\"\>", ",", "\<\"arcana\"\>", ",", "\<\"armada\"\>", ",", "\<\"Asama\"\>", ",", "\<\"Asmara\"\>", ",", "\<\"Astana\"\>", ",", "\<\"ataxia\"\>"}], "}"}], Short[#, 5]& ]], "Output", CellChangeTimes->{3.44172460486545*^9, 3.4417246426397667`*^9, 3.441806682007472*^9}] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell["Passing options with inappropriate option settings ", "Subsection", CellChangeTimes->{{3.4411023371068287`*^9, 3.4411023870886993`*^9}, { 3.441102643227008*^9, 3.44110264978644*^9}, 3.4414483927465906`*^9}, FontWeight->"Plain"], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "Fals"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{3.4411013259628754`*^9}], Cell[BoxData[ TagBox[ RowBox[{"{", "}"}], Short[#, 5]& ]], "Output", CellChangeTimes->{3.441724650020379*^9, 3.44180668396028*^9, 3.4418067929069376`*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "False"}], ",", RowBox[{"MaxWordLength", "\[Rule]", "\"\\""}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{{3.441101380110736*^9, 3.4411013819433713`*^9}}], Cell[BoxData[ TagBox[ RowBox[{"{", RowBox[{"\<\"Aaliyah\"\>", ",", "\<\"aardvark\"\>", ",", "\<\"aardvarks\"\>", ",", "\<\"aberrational\"\>", ",", "\<\"Abraham\"\>", ",", "\<\"acacia\"\>", ",", RowBox[{"\[LeftSkeleton]", "252", "\[RightSkeleton]"}], ",", "\<\"Australia\"\>", ",", "\<\"Australian\"\>", ",", "\<\"Australians\"\>", ",", "\<\"authoritarian\"\>", ",", "\<\"authoritarianism\"\>", ",", "\<\"authoritarians\"\>"}], "}"}], Short[#, 5]& ]], "Output", CellChangeTimes->{3.441724651612669*^9, 3.441806685933117*^9, 3.441806793838277*^9}] }, Open ]], Cell["\<\ Note that the resulting behavior is rather arbitrary: in the first case, an \ empty list is returned, while in the second, all the words that have 3 \ letters \"a\" are returned. Thus, from the viewpoint of the user who does not \ know or bother about implementation details, the behavior is undefined.\ \>", "Text", CellChangeTimes->{{3.441102393888477*^9, 3.4411025110769854`*^9}, 3.4411026634861393`*^9}] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell["Protecting the package from inappropriate options", "Section", CellChangeTimes->{{3.441102718234864*^9, 3.441102739014744*^9}, { 3.4411077543364224`*^9, 3.441107755207675*^9}}, FontWeight->"Plain"], Cell[CellGroupData[{ Cell["Protecting our toy package", "Subsection", CellChangeTimes->{{3.4416097526504335`*^9, 3.441609762554675*^9}}, FontWeight->"Plain"], Cell[CellGroupData[{ Cell["Preliminaries", "Subsubsection", CellChangeTimes->{{3.441616866159157*^9, 3.4416168709360256`*^9}}, FontWeight->"Plain"], Cell[TextData[{ "The way to use the functionality of \"", StyleBox["PackageOptionChecks`", FontWeight->"Bold", FontSlant->"Italic"], "\" in our toy package \"", StyleBox["LetterFrequencies`", FontWeight->"Bold", FontSlant->"Italic"], "\" is to use the public import. But first, let us ", StyleBox["Remove", FontSlant->"Italic"], " all the names in the \"", StyleBox["LetterFrequencies`", FontSlant->"Italic"], "\" context and \"", StyleBox["LetterFrequencies`Private`", FontSlant->"Italic"], "\" context so that we indeed start \"from scratch\" (an alternative would \ be to restart the kernel at this point). " }], "Text", CellChangeTimes->{{3.4411078159750547`*^9, 3.4411078564632735`*^9}, { 3.4411079079072466`*^9, 3.441107982744858*^9}, {3.4414496487125807`*^9, 3.4414497061051073`*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"Remove", "@@", RowBox[{"Join", "[", RowBox[{ RowBox[{"Names", "[", "\"\\"", "]"}], ",", RowBox[{"Names", "[", "\"\\"", "]"}]}], "]"}]}], ";"}]], "Input", CellChangeTimes->{{3.441107991637645*^9, 3.441108087405352*^9}}], Cell[TextData[{ "Unless you have already done so, you have to let ", StyleBox["Mathematica", FontSlant->"Italic"], " know where to look for the package <", StyleBox["PackageOptionChecks", FontWeight->"Bold", FontSlant->"Italic"], "> that we are going to use (", StyleBox["important", FontWeight->"Bold", FontVariations->{"Underline"->True}], ": please note that this package itself uses the <", StyleBox["CheckOptions`", FontWeight->"Bold", FontSlant->"Italic"], "> package, so the latter should also be available to ", StyleBox["Mathematica", FontSlant->"Italic"], " at the time this one is loaded - possibly be placed in the same \ directory). Assuming that you place it in a directory \"", StyleBox["C:\\\\MyDirectory", FontSlant->"Italic"], "\" (use your specific directory instead), this is done most easily by \ executing: ", StyleBox["AppendTo[$Path, \"C:\\\\MyDirectory\"]", FontSlant->"Italic"], ". This is a particular case with my machine :" }], "Text", CellChangeTimes->{{3.4404401775090466`*^9, 3.4404403218666224`*^9}, { 3.4404418893505535`*^9, 3.4404418908527136`*^9}, {3.4411077652821617`*^9, 3.4411077911393423`*^9}, 3.4411078904621615`*^9, {3.441108356161805*^9, 3.441108422467147*^9}, {3.4414497289579678`*^9, 3.4414497294486732`*^9}, 3.441617777078995*^9}], Cell[BoxData[ RowBox[{ RowBox[{"AppendTo", "[", RowBox[{ "$Path", ",", "\"\\""}], "]"}], ";"}]], "Input", CellChangeTimes->{{3.4306365337101617`*^9, 3.4306365531481123`*^9}, { 3.441445237179107*^9, 3.4414452384609504`*^9}}, FontWeight->"Plain"], Cell[TextData[{ "We start our package again (note the public import of <", StyleBox["PackageOptionChecks`", FontSlant->"Italic"], "> ) :" }], "Text", CellChangeTimes->{{3.441108134272744*^9, 3.441108144166971*^9}, { 3.441616367692397*^9, 3.441616387580995*^9}}], Cell[BoxData[{ RowBox[{ StyleBox[ RowBox[{ RowBox[{"BeginPackage", "[", RowBox[{ "\"\\"", ",", "\"\\""}], "]"}], ";"}], FontWeight->"Bold"], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"LetterFrequenciesInWord", "::", "usage"}], " ", "=", " ", "\[IndentingNewLine]", "\"\\""}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "::", "usage"}], " ", "=", " ", "\[IndentingNewLine]", "\"\ occurs with the frequency \>\""}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"CaseSensitive", "::", "usage"}], " ", "=", " ", "\"\\""}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"MaxWordLength", "::", "usage"}], " ", "=", "\"\\""}], ";"}], " "}]}], "Input", CellFrame->True, CellChangeTimes->{{3.4411081592586718`*^9, 3.441108181290352*^9}, { 3.441108282736224*^9, 3.441108294873677*^9}, {3.4414714540070543`*^9, 3.441471454597904*^9}, 3.4416094576262093`*^9}, FontWeight->"Plain"], Cell[TextData[{ "Since this is a public import, the functions of \"", StyleBox["PackageOptionChecks`", FontSlant->"Italic"], "\" should now be available :" }], "Text", CellChangeTimes->{{3.4411081870286036`*^9, 3.441108227837283*^9}, { 3.4416178205214624`*^9, 3.441617822914904*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"?", "PackageOptionChecks`*"}]], "Input", CellChangeTimes->{{3.441108232463936*^9, 3.4411082389933248`*^9}, { 3.4414719655225773`*^9, 3.4414719660433264`*^9}, 3.441609459318643*^9}], Cell[BoxData[ DynamicModuleBox[{Typeset`open$$ = True}, PaneSelectorBox[{False-> RowBox[{ OpenerBox[Dynamic[Typeset`open$$], ImageSize->Small], StyleBox["PackageOptionChecks`", "InfoHeading"]}], True->GridBox[{ { RowBox[{ OpenerBox[Dynamic[Typeset`open$$], ImageSize->Small], StyleBox["PackageOptionChecks`", "InfoHeading"]}]}, {GridBox[{ { ButtonBox["ClearOptionsInfo", BaseStyle->"InformationLink", ButtonData:>{ "Info3441778017-6371187", "PackageOptionChecks`ClearOptionsInfo"}, ButtonNote->"PackageOptionChecks`"], ButtonBox["PackageOptionChecksAvailableQ", BaseStyle->"InformationLink", ButtonData:>{ "Info3441778017-6371187", "PackageOptionChecks`PackageOptionChecksAvailableQ"}, ButtonNote->"PackageOptionChecks`"]}, { ButtonBox["GetOptionsInfo", BaseStyle->"InformationLink", ButtonData:>{ "Info3441778017-6371187", "PackageOptionChecks`GetOptionsInfo"}, ButtonNote->"PackageOptionChecks`"], ButtonBox["ResetOptionsInfo", BaseStyle->"InformationLink", ButtonData:>{ "Info3441778017-6371187", "PackageOptionChecks`ResetOptionsInfo"}, ButtonNote->"PackageOptionChecks`"]}, { ButtonBox["OptionCheckIsOn", BaseStyle->"InformationLink", ButtonData:>{ "Info3441778017-6371187", "PackageOptionChecks`OptionCheckIsOn"}, ButtonNote->"PackageOptionChecks`"], ButtonBox["SetOptionsInfo", BaseStyle->"InformationLink", ButtonData:>{ "Info3441778017-6371187", "PackageOptionChecks`SetOptionsInfo"}, ButtonNote->"PackageOptionChecks`"]}, { ButtonBox["OptionCheckOff", BaseStyle->"InformationLink", ButtonData:>{ "Info3441778017-6371187", "PackageOptionChecks`OptionCheckOff"}, ButtonNote->"PackageOptionChecks`"], ButtonBox["TurnOptionChecksOff", BaseStyle->"InformationLink", ButtonData:>{ "Info3441778017-6371187", "PackageOptionChecks`TurnOptionChecksOff"}, ButtonNote->"PackageOptionChecks`"]}, { ButtonBox["OptionCheckOn", BaseStyle->"InformationLink", ButtonData:>{ "Info3441778017-6371187", "PackageOptionChecks`OptionCheckOn"}, ButtonNote->"PackageOptionChecks`"], ButtonBox["TurnOptionChecksOn", BaseStyle->"InformationLink", ButtonData:>{ "Info3441778017-6371187", "PackageOptionChecks`TurnOptionChecksOn"}, ButtonNote->"PackageOptionChecks`"]} }, DefaultBaseStyle->"InfoGrid", GridBoxItemSize->{"Columns" -> {{ Scaled[0.475]}}}]} }, GridBoxAlignment->{"Columns" -> {{Left}}, "Rows" -> {{Baseline}}}]}, Dynamic[Typeset`open$$], ImageSize->Automatic]]], "Print", "InfoCell", CellChangeTimes->{3.441806817552376*^9}] }, Open ]], Cell[TextData[{ "If the predicate < ", StyleBox["PackageOptionChecksAvailableQ", FontWeight->"Bold", FontSlant->"Italic"], " > gives ", StyleBox["True", FontSlant->"Italic"], " (or, in fact, has any value), then the functionality is available. In our \ interactive session this is redundant since we can already see it by looking \ at the list of function names, but if this is used in writing a package, this \ predicate is useful." }], "Text", CellChangeTimes->{{3.441108323875379*^9, 3.441108346628096*^9}, { 3.4411084451998353`*^9, 3.441108539205008*^9}}], Cell[CellGroupData[{ Cell[BoxData["$Context"], "Input", CellChangeTimes->{{3.4411085955159793`*^9, 3.4411085989008465`*^9}}], Cell[BoxData["\<\"LetterFrequencies`\"\>"], "Output", CellChangeTimes->{3.4418068199758606`*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"PackageOptionChecksAvailableQ", "[", "]"}]], "Input", CellChangeTimes->{{3.4411085441721506`*^9, 3.441108552724448*^9}, { 3.441108627431872*^9, 3.441108627501973*^9}}], Cell[BoxData["True"], "Output", CellChangeTimes->{3.441724684209541*^9, 3.4417981957147827`*^9, 3.4418068223693027`*^9}] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell["First step of protection procedure", "Subsubsection", CellChangeTimes->{{3.4416168839247026`*^9, 3.441616896412659*^9}}, FontWeight->"Plain"], Cell[TextData[{ "There are 2 ways to \"declare\" options together with their appropriate \ values (patterns that the rhs of an option should match) : we can do it from \ within the main context or ", StyleBox["`Private`", FontSlant->"Italic"], " subcontext. In both cases, we use < ", StyleBox["SetOptionsInfo", FontWeight->"Bold", FontSlant->"Italic"], " > function for that. In the former case, we can use its brief form which \ needs only the structure describing option information, while in the latter \ we need also to supply the context name explicitly (otherwise it will assume \ that protection is needed for the ", StyleBox["`Private`", FontSlant->"Italic"], " sub-context).\n \n Assuming that we want to restrict the ", StyleBox["CaseSensitive", FontSlant->"Italic"], " option to ", StyleBox["True", FontSlant->"Italic"], " or ", StyleBox["False", FontSlant->"Italic"], " values, and ", StyleBox["MaxWordLength", FontSlant->"Italic"], " option to values less than ", StyleBox["12", FontSlant->"Italic"], " (for instance), the function call will look like :" }], "Text", CellChangeTimes->{{3.441110109523014*^9, 3.4411103799118147`*^9}, { 3.441449800310568*^9, 3.441449840999075*^9}}], Cell[BoxData[ RowBox[{ RowBox[{ StyleBox["If", FontWeight->"Bold"], StyleBox["[", FontWeight->"Bold"], RowBox[{ StyleBox[ RowBox[{"PackageOptionChecksAvailableQ", "[", "]"}], FontWeight->"Bold"], StyleBox[",", FontWeight->"Bold"], StyleBox["\[IndentingNewLine]", FontWeight->"Bold"], RowBox[{ StyleBox["SetOptionsInfo", FontWeight->"Bold"], StyleBox["[", FontWeight->"Bold"], RowBox[{ StyleBox["{", FontWeight->"Bold"], RowBox[{ StyleBox[ RowBox[{"{", RowBox[{"CaseSensitive", ",", RowBox[{"True", "|", "False"}], ",", RowBox[{"{", RowBox[{ RowBox[{ "AllWordsWithLetterFrequency", "\[RuleDelayed]", "$Failed"}], ",", RowBox[{ "LetterFrequenciesInWord", "\[RuleDelayed]", "$Failed"}]}], "}"}]}], "}"}], FontWeight->"Bold"], StyleBox[",", FontWeight->"Bold"], StyleBox["\[IndentingNewLine]", FontWeight->"Bold"], RowBox[{ StyleBox["{", FontWeight->"Bold"], RowBox[{ StyleBox["MaxWordLength", FontWeight->"Bold"], StyleBox[",", FontWeight->"Bold"], StyleBox[ RowBox[{"_", "?", RowBox[{"(", RowBox[{ RowBox[{"#", "\[LessEqual]", " ", "12"}], "&"}], ")"}]}], FontWeight->"Bold"], StyleBox[",", FontWeight->"Bold"], RowBox[{ StyleBox["AllWordsWithLetterFrequency", FontWeight->"Bold"], StyleBox["\[RuleDelayed]", FontWeight->"Bold"], " ", StyleBox["$Failed", FontWeight->"Bold"]}]}], StyleBox["}", FontWeight->"Bold"]}]}], StyleBox["}", FontWeight->"Bold"]}], StyleBox["]", FontWeight->"Bold"]}]}], StyleBox["]", FontWeight->"Bold"]}], StyleBox[";", FontWeight->"Bold"]}]], "Input", CellFrame->True, CellChangeTimes->{{3.441110383977661*^9, 3.4411105149359694`*^9}, { 3.4414714625893955`*^9, 3.4414714906397295`*^9}, {3.44147201179912*^9, 3.441472016245514*^9}, {3.4414732126959248`*^9, 3.4414732182238736`*^9}}, FontWeight->"Plain"], Cell[TextData[{ "Here, the rhs-s of the rules describe the code to be executed in case of \ bad options (more on this later). For reasons to be explained soon, the \ delayed rules (", StyleBox["RuleDelayed", FontSlant->"Italic"], ") in the option protection information structure are mandatory and can not \ be replaced by immediate rules (", StyleBox["Rule", FontSlant->"Italic"], ")." }], "Text", CellChangeTimes->{{3.4411105433768654`*^9, 3.44111062625604*^9}, { 3.441110668096203*^9, 3.44111071347145*^9}, {3.4416146510539923`*^9, 3.4416146995837746`*^9}, {3.4416165221645164`*^9, 3.441616604993619*^9}}], Cell["\<\ We have \"registered\" our options and at the same this gives us \ information about option - taking functions in our package. We now go on with \ our previous implementation - nothing changes here.\ \>", "Text", CellChangeTimes->{{3.4411105433768654`*^9, 3.44111062625604*^9}, { 3.441110668096203*^9, 3.44111071347145*^9}, {3.4416146510539923`*^9, 3.4416147008155456`*^9}, {3.4416147415941825`*^9, 3.4416147693941565`*^9}}], Cell[BoxData[{ RowBox[{ RowBox[{ RowBox[{"Begin", "[", "\"\<`Private`\>\"", "]"}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"Options", "[", "LetterFrequenciesInWord", "]"}], "=", RowBox[{"{", RowBox[{"CaseSensitive", "\[Rule]", " ", "True"}], "}"}]}], ";"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"Options", "[", "AllWordsWithLetterFrequency", "]"}], "=", RowBox[{"{", RowBox[{ RowBox[{"CaseSensitive", "\[Rule]", " ", "True"}], ",", RowBox[{"MaxWordLength", "\[Rule]", " ", "10"}]}], "}"}]}], ";"}], "\n"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"UseOption", "[", RowBox[{"optname_Symbol", ",", "function_", ",", RowBox[{"opts___", "?", "OptionQ"}]}], "]"}], ":=", "\n", "\t", RowBox[{ RowBox[{"optname", "/.", RowBox[{"Flatten", "[", RowBox[{"{", "opts", "}"}], "]"}]}], "/.", RowBox[{"Options", "[", "function", "]"}]}]}], ";"}], "\n"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"With", "[", RowBox[{ RowBox[{"{", RowBox[{"earlyVersion", "=", RowBox[{ RowBox[{"ToExpression", "[", RowBox[{"StringTake", "[", RowBox[{"$Version", ",", "1"}], "]"}], "]"}], "<", "6"}]}], "}"}], ",", "\[IndentingNewLine]", RowBox[{"allWords", "=", "\[IndentingNewLine]", RowBox[{"If", "[", RowBox[{"earlyVersion", ",", "\[IndentingNewLine]", "\t", RowBox[{ RowBox[{"Needs", "[", "\"\\"", "]"}], ";", "\[IndentingNewLine]", "\t", RowBox[{"Take", "[", RowBox[{ RowBox[{ "Miscellaneous`Dictionary`FindWords", "[", "\"\<*\>\"", "]"}], ",", "5000"}], "]"}]}], ",", "\[IndentingNewLine]", "\t", RowBox[{"(*", " ", "else", " ", "*)"}], "\[IndentingNewLine]", "\t", RowBox[{"Take", "[", RowBox[{ RowBox[{"DictionaryLookup", "[", "\"\<*\>\"", "]"}], ",", "5000"}], "]"}]}], "]"}]}]}], "]"}], ";"}], "\[IndentingNewLine]"}], "\n", RowBox[{ RowBox[{ RowBox[{ RowBox[{"frequencies", "[", "x_List", "]"}], ":=", RowBox[{ RowBox[{ RowBox[{"{", RowBox[{ RowBox[{"First", "[", "#", "]"}], ",", RowBox[{"Length", "[", "#", "]"}]}], "}"}], "&"}], "/@", RowBox[{"Split", "[", RowBox[{"Sort", "[", "x", "]"}], "]"}]}]}], ";"}], "\[IndentingNewLine]", "\n"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"LetterFrequenciesInWord", "[", RowBox[{"word_String", ",", RowBox[{"opts___", "?", "OptionQ"}]}], "]"}], ":=", "\[IndentingNewLine]", RowBox[{"With", "[", RowBox[{ RowBox[{"{", RowBox[{"fn", "=", " ", RowBox[{ RowBox[{"If", "[", RowBox[{ RowBox[{"UseOption", "[", RowBox[{ "CaseSensitive", ",", "LetterFrequenciesInWord", ",", "opts"}], "]"}], ",", "\[IndentingNewLine]", "\t", "#", ",", RowBox[{"ToLowerCase", "[", "#", "]"}]}], "]"}], "&"}]}], "}"}], ",", "\[IndentingNewLine]", RowBox[{"frequencies", "[", RowBox[{"Characters", "[", RowBox[{"fn", "[", "word", "]"}], "]"}], "]"}]}], "]"}]}], ";"}], "\[IndentingNewLine]"}], "\n", RowBox[{ RowBox[{ RowBox[{ RowBox[{"frequentLettersExistQ", "[", RowBox[{"word_String", ",", "freq_Integer", ",", RowBox[{"letters", ":", RowBox[{"(", RowBox[{"_String", "|", RowBox[{"{", "__String", "}"}]}], ")"}]}], ",", RowBox[{"opts___", "?", "OptionQ"}]}], "]"}], ":=", RowBox[{ RowBox[{"Intersection", "[", RowBox[{ RowBox[{"Cases", "[", RowBox[{ RowBox[{"LetterFrequenciesInWord", "[", RowBox[{"word", ",", "opts"}], "]"}], ",", RowBox[{ RowBox[{"{", RowBox[{"let_String", ",", "freq"}], "}"}], "\[RuleDelayed]", "let"}]}], "]"}], ",", RowBox[{"Flatten", "[", RowBox[{"{", "letters", "}"}], "]"}]}], "]"}], "=!=", RowBox[{"{", "}"}]}]}], ";"}], "\[IndentingNewLine]", "\n", RowBox[{"(*", " ", RowBox[{ "The", " ", "test", " ", "for", " ", "the", " ", "word", " ", "size", " ", "has", " ", "been", " ", "deliberately", " ", "written", " ", "in", " ", "a", " ", "way", " ", "that", " ", "produces", " ", "all", " ", "words", " ", "if", " ", "the", " ", "value", " ", "of", " ", "MaxWordLength", " ", "option", " ", "is", " ", "inappropriate", " ", RowBox[{"(", RowBox[{"say", ",", " ", RowBox[{"not", " ", "numerical"}]}], ")"}]}], "*)"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{ RowBox[{"letters", ":", RowBox[{"(", RowBox[{"_String", "|", RowBox[{"{", "__String", "}"}]}], ")"}]}], ",", "freq_Integer", ",", RowBox[{"opts___", "?", "OptionQ"}]}], "]"}], ":=", "\[IndentingNewLine]", RowBox[{"With", "[", RowBox[{ RowBox[{"{", RowBox[{"maxLen", " ", "=", " ", RowBox[{"UseOption", "[", RowBox[{ "MaxWordLength", ",", "AllWordsWithLetterFrequency", ",", "opts"}], "]"}]}], "}"}], ",", "\[IndentingNewLine]", RowBox[{"Select", "[", RowBox[{ RowBox[{"Select", "[", RowBox[{"allWords", ",", RowBox[{ RowBox[{"!", RowBox[{"TrueQ", "[", RowBox[{ RowBox[{"StringLength", "[", "#", "]"}], ">", " ", "maxLen"}], "]"}]}], "&"}]}], "]"}], ",", RowBox[{ RowBox[{"frequentLettersExistQ", "[", RowBox[{"#", ",", "freq", ",", "letters", ",", "opts"}], "]"}], "&"}]}], "]"}]}], "]"}]}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{"End", "[", "]"}], ";"}]}], "Input", CellFrame->True, CellChangeTimes->{{3.4411010962926254`*^9, 3.441101162517853*^9}, { 3.4411017126789455`*^9, 3.441101853962101*^9}, {3.441101894480363*^9, 3.4411020214629555`*^9}, {3.44111065504744*^9, 3.441110665732805*^9}, 3.4414393277679696`*^9}, FontWeight->"Plain"] }, Open ]], Cell[CellGroupData[{ Cell["Second step of protection procedure", "Subsubsection", CellChangeTimes->{{3.441616907628787*^9, 3.4416169222698402`*^9}}, FontWeight->"Plain"], Cell[TextData[{ "After the < ", StyleBox["End[] ", FontSlant->"Italic"], "> command, but before the <", StyleBox[" EndPackage[]", FontSlant->"Italic"], " >, we add a command to enable option protection :" }], "Text", CellChangeTimes->{{3.441110716836288*^9, 3.4411107471899347`*^9}, { 3.4416179030801764`*^9, 3.441617903150277*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"If", "[", RowBox[{ RowBox[{"PackageOptionChecksAvailableQ", "[", "]"}], ",", "\[IndentingNewLine]", RowBox[{"TurnOptionChecksOn", "[", "]"}]}], "]"}], ";"}]], "Input", CellFrame->True, CellChangeTimes->{{3.4411107611900654`*^9, 3.4411108076568813`*^9}, { 3.4411128644544115`*^9, 3.441112921826909*^9}, {3.4411130574619427`*^9, 3.4411130611171985`*^9}}], Cell["And finally, ", "Text", CellChangeTimes->{{3.441110811302123*^9, 3.4411108143665295`*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"EndPackage", "[", "]"}], ";"}]], "Input", CellFrame->True, CellChangeTimes->{{3.441110822317963*^9, 3.441110854213827*^9}}, FontWeight->"Plain"], Cell[TextData[{ "As we can see, the original package has been modified in 3 places :\n\n", StyleBox["1.", FontWeight->"Bold"], " In the beginning, in BeginPackage command, we added a declaration for \ public import of \"", StyleBox["PackageOptionChecks`", FontSlant->"Italic"], "\".\n\n", StyleBox["2.", FontWeight->"Bold"], " After the user messages, but before entering the ", StyleBox["`Private`", FontSlant->"Italic"], " subcontext, we added code to \"register\" appropriate option values and \ option - taking functions.This code could be moved to the ", StyleBox["`Private`", FontSlant->"Italic"], " sub - context, but then the ", StyleBox["SetOptionsInfo[]", FontSlant->"Italic"], " function should be given the main context name explicitly as a first \ argument.\n\n", StyleBox["3.", FontWeight->"Bold"], " We called the < ", StyleBox["TurnOptionChecksOn", FontWeight->"Bold", FontSlant->"Italic"], " > function to enable the option - protection. Note that this call also \ \"declares\" the option - carrying functions (first \"registered\" with ", StyleBox["SetOptionsInfo", FontSlant->"Italic"], ") as those that can be protected. It is important for further \ protection/unprotection operations, should these be necessary (see below).\n\n\ This operation also could be moved into a ", StyleBox["`Private`", FontSlant->"Italic"], " sub-context, so long as it is performed after all functions to be \ protected are defined. In this case, however, we would have to pass the \ context name to <", StyleBox["TurnOptionChecksOn", FontSlant->"Italic"], "> explicitly. " }], "Text", CellChangeTimes->{{3.4411108743627996`*^9, 3.441111228902603*^9}, { 3.4414499228868237`*^9, 3.4414499234175873`*^9}, {3.4416166435290303`*^9, 3.4416168021070547`*^9}, 3.4416172439924545`*^9}] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell["Testing the \"protected\" version of our toy package", "Subsection", CellChangeTimes->{{3.441111277502486*^9, 3.441111293064864*^9}, { 3.4416096716539664`*^9, 3.4416096747584305`*^9}, {3.4416097255614815`*^9, 3.441609727794693*^9}}, FontWeight->"Plain"], Cell["\<\ We can now use the same tests as before, to see whether and how the behavior \ of the functions has changed.\ \>", "Text", CellChangeTimes->{{3.4411112332288237`*^9, 3.4411112698014126`*^9}, { 3.441449950025848*^9, 3.4414499510873747`*^9}}], Cell[CellGroupData[{ Cell["Some checks with appropriate option setting:", "Subsubsection", CellChangeTimes->{{3.4411023181195264`*^9, 3.441102326892141*^9}, { 3.441102621295472*^9, 3.44110263167039*^9}}, FontWeight->"Plain"], Cell["The first 3 inputs are ok :", "Text", CellChangeTimes->{{3.4411115491731296`*^9, 3.441111559638178*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"LetterFrequenciesInWord", "[", "\"\\"", "]"}]], "Input", CellChangeTimes->{{3.4411010693538895`*^9, 3.4411010826630273`*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{ RowBox[{"{", RowBox[{"\<\"e\"\>", ",", "4"}], "}"}], ",", RowBox[{"{", RowBox[{"\<\"h\"\>", ",", "1"}], "}"}], ",", RowBox[{"{", RowBox[{"\<\"l\"\>", ",", "1"}], "}"}], ",", RowBox[{"{", RowBox[{"\<\"n\"\>", ",", "1"}], "}"}], ",", RowBox[{"{", RowBox[{"\<\"r\"\>", ",", "1"}], "}"}], ",", RowBox[{"{", RowBox[{"\<\"s\"\>", ",", "2"}], "}"}], ",", RowBox[{"{", RowBox[{"\<\"t\"\>", ",", "1"}], "}"}], ",", RowBox[{"{", RowBox[{"\<\"v\"\>", ",", "1"}], "}"}]}], "}"}]], "Output", CellChangeTimes->{3.4417246958663025`*^9, 3.4417982046776705`*^9, 3.441798892036043*^9, 3.4417993498443394`*^9, 3.4417994534533215`*^9, 3.4418009167874928`*^9, 3.4418044212066*^9, 3.4418048822195044`*^9, 3.4418049944909425`*^9, 3.441806833194869*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3"}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{{3.4411012030861874`*^9, 3.441101240910576*^9}, { 3.4411012900812798`*^9, 3.441101290662115*^9}}], Cell[BoxData[ TagBox[ RowBox[{"{", RowBox[{"\<\"aardvark\"\>", ",", "\<\"aardvarks\"\>", ",", "\<\"acacia\"\>", ",", "\<\"acacias\"\>", ",", "\<\"academia\"\>", ",", "\<\"academical\"\>", ",", "\<\"actuarial\"\>", ",", "\<\"adamant\"\>", ",", RowBox[{"\[LeftSkeleton]", "78", "\[RightSkeleton]"}], ",", "\<\"Atahualpa\"\>", ",", "\<\"Atalanta\"\>", ",", "\<\"ataxia\"\>", ",", "\<\"Athabasca\"\>", ",", "\<\"Athabaskan\"\>", ",", "\<\"attachable\"\>", ",", "\<\"attainable\"\>", ",", "\<\"attractant\"\>"}], "}"}], Short[#, 5]& ]], "Output", CellChangeTimes->{3.4417246981696143`*^9, 3.4417982061297584`*^9, 3.441798893387987*^9, 3.4417993517570896`*^9, 3.441799455095683*^9, 3.4418009182796383`*^9, 3.4418044228790045`*^9, 3.4418048835714483`*^9, 3.4418049959029727`*^9, 3.4418068351376624`*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "False"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{{3.441101267328563*^9, 3.441101302238762*^9}}], Cell[BoxData[ TagBox[ RowBox[{"{", RowBox[{"\<\"Aaliyah\"\>", ",", "\<\"aardvark\"\>", ",", "\<\"aardvarks\"\>", ",", "\<\"Abraham\"\>", ",", "\<\"acacia\"\>", ",", "\<\"acacias\"\>", ",", "\<\"academia\"\>", ",", "\<\"academical\"\>", ",", RowBox[{"\[LeftSkeleton]", "139", "\[RightSkeleton]"}], ",", "\<\"ataxia\"\>", ",", "\<\"Atlanta\"\>", ",", "\<\"attachable\"\>", ",", "\<\"attainable\"\>", ",", "\<\"attractant\"\>", ",", "\<\"Australia\"\>", ",", "\<\"Australian\"\>"}], "}"}], Short[#, 5]& ]], "Output", CellChangeTimes->{3.4417247000222783`*^9, 3.4417982075317745`*^9, 3.4417988945296288`*^9, 3.441799352878702*^9, 3.4417994560871086`*^9, 3.441800919791813*^9, 3.4418044242109203`*^9, 3.4418048847431326`*^9, 3.441804997064643*^9, 3.4418068371806*^9}] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell["Discovering and correcting a flaw in our package", "Subsubsection", CellChangeTimes->{{3.4411133900401664`*^9, 3.44111340775564*^9}}, FontWeight->"Plain"], Cell["\<\ Here we will for the first time see the results of using option protection. \ This seems like a totally legitimate input (and it is!). \ \>", "Text", CellChangeTimes->{{3.441111564344946*^9, 3.4411115786555233`*^9}, { 3.441111648706251*^9, 3.441111696875515*^9}, 3.441113737269458*^9}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "False"}], ",", RowBox[{"MaxWordLength", "\[Rule]", "6"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{{3.4411013545539875`*^9, 3.4411013650991507`*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"LetterFrequenciesInWord", "::", "\<\"optundef\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(MaxWordLength \[Rule] 6\\) is \ unknown\"\>"}]], "Message", CellChangeTimes->{3.4417247036875486`*^9, 3.4417982103257923`*^9, 3.4417988967528257`*^9, 3.4417993553823023`*^9, 3.4417994583804064`*^9, 3.4418009226559315`*^9, 3.441804426113656*^9, 3.4418048912024207`*^9, 3.4418049984766736`*^9, 3.4418068411262736`*^9}], Cell[BoxData[ RowBox[{ RowBox[{"LetterFrequenciesInWord", "::", "\<\"optundef\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(MaxWordLength \[Rule] 6\\) is \ unknown\"\>"}]], "Message", CellChangeTimes->{3.4417247036875486`*^9, 3.4417982103257923`*^9, 3.4417988967528257`*^9, 3.4417993553823023`*^9, 3.4417994583804064`*^9, 3.4418009226559315`*^9, 3.441804426113656*^9, 3.4418048912024207`*^9, 3.4418049984766736`*^9, 3.4418068411362877`*^9}], Cell[BoxData[ RowBox[{ RowBox[{"LetterFrequenciesInWord", "::", "\<\"optundef\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(MaxWordLength \[Rule] 6\\) is \ unknown\"\>"}]], "Message", CellChangeTimes->{3.4417247036875486`*^9, 3.4417982103257923`*^9, 3.4417988967528257`*^9, 3.4417993553823023`*^9, 3.4417994583804064`*^9, 3.4418009226559315`*^9, 3.441804426113656*^9, 3.4418048912024207`*^9, 3.4418049984766736`*^9, 3.441806841176346*^9}], Cell[BoxData[ RowBox[{ RowBox[{"General", "::", "\<\"stop\"\>"}], RowBox[{ ":", " "}], "\<\"Further output of \\!\\(LetterFrequenciesInWord :: \ \\\"optundef\\\"\\) will be suppressed during this calculation. \ \\!\\(\\*ButtonBox[\\\"\[RightSkeleton]\\\", ButtonStyle->\\\"Link\\\", \ ButtonFrame->None, ButtonData:>\\\"paclet:ref/message/General/stop\\\", \ ButtonNote -> \\\"General::stop\\\"]\\)\"\>"}]], "Message", CellChangeTimes->{3.4417247036875486`*^9, 3.4417982103257923`*^9, 3.4417988967528257`*^9, 3.4417993553823023`*^9, 3.4417994583804064`*^9, 3.4418009226559315`*^9, 3.441804426113656*^9, 3.4418048912024207`*^9, 3.4418049984766736`*^9, 3.441806841366619*^9}], Cell[BoxData[ TagBox[ RowBox[{"{", "}"}], Short[#, 5]& ]], "Output", CellChangeTimes->{3.4417247042283263`*^9, 3.4417982108665695`*^9, 3.441798897313632*^9, 3.4417993559330945`*^9, 3.441799459021328*^9, 3.441800923296853*^9, 3.4418044266544333`*^9, 3.441804891753213*^9, 3.441804999117595*^9, 3.441806841657037*^9}] }, Open ]], Cell["This output reflects an internal defect of our package.", "Text", CellChangeTimes->{{3.4411137461722593`*^9, 3.4411137473239155`*^9}, { 3.441449982512562*^9, 3.441449983704275*^9}}], Cell[TextData[{ "The problem is that the function ", StyleBox["AllWordsWithLetterFrequency", FontSlant->"Italic"], ", which does have an option < ", StyleBox["MaxWordLength", FontSlant->"Italic"], " > (as \"registered\" by ", StyleBox["SetOptionsInfo", FontSlant->"Italic"], "), passes all options it receives to < ", StyleBox["LetterFrequenciesInWord", FontSlant->"Italic"], " >, which is also a public function, registered with < ", StyleBox["SetOptionsInfo", FontSlant->"Italic"], " >, and which DOES NOT have this option. In other words, the options passed \ to ", StyleBox["LetterFrequenciesInWord", FontSlant->"Italic"], " have not been filtered properly, and our option - checking mechanism has \ caught this flaw. To correct this, we will now redefine the function by \ including the proper options filtering (I will use ", StyleBox["FilterRules", FontSlant->"Italic"], ", which is the system function in v.6.0+, and for versions 5.2 or earlier, \ similar functionality is provided by the ", StyleBox["Utilities`FilterOptions`", FontSlant->"Italic"], " package - see also the book \"Programming in ", StyleBox["Mathematica", FontSlant->"Italic"], "\" by Roman Maeder)." }], "Text", CellChangeTimes->{{3.441111583913083*^9, 3.4411115887900963`*^9}, { 3.441111634175357*^9, 3.4411116442097855`*^9}, {3.441111707140275*^9, 3.4411119658723135`*^9}, {3.44111378454744*^9, 3.4411137864902334`*^9}, { 3.4416092293679905`*^9, 3.4416092575284834`*^9}}], Cell[BoxData[{ RowBox[{ RowBox[{ RowBox[{"BeginPackage", "[", RowBox[{ "\"\\"", ",", "\"\\""}], "]"}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"Begin", "[", "\"\<`Private`\>\"", "]"}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"ClearAll", "[", "AllWordsWithLetterFrequency", "]"}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{ StyleBox["With", FontWeight->"Bold"], StyleBox["[", FontWeight->"Bold"], RowBox[{ StyleBox[ RowBox[{"{", RowBox[{"earlyVersion", "=", RowBox[{ RowBox[{"ToExpression", "[", RowBox[{"StringTake", "[", RowBox[{"$Version", ",", "1"}], "]"}], "]"}], "<", "6"}]}], "}"}], FontWeight->"Bold"], StyleBox[",", FontWeight->"Bold"], StyleBox["\[IndentingNewLine]", FontWeight->"Bold"], RowBox[{ StyleBox[ RowBox[{"If", "[", RowBox[{"earlyVersion", ",", RowBox[{"Needs", "[", "\"\\"", "]"}]}], "]"}], FontWeight->"Bold"], StyleBox[";", FontWeight->"Bold"], StyleBox["\[IndentingNewLine]", FontWeight->"Bold"], "\[IndentingNewLine]", RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{ RowBox[{"letters", ":", RowBox[{"(", RowBox[{"_String", "|", RowBox[{"{", "__String", "}"}]}], ")"}]}], ",", "freq_Integer", ",", RowBox[{"opts___", "?", "OptionQ"}]}], "]"}], ":=", "\[IndentingNewLine]", RowBox[{"With", "[", RowBox[{ RowBox[{"{", RowBox[{"maxLen", " ", "=", " ", RowBox[{"UseOption", "[", RowBox[{ "MaxWordLength", ",", "AllWordsWithLetterFrequency", ",", "opts"}], "]"}]}], "}"}], ",", "\[IndentingNewLine]", RowBox[{"Select", "[", RowBox[{ RowBox[{"Select", "[", RowBox[{"allWords", ",", RowBox[{ RowBox[{"!", RowBox[{"TrueQ", "[", RowBox[{ RowBox[{"StringLength", "[", "#", "]"}], ">", " ", "maxLen"}], "]"}]}], "&"}]}], "]"}], ",", RowBox[{ RowBox[{"frequentLettersExistQ", "[", RowBox[{ "#", ",", "freq", ",", "letters", ",", "\[IndentingNewLine]", RowBox[{ StyleBox["If", FontWeight->"Bold"], StyleBox["[", FontWeight->"Bold"], RowBox[{ StyleBox["earlyVersion", FontWeight->"Bold"], StyleBox[",", FontWeight->"Bold"], StyleBox["\[IndentingNewLine]", FontWeight->"Bold"], StyleBox[ RowBox[{ "Utilities`FilterOptions`FilterOptions", "[", "\[IndentingNewLine]", RowBox[{"LetterFrequenciesInWord", ",", RowBox[{"{", "opts", "}"}]}], "]"}], FontWeight->"Bold"], ",", "\[IndentingNewLine]", RowBox[{"(*", " ", "else", " ", "*)"}], "\[IndentingNewLine]", StyleBox[ RowBox[{"Sequence", "@@", RowBox[{"FilterRules", "[", RowBox[{ RowBox[{"{", "opts", "}"}], ",", RowBox[{ "Options", "[", "LetterFrequenciesInWord", "]"}]}], "]"}]}], FontWeight->"Bold"]}], StyleBox["]", FontWeight->"Bold"]}]}], StyleBox["]", FontWeight->"Bold"]}], "&"}]}], "]"}]}], "]"}]}], ";"}]}], "\[IndentingNewLine]", StyleBox["]", FontWeight->"Bold"]}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"End", "[", "]"}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"If", "[", RowBox[{ RowBox[{"PackageOptionChecksAvailableQ", "[", "]"}], ",", "\[IndentingNewLine]", RowBox[{"TurnOptionChecksOn", "[", "]"}]}], "]"}], ";"}], "\[IndentingNewLine]"}], "\[IndentingNewLine]", RowBox[{ RowBox[{"EndPackage", "[", "]"}], ";"}]}], "Input", CellFrame->True, CellChangeTimes->{{3.441111996205931*^9, 3.441112061650035*^9}, { 3.441112192307912*^9, 3.4411122661540976`*^9}, {3.4411131231263633`*^9, 3.4411131234067664`*^9}, {3.441472100346445*^9, 3.4414721007570353`*^9}, 3.4416094656878014`*^9}, FontWeight->"Plain"], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "False"}], ",", RowBox[{"MaxWordLength", "\[Rule]", "6"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input"], Cell[BoxData[ TagBox[ RowBox[{"{", RowBox[{"\<\"acacia\"\>", ",", "\<\"Acadia\"\>", ",", "\<\"Adana\"\>", ",", "\<\"Adhara\"\>", ",", "\<\"Agana\"\>", ",", "\<\"Agatha\"\>", ",", "\<\"Aglaia\"\>", ",", "\<\"Alana\"\>", ",", "\<\"Alaska\"\>", ",", "\<\"alpaca\"\>", ",", RowBox[{"\[LeftSkeleton]", "4", "\[RightSkeleton]"}], ",", "\<\"Arabia\"\>", ",", "\<\"Arafat\"\>", ",", "\<\"Ararat\"\>", ",", "\<\"Arawak\"\>", ",", "\<\"arcana\"\>", ",", "\<\"armada\"\>", ",", "\<\"Asama\"\>", ",", "\<\"Asmara\"\>", ",", "\<\"Astana\"\>", ",", "\<\"ataxia\"\>"}], "}"}], Short[#, 5]& ]], "Output", CellChangeTimes->{ 3.4417247090953245`*^9, 3.4417982170454545`*^9, 3.4417989250935774`*^9, 3.4417993613008127`*^9, 3.4417994702174273`*^9, 3.441800927382728*^9, 3.4418044433484383`*^9, 3.4418048960393763`*^9, 3.441805003273571*^9, { 3.441806846814453*^9, 3.4418068708389983`*^9}}] }, Open ]], Cell[TextData[{ "Note that we had to execute ", StyleBox["TurnOptionChecksOn[]", FontWeight->"Bold", FontSlant->"Italic"], " again to update the \"protection\" since one of the functions has been \ redefined (in principle, one may probably skip this unless any signatures in \ original function definitions changed or new option - taking definition has \ been introduced, but it is safer this way. Besides, we are in the debugging \ stage now - in fully debugged package there is normally no need in calling ", StyleBox["TurnOptionChecksOn", FontSlant->"Italic"], " more than once )" }], "Text", CellChangeTimes->{{3.441450035248392*^9, 3.441450049138365*^9}}] }, Open ]], Cell[CellGroupData[{ Cell["Passing options with inappropriate option settings:", "Subsubsection", CellChangeTimes->{{3.4411023371068287`*^9, 3.4411023870886993`*^9}, { 3.441102643227008*^9, 3.44110264978644*^9}, 3.44111354604449*^9}, FontWeight->"Plain"], Cell[TextData[{ "Now we use the same improper inputs as before, and we see that the now \ invoked option protection causes the functions to issue error messages and \ return ", StyleBox["$Failed", FontSlant->"Italic"], "." }], "Text", CellChangeTimes->{{3.4411134356257153`*^9, 3.4411134387802515`*^9}, { 3.441113473810622*^9, 3.4411135313633795`*^9}, {3.441450085550723*^9, 3.4414500899170017`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "Fals"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{3.4411013259628754`*^9}], Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(CaseSensitive \[Rule] Fals\\) is invalid. \ \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(True | False\\) \ \"\>"}]], "Message", CellChangeTimes->{3.4417247117291117`*^9, 3.4417982196892557`*^9, 3.4417989288189344`*^9, 3.441799364265075*^9, 3.441799474583706*^9, 3.4418009300265293`*^9, 3.4418044459321537`*^9, 3.4418048994843297`*^9, 3.441805006868741*^9, 3.441806873582944*^9}], Cell[BoxData[ TagBox["$Failed", Short[#, 5]& ]], "Output", CellChangeTimes->{3.4417247117291117`*^9, 3.4417982196992702`*^9, 3.4417989288489776`*^9, 3.441799364305133*^9, 3.4417994746137486`*^9, 3.4418009300766015`*^9, 3.441804445972211*^9, 3.441804899514373*^9, 3.4418050068987837`*^9, 3.4418068736230016`*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "Fals"}], ",", RowBox[{"a", "\[Rule]", "b"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{{3.4417994859700785`*^9, 3.4417994874722385`*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(CaseSensitive \[Rule] Fals\\) is invalid. \ \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(True | False\\) \ \"\>"}]], "Message", "MSG", CellChangeTimes->{3.441799488163232*^9, 3.4418009337518864`*^9, 3.441804447464357*^9, 3.4418050147000017`*^9, 3.441806883196768*^9}], Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "::", "\<\"optundef\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(a \[Rule] b\\) is unknown\"\>"}]], \ "Message", "MSG", CellChangeTimes->{3.441799488163232*^9, 3.4418009337518864`*^9, 3.441804447464357*^9, 3.4418050147000017`*^9, 3.4418068840580063`*^9}], Cell[BoxData[ TagBox["$Failed", Short[#, 5]& ]], "Output", CellChangeTimes->{3.4417994891146*^9, 3.4418009348134127`*^9, 3.4418044484257393`*^9, 3.441805015591283*^9, 3.441806884098064*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "False"}], ",", RowBox[{"MaxWordLength", "\[Rule]", "\"\\""}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{{3.441101380110736*^9, 3.4411013819433713`*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(MaxWordLength \[Rule] \\\"a\\\"\\) is \ invalid. \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(_ ? \ \\(\\((\\(\\(\\(#1 \[LessEqual] 12\\)\\) &\\))\\)\\)\\) \"\>"}]], "Message", CellChangeTimes->{3.4417247138020926`*^9, 3.4417982216120205`*^9, 3.441799383242363*^9, 3.4417994972362785`*^9, 3.441800947481629*^9, 3.441804450678979*^9, 3.441805020468296*^9, 3.44180689125836*^9}], Cell[BoxData[ TagBox["$Failed", Short[#, 5]& ]], "Output", CellChangeTimes->{3.441724713812107*^9, 3.4417982216620927`*^9, 3.441799383282421*^9, 3.4417994972863503`*^9, 3.441800947511672*^9, 3.441804450719037*^9, 3.441805020518368*^9, 3.4418068912884035`*^9}] }, Open ]] }, Open ]] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell["Finer control over option protection", "Section", CellChangeTimes->{{3.4411135507813005`*^9, 3.441113568166299*^9}, { 3.4416152780555763`*^9, 3.441615278325965*^9}}, FontWeight->"Plain"], Cell[CellGroupData[{ Cell["Protection on the level of the entire package (context)", "Subsection", CellChangeTimes->{{3.4411169602739105`*^9, 3.441116984969421*^9}}, FontWeight->"Plain"], Cell["\<\ There are ways to switch the protection off and on again, both on the level \ of entire package or individual functions.\ \>", "Text", CellChangeTimes->{{3.4411135702492943`*^9, 3.4411135990907664`*^9}, 3.4411136315474367`*^9}], Cell["This will switch off the protection for an entire package :", "Text", CellChangeTimes->{{3.4411136332498846`*^9, 3.441113647390218*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"TurnOptionChecksOff", "[", "\"\\"", "]"}]], "Input", CellChangeTimes->{{3.4411138353104334`*^9, 3.441113865043187*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{"AllWordsWithLetterFrequency", ",", "LetterFrequenciesInWord"}], "}"}]], "Output", CellChangeTimes->{3.4417247177477665`*^9, 3.441798233178653*^9, 3.4418009531497793`*^9, 3.4418044545144944`*^9, 3.4418050412882338`*^9, 3.4418069153830495`*^9}] }, Open ]], Cell["\<\ We see that our improper inputs are again consumed without any hesitation :\ \>", "Text", CellChangeTimes->{{3.441113896107856*^9, 3.441113925289818*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "Fals"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{3.4411013259628754`*^9}], Cell[BoxData[ TagBox[ RowBox[{"{", "}"}], Short[#, 5]& ]], "Output", CellChangeTimes->{3.441724719840776*^9, 3.4417982349512014`*^9, 3.441800954942357*^9, 3.4418044567076483`*^9, 3.44180504294061*^9, 3.441806917195656*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "False"}], ",", RowBox[{"MaxWordLength", "\[Rule]", "\"\\""}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{{3.441101380110736*^9, 3.4411013819433713`*^9}}], Cell[BoxData[ TagBox[ RowBox[{"{", RowBox[{"\<\"Aaliyah\"\>", ",", "\<\"aardvark\"\>", ",", "\<\"aardvarks\"\>", ",", "\<\"aberrational\"\>", ",", "\<\"Abraham\"\>", ",", "\<\"acacia\"\>", ",", RowBox[{"\[LeftSkeleton]", "252", "\[RightSkeleton]"}], ",", "\<\"Australia\"\>", ",", "\<\"Australian\"\>", ",", "\<\"Australians\"\>", ",", "\<\"authoritarian\"\>", ",", "\<\"authoritarianism\"\>", ",", "\<\"authoritarians\"\>"}], "}"}], Short[#, 5]& ]], "Output", CellChangeTimes->{3.441724722704894*^9, 3.4417982366336207`*^9, 3.4418009571555395`*^9, 3.44180445835001*^9, 3.441805044452784*^9, 3.441806918868061*^9}] }, Open ]], Cell[TextData[{ "We now turn the protection on again. Note however that this time, since we \ are outside the context of our package, we have to explicitly supply the name \ of the context to ", StyleBox["TurnOptionChecksOn", FontSlant->"Italic"], ". Otherwise, it will attempt to turn the protection on for the current \ context :" }], "Text", CellChangeTimes->{{3.4411139299164705`*^9, 3.441113988210293*^9}, { 3.4411167304935026`*^9, 3.4411167327868*^9}, {3.441116853270046*^9, 3.441116871866787*^9}, {3.4414385852002096`*^9, 3.4414385977382383`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"TurnOptionChecksOn", "[", "]"}]], "Input", CellChangeTimes->{{3.4411139938784432`*^9, 3.441113993948544*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"TurnOptionChecksOn", "::", "\<\"noinfo\"\>"}], RowBox[{ ":", " "}], "\<\"There is no information available about the patterns that \ options for the functions in the context \\!\\(\\\"Global`\\\"\\) must match. \ Perhaps, the SetOptionsInfo function has not yet been called for the context \ \\!\\(\\\"Global`\\\"\\).\"\>"}]], "Message", CellChangeTimes->{3.4417247255690126`*^9, 3.4417982385864286`*^9, 3.4418009609309683`*^9, 3.4418044613543296`*^9, 3.441805046405592*^9, 3.4418069200898175`*^9}], Cell[BoxData[ RowBox[{"TurnOptionChecksOn", "[", "\<\"Global`\"\>", "]"}]], "Output", CellChangeTimes->{3.4417247255690126`*^9, 3.4417982386264863`*^9, 3.4418009609710255`*^9, 3.4418044613843727`*^9, 3.4418050464456496`*^9, 3.4418069201198606`*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"TurnOptionChecksOn", "[", "\"\\"", "]"}]], "Input", CellChangeTimes->{3.4411169000172653`*^9}], Cell[BoxData[ RowBox[{"{", RowBox[{"AllWordsWithLetterFrequency", ",", "LetterFrequenciesInWord"}], "}"}]], "Output", CellChangeTimes->{3.441724726750712*^9, 3.4417982398382287`*^9, 3.44180096398536*^9, 3.441804462576086*^9, 3.4418050477174788`*^9, 3.441806921111286*^9}] }, Open ]], Cell["We now check the same inputs as before :", "Text", CellChangeTimes->{{3.44111691238505*^9, 3.4411169264552813`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "Fals"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{3.4411013259628754`*^9}], Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(CaseSensitive \[Rule] Fals\\) is invalid. \ \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(True | False\\) \ \"\>"}]], "Message", CellChangeTimes->{3.4417247282328434`*^9, 3.4417982414104896`*^9, 3.4418009656076927`*^9, 3.441804464228462*^9, 3.4418050489893074`*^9, 3.4418069229739647`*^9}], Cell[BoxData[ TagBox["$Failed", Short[#, 5]& ]], "Output", CellChangeTimes->{3.4417247282328434`*^9, 3.4417982414405327`*^9, 3.4418009656477504`*^9, 3.4418044642685204`*^9, 3.441805049039379*^9, 3.4418069230140224`*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "False"}], ",", RowBox[{"MaxWordLength", "\[Rule]", "\"\\""}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{{3.441101380110736*^9, 3.4411013819433713`*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(MaxWordLength \[Rule] \\\"a\\\"\\) is \ invalid. \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(_ ? \ \\(\\((\\(\\(\\(#1 \[LessEqual] 12\\)\\) &\\))\\)\\)\\) \"\>"}]], "Message", CellChangeTimes->{3.441724729785075*^9, 3.4417982428826065`*^9, 3.4418009680512066`*^9, 3.4418044695561233`*^9, 3.4418050516531377`*^9, 3.441806924576269*^9}], Cell[BoxData[ TagBox["$Failed", Short[#, 5]& ]], "Output", CellChangeTimes->{3.441724729785075*^9, 3.4417982429126496`*^9, 3.441800968091264*^9, 3.441804469596181*^9, 3.4418050516931953`*^9, 3.4418069246163263`*^9}] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell["Protection on the level of individual functions", "Subsection", CellChangeTimes->{{3.441116993862208*^9, 3.4411170080025406`*^9}}, FontWeight->"Plain"], Cell[TextData[{ "The pair of commands ", StyleBox["OptionCheckOn", FontWeight->"Bold", FontSlant->"Italic"], "/", StyleBox["OptionCheckOff", FontWeight->"Bold", FontSlant->"Italic"], " provide finer control over the option protection - on the level of \ individual functions. In addition, the predicate ", StyleBox["OptionCheckIsOn", FontWeight->"Bold", FontSlant->"Italic"], " allows to test the current protection status of each function:" }], "Text", CellChangeTimes->{{3.4411170126191792`*^9, 3.441117130678941*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"OptionCheckIsOn", "[", "AllWordsWithLetterFrequency", "]"}]], "Input", CellChangeTimes->{{3.441117132181101*^9, 3.4411171463815203`*^9}}], Cell[BoxData["True"], "Output", CellChangeTimes->{3.441724731507552*^9, 3.4417982451658897`*^9, 3.4418009718066063`*^9, 3.4418044725203857`*^9, 3.4418050620580993`*^9, 3.4418069273101997`*^9}] }, Open ]], Cell["\<\ Here we switch the protection off for AllWordsWithLetterFrequency function. \ \>", "Text", CellChangeTimes->{{3.4411171746020994`*^9, 3.4411172057268543`*^9}, 3.441117272032197*^9}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"OptionCheckOff", "[", "AllWordsWithLetterFrequency", "]"}]], "Input",\ CellChangeTimes->{{3.4411171517592525`*^9, 3.441117155544696*^9}}], Cell[BoxData[ RowBox[{"{", "}"}]], "Output", CellChangeTimes->{3.441724732278661*^9, 3.44179824748923*^9, 3.4418009738395295`*^9, 3.441804473451725*^9, 3.4418050631897264`*^9, 3.4418069283416834`*^9}] }, Open ]], Cell["The other function remains protected :", "Text"], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"OptionCheckIsOn", "/@", RowBox[{"{", RowBox[{"AllWordsWithLetterFrequency", ",", "LetterFrequenciesInWord"}], "}"}]}]], "Input", CellChangeTimes->{{3.4411172129572515`*^9, 3.4411172187956467`*^9}, 3.441117253505557*^9}], Cell[BoxData[ RowBox[{"{", RowBox[{"False", ",", "True"}], "}"}]], "Output", CellChangeTimes->{3.441724733590547*^9, 3.4417982490114193`*^9, 3.4418009757622943`*^9, 3.4418044745533085`*^9, 3.4418050646618433`*^9, 3.441806929593483*^9}] }, Open ]], Cell["We try again one of our erroneous inputs :", "Text", CellChangeTimes->{{3.4411172785315423`*^9, 3.441117289317051*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "False"}], ",", RowBox[{"MaxWordLength", "\[Rule]", "\"\\""}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input"], Cell[BoxData[ TagBox[ RowBox[{"{", RowBox[{"\<\"Aaliyah\"\>", ",", "\<\"aardvark\"\>", ",", "\<\"aardvarks\"\>", ",", "\<\"aberrational\"\>", ",", "\<\"Abraham\"\>", ",", "\<\"acacia\"\>", ",", RowBox[{"\[LeftSkeleton]", "252", "\[RightSkeleton]"}], ",", "\<\"Australia\"\>", ",", "\<\"Australian\"\>", ",", "\<\"Australians\"\>", ",", "\<\"authoritarian\"\>", ",", "\<\"authoritarianism\"\>", ",", "\<\"authoritarians\"\>"}], "}"}], Short[#, 5]& ]], "Output", CellChangeTimes->{3.4417247362243347`*^9, 3.441798251915595*^9, 3.4418009783860674`*^9, 3.4418044767064047`*^9, 3.441805067035256*^9, 3.441806931686493*^9}] }, Open ]], Cell["\<\ Now it is again readily consumed. We now turn the protection on again :\ \>", "Text", CellChangeTimes->{{3.4411172965875053`*^9, 3.4411173128809347`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"OptionCheckOn", "[", "AllWordsWithLetterFrequency", "]"}]], "Input",\ CellChangeTimes->{{3.4411173236964865`*^9, 3.4411173244776096`*^9}}], Cell[BoxData[ RowBox[{"{", "}"}]], "Output", CellChangeTimes->{3.4417247364546657`*^9, 3.4417982539985905`*^9, 3.4418009803889475`*^9, 3.4418044781484785`*^9, 3.4418050672255297`*^9, 3.441806933118552*^9}] }, Open ]], Cell["Check :", "Text", CellChangeTimes->{{3.4414501734370975`*^9, 3.4414501750694447`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"OptionCheckIsOn", "/@", RowBox[{"{", RowBox[{"AllWordsWithLetterFrequency", ",", "LetterFrequenciesInWord"}], "}"}]}]], "Input"], Cell[BoxData[ RowBox[{"{", RowBox[{"True", ",", "True"}], "}"}]], "Output", CellChangeTimes->{3.4417247382172003`*^9, 3.4417982559513984`*^9, 3.4418009820713663`*^9, 3.4418044795204515`*^9, 3.4418050686676035`*^9, 3.4418069345506115`*^9}] }, Open ]], Cell["And now :", "Text", CellChangeTimes->{{3.4414501816689343`*^9, 3.441450183231181*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "False"}], ",", RowBox[{"MaxWordLength", "\[Rule]", "\"\\""}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input"], Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(MaxWordLength \[Rule] \\\"a\\\"\\) is \ invalid. \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(_ ? \ \\(\\((\\(\\(\\(#1 \[LessEqual] 12\\)\\) &\\))\\)\\)\\) \"\>"}]], "Message", CellChangeTimes->{3.441724739238669*^9, 3.4417982576137886`*^9, 3.441800984915456*^9, 3.441804480521891*^9, 3.4418050696890717`*^9, 3.4418069355320225`*^9}], Cell[BoxData[ TagBox["$Failed", Short[#, 5]& ]], "Output", CellChangeTimes->{3.441724739288741*^9, 3.4417982576538467`*^9, 3.441800984955514*^9, 3.441804480561949*^9, 3.4418050697391443`*^9, 3.4418069355620656`*^9}] }, Open ]], Cell["\<\ It may make sense to switch off the option protection to improve efficiency, \ in case if the function is very frequently called, not very computationally \ intensive and when at the same time one can be sure that all the options \ passed to it do make sense. Technically we can distinguish 2 possibilities : \ either the user of the package switches the protection off externally \ (outside the package), or, when the user of a given function is another \ function from the same package, it does so internally (from within the \ package). In the latter case usually switching the protection off is \ temporary, and the protection is restored after the second function is done \ with the job.\ \>", "Text", CellChangeTimes->{{3.4411174078975616`*^9, 3.4411177148188925`*^9}}] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell["\<\ Changing option-protecting information from outside of the package\ \>", "Section", CellChangeTimes->{{3.441117743389976*^9, 3.441117761165536*^9}, { 3.4414506218118286`*^9, 3.441450631786171*^9}, {3.441615426328782*^9, 3.4416154269697037`*^9}}, FontWeight->"Plain"], Cell["\<\ It may be necessary to \"re-register\" and then re - protect the functions of \ a given package from the outside of the package. This may be needed either \ for convenience purposes (for instance, if we are debugging the package), or \ if the protection for a given function or set of functions has to be modified \ or removed for some options.\ \>", "Text", CellChangeTimes->{{3.44111776376928*^9, 3.4411178439645953`*^9}, { 3.4411288351892*^9, 3.441128865032112*^9}, {3.4414502134145823`*^9, 3.4414502288668013`*^9}}], Cell[CellGroupData[{ Cell["Details", "Subsection", CellChangeTimes->{{3.4416150566472063`*^9, 3.4416150591508064`*^9}}, FontWeight->"Plain"], Cell[CellGroupData[{ Cell["Several contexts", "Subsubsection", CellChangeTimes->{{3.441803638180664*^9, 3.441803646642832*^9}}, FontWeight->"Plain"], Cell["\<\ Before we proceed, we will define a simple function in the Global` context, \ to illustrate that we can set option - protecting information for several \ contexts at the same time\ \>", "Text", CellChangeTimes->{{3.441803413958248*^9, 3.441803476668421*^9}}], Cell[BoxData[{ RowBox[{ RowBox[{"ClearAll", "[", "getPrimes", "]"}], ";"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"Options", "[", "getPrimes", "]"}], "=", RowBox[{"{", RowBox[{"MaxPrime", "\[Rule]", " ", "1000"}], "}"}]}], ";"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"getPrimes", "[", RowBox[{ RowBox[{"n_Integer", "?", "Positive"}], ",", RowBox[{"opts___", "?", "OptionQ"}]}], "]"}], ":=", "\[IndentingNewLine]", RowBox[{"With", "[", RowBox[{ RowBox[{"{", RowBox[{"max", " ", "=", " ", RowBox[{ RowBox[{"MaxPrime", "/.", RowBox[{"Flatten", "[", RowBox[{"{", "opts", "}"}], "]"}]}], "/.", RowBox[{"Options", "[", "getPrimes", "]"}]}]}], "}"}], ",", "\[IndentingNewLine]", RowBox[{"Module", "[", RowBox[{ RowBox[{"{", RowBox[{ RowBox[{"num", "=", "0"}], ",", RowBox[{"current", "=", "0"}]}], "}"}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"Reap", "[", RowBox[{"While", "[", RowBox[{ RowBox[{ RowBox[{"num", "<", " ", "n"}], "&&", RowBox[{"current", "<", "max"}]}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"If", "[", RowBox[{ RowBox[{"PrimeQ", "[", "#", "]"}], ",", RowBox[{ RowBox[{"Sow", "[", "#", "]"}], ";", RowBox[{"num", "++"}]}]}], "]"}], "&"}], "[", RowBox[{"current", "++"}], "]"}]}], "]"}], "]"}], "[", RowBox[{"[", RowBox[{"2", ",", "1"}], "]"}], "]"}]}], "]"}]}], "]"}]}], ";"}]}], "Input", CellChangeTimes->{{3.4418029306432753`*^9, 3.441803210906274*^9}, { 3.441803248700619*^9, 3.441803331559765*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"getPrimes", "[", "10", "]"}]], "Input", CellChangeTimes->{{3.441803178119128*^9, 3.4418031917487264`*^9}, { 3.4418033074150467`*^9, 3.4418033538017473`*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{ "2", ",", "3", ",", "5", ",", "7", ",", "11", ",", "13", ",", "17", ",", "19", ",", "23", ",", "29"}], "}"}]], "Output", CellChangeTimes->{{3.4418031848387904`*^9, 3.4418032135600896`*^9}, { 3.441803276780997*^9, 3.4418033543024673`*^9}, 3.4418044862401133`*^9, 3.4418050749666605`*^9, 3.4418069411801443`*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"getPrimes", "[", RowBox[{"10", ",", RowBox[{"MaxPrime", "\[Rule]", "6"}]}], "]"}]], "Input", CellChangeTimes->{{3.4418044954333324`*^9, 3.4418044986078978`*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{"2", ",", "3", ",", "5"}], "}"}]], "Output", CellChangeTimes->{3.441804500300331*^9, 3.441805077229915*^9, 3.4418069428926067`*^9}] }, Open ]], Cell["\<\ Here is what happens as a result of option passed with inappropriate value :\ \ \>", "Text", CellChangeTimes->{{3.441804513008605*^9, 3.441804540678392*^9}, { 3.4418069526366177`*^9, 3.4418069659257264`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"getPrimes", "[", RowBox[{"10", ",", RowBox[{"MaxPrime", "\[Rule]", "\"\\""}]}], "]"}]], "Input", CellChangeTimes->{{3.441804506248885*^9, 3.4418045076208577`*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"Part", "::", "\<\"partw\"\>"}], RowBox[{ ":", " "}], "\<\"Part \\!\\(1\\) of \\!\\({}\\) does not exist. \ \\!\\(\\*ButtonBox[\\\"\[RightSkeleton]\\\", ButtonStyle->\\\"Link\\\", \ ButtonFrame->None, ButtonData:>\\\"paclet:ref/message/General/partw\\\", \ ButtonNote -> \\\"Part::partw\\\"]\\)\"\>"}]], "Message", "MSG", CellChangeTimes->{ 3.4418045083519087`*^9, 3.4418050791727085`*^9, {3.441806946317531*^9, 3.441806968078822*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"{", RowBox[{"Null", ",", RowBox[{"{", "}"}]}], "}"}], "\[LeftDoubleBracket]", RowBox[{"2", ",", "1"}], "\[RightDoubleBracket]"}]], "Output", CellChangeTimes->{ 3.441804508411995*^9, 3.4418050792127666`*^9, {3.441806946347574*^9, 3.4418069680888367`*^9}}] }, Open ]], Cell["\<\ Without looking at the implementation details, the output provides no clue \ about the reason. We now set up the protection :\ \>", "Text", CellChangeTimes->{{3.4418046289453135`*^9, 3.4418046776653695`*^9}}], Cell[CellGroupData[{ Cell[BoxData[{ RowBox[{ RowBox[{"SetOptionsInfo", "[", RowBox[{"{", RowBox[{"{", RowBox[{"MaxPrime", ",", RowBox[{"_Integer", "?", "Positive"}], ",", RowBox[{"getPrimes", "\[RuleDelayed]", " ", "$Failed"}]}], "}"}], "}"}], "]"}], ";"}], "\[IndentingNewLine]", RowBox[{"TurnOptionChecksOn", "[", "]"}]}], "Input", CellChangeTimes->{{3.441802854583907*^9, 3.441802927709056*^9}, { 3.4418033750623183`*^9, 3.44180337895792*^9}, {3.4418046879902163`*^9, 3.4418046940889854`*^9}}], Cell[BoxData[ RowBox[{"{", "getPrimes", "}"}]], "Output", CellChangeTimes->{3.441804694860094*^9, 3.4418050811455455`*^9, 3.441806979254893*^9}] }, Open ]], Cell["Now the reason is clear :", "Text", CellChangeTimes->{{3.4418047053752146`*^9, 3.441804710021896*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"getPrimes", "[", RowBox[{"10", ",", RowBox[{"MaxPrime", "\[Rule]", "\"\\""}]}], "]"}]], "Input"], Cell[BoxData[ RowBox[{ RowBox[{"getPrimes", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(MaxPrime \[Rule] \\\"a\\\"\\) is invalid. \ \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(_Integer ? \ Positive\\) \"\>"}]], "Message", "MSG", CellChangeTimes->{{3.4418045587443695`*^9, 3.4418045856530623`*^9}, 3.4418047037528815`*^9, 3.4418050834388433`*^9, 3.441806983080394*^9}], Cell[BoxData["$Failed"], "Output", CellChangeTimes->{{3.4418045588044558`*^9, 3.44180458569312*^9}, 3.4418047037829247`*^9, 3.4418050834688864`*^9, 3.4418069830904083`*^9}] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell["Illustration", "Subsubsection", CellChangeTimes->{{3.441803673000733*^9, 3.441803676255413*^9}}, FontWeight->"Plain"], Cell[TextData[{ "There are 2 functions available to to \"re-register\" and then re - protect \ the functions of a given package from the outside of the package: ", StyleBox["ResetOptionsInfo", FontWeight->"Bold", FontSlant->"Italic"], " and ", StyleBox["ClearOptionsInfo", FontWeight->"Bold", FontSlant->"Italic"], ". The first allows to modify the existing option - protecting information \ or add new one, while the second one can be used to remove such information \ for a given list of option names. " }], "Text", CellChangeTimes->{{3.4411288754871454`*^9, 3.4411290214670544`*^9}, { 3.441607274046376*^9, 3.4416073089365454`*^9}, {3.4416172703603697`*^9, 3.4416172800643234`*^9}, 3.4418034098924017`*^9, {3.441803611332058*^9, 3.4418036246411953`*^9}}], Cell[TextData[{ "You can also use ", StyleBox["SetOptionInfo", FontSlant->"Italic"], ", but then the new information will completely replace the old one rather \ than just update it." }], "Text", CellChangeTimes->{{3.4411288754871454`*^9, 3.4411290214670544`*^9}, { 3.441607274046376*^9, 3.4416073089365454`*^9}, {3.4416172703603697`*^9, 3.4416172800643234`*^9}, 3.4418034098924017`*^9, 3.441803656466958*^9}], Cell[TextData[{ "The current (updated) option - protecting information can be obtained \ through ", StyleBox["GetOptionsInfo", FontWeight->"Bold", FontSlant->"Italic"], " :" }], "Text"], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"GetOptionsInfo", "[", "\"\\"", "]"}]], "Input"], Cell[BoxData[ RowBox[{"{", RowBox[{ RowBox[{"{", RowBox[{"CaseSensitive", ",", RowBox[{"True", "|", "False"}], ",", RowBox[{"{", RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "\[RuleDelayed]", "$Failed"}], ",", RowBox[{"LetterFrequenciesInWord", "\[RuleDelayed]", "$Failed"}]}], "}"}]}], "}"}], ",", RowBox[{"{", RowBox[{"MaxWordLength", ",", RowBox[{"_", "?", RowBox[{"(", RowBox[{ RowBox[{"#1", "\[LessEqual]", "12"}], "&"}], ")"}]}], ",", RowBox[{"AllWordsWithLetterFrequency", "\[RuleDelayed]", "$Failed"}]}], "}"}]}], "}"}]], "Output", CellChangeTimes->{ 3.4417247419726*^9, 3.4417982652047043`*^9, 3.441800989902627*^9, { 3.441803686099568*^9, 3.4418037122571807`*^9}, 3.4418051172474575`*^9, 3.441806997020438*^9}] }, Open ]], Cell[TextData[{ "For instance, we will remove the protection from the ", StyleBox["CaseSensitive", FontSlant->"Italic"], " option :" }], "Text", CellChangeTimes->{{3.441129050368613*^9, 3.4411290807923603`*^9}}], Cell[BoxData[ RowBox[{"ClearOptionsInfo", "[", RowBox[{"\"\\"", ",", RowBox[{"{", RowBox[{ "CaseSensitive", "\[RuleDelayed]", "AllWordsWithLetterFrequency"}], " ", "}"}]}], "]"}]], "Input", CellChangeTimes->{{3.441129091828229*^9, 3.4411291211904497`*^9}, { 3.4414451105269904`*^9, 3.44144512739124*^9}, {3.441696152962538*^9, 3.441696164989832*^9}}], Cell["Now:", "Text", CellChangeTimes->{{3.441129144764347*^9, 3.441129199332813*^9}, { 3.4414396271284285`*^9, 3.4414396508425283`*^9}, {3.441439684370739*^9, 3.4414397014252625`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"GetOptionsInfo", "[", "\"\\"", "]"}]], "Input",\ CellChangeTimes->{{3.4414396520342417`*^9, 3.4414396713520193`*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{ RowBox[{"{", RowBox[{"CaseSensitive", ",", RowBox[{"True", "|", "False"}], ",", RowBox[{"LetterFrequenciesInWord", "\[RuleDelayed]", "$Failed"}]}], "}"}], ",", RowBox[{"{", RowBox[{"MaxWordLength", ",", RowBox[{"_", "?", RowBox[{"(", RowBox[{ RowBox[{"#1", "\[LessEqual]", "12"}], "&"}], ")"}]}], ",", RowBox[{"AllWordsWithLetterFrequency", "\[RuleDelayed]", "$Failed"}]}], "}"}]}], "}"}]], "Output", CellChangeTimes->{3.4417247445963726`*^9, 3.441798268890003*^9, 3.4418009925764723`*^9, 3.4418011243659763`*^9, 3.4418037185362096`*^9, 3.4418051237367887`*^9, 3.4418070003952913`*^9}] }, Open ]], Cell["\<\ By the way, we can see that manipulations with \"protected\" functions in one \ context do not affect other contexts :\ \>", "Text", CellChangeTimes->{{3.441803720178571*^9, 3.441803723423237*^9}, { 3.4418051349429026`*^9, 3.441805164325152*^9}, {3.4418052170209246`*^9, 3.441805220926541*^9}, {3.441807008026264*^9, 3.4418070086070995`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"GetOptionsInfo", "[", "\"\\"", "]"}]], "Input", CellChangeTimes->{{3.441805195550051*^9, 3.4418051978333344`*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{"{", RowBox[{"MaxPrime", ",", RowBox[{"_Integer", "?", "Positive"}], ",", RowBox[{"getPrimes", "\[RuleDelayed]", "$Failed"}]}], "}"}], "}"}]], "Output", CellChangeTimes->{3.4418051999163294`*^9, 3.441807010880368*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"getPrimes", "[", RowBox[{"10", ",", RowBox[{"MaxPrime", "\[Rule]", "\"\\""}]}], "]"}]], "Input"], Cell[BoxData[ RowBox[{ RowBox[{"getPrimes", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(MaxPrime \[Rule] \\\"a\\\"\\) is invalid. \ \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(_Integer ? \ Positive\\) \"\>"}]], "Message", "MSG", CellChangeTimes->{3.441805185926213*^9, 3.4418070121421824`*^9}], Cell[BoxData["$Failed"], "Output", CellChangeTimes->{3.4418051859862995`*^9, 3.44180701218224*^9}] }, Open ]], Cell["We can try now:", "Text", CellChangeTimes->{{3.441129144764347*^9, 3.441129199332813*^9}, { 3.4414396271284285`*^9, 3.441439633998307*^9}, 3.441439675197549*^9}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "Fal"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{{3.4411291885172606`*^9, 3.4411291886674767`*^9}, { 3.441432374750021*^9, 3.441432374980352*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "::", "\<\"optundef\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(CaseSensitive \[Rule] Fal\\) is unknown\"\ \>"}]], "Message", CellChangeTimes->{3.441724745697957*^9, 3.4417982717641363`*^9, 3.441805238652029*^9, 3.441807014415451*^9}], Cell[BoxData[ TagBox["$Failed", Short[#, 5]& ]], "Output", CellChangeTimes->{3.4417247457279997`*^9, 3.4417982718041935`*^9, 3.441805238662043*^9, 3.4418070144555087`*^9}] }, Open ]], Cell[TextData[{ "If we want an option to be known but don' t want to restrict it to any \ particular set of values, we can use the ", StyleBox["Blank[] ", FontSlant->"Italic"], "(_) pattern. To add option information, we have to use ", StyleBox["ResetOptionsInfo", FontWeight->"Bold", FontSlant->"Italic"], " :" }], "Text", CellChangeTimes->{{3.441438684232611*^9, 3.441438694347155*^9}, { 3.4414397099375024`*^9, 3.441439791895352*^9}, 3.4418052487165008`*^9}], Cell[BoxData[ RowBox[{"ResetOptionsInfo", "[", RowBox[{"\"\\"", ",", RowBox[{"{", RowBox[{"{", RowBox[{"CaseSensitive", ",", "_", ",", RowBox[{ "AllWordsWithLetterFrequency", "\[RuleDelayed]", " ", "$Failed"}]}], "}"}], "}"}]}], "]"}]], "Input", CellChangeTimes->{{3.4414398029412355`*^9, 3.4414398501090593`*^9}, { 3.441446065470131*^9, 3.44144609469215*^9}, {3.441476135338478*^9, 3.4414761489981203`*^9}}], Cell["Here is the new info :", "Text", CellChangeTimes->{{3.44143992519703*^9, 3.4414399308551664`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"GetOptionsInfo", "[", "\"\\"", "]"}]], "Input"], Cell[BoxData[ RowBox[{"{", RowBox[{ RowBox[{"{", RowBox[{"CaseSensitive", ",", RowBox[{"True", "|", "False"}], ",", RowBox[{"LetterFrequenciesInWord", "\[RuleDelayed]", "$Failed"}]}], "}"}], ",", RowBox[{"{", RowBox[{"MaxWordLength", ",", RowBox[{"_", "?", RowBox[{"(", RowBox[{ RowBox[{"#1", "\[LessEqual]", "12"}], "&"}], ")"}]}], ",", RowBox[{"AllWordsWithLetterFrequency", "\[RuleDelayed]", "$Failed"}]}], "}"}], ",", RowBox[{"{", RowBox[{"CaseSensitive", ",", "_", ",", RowBox[{"AllWordsWithLetterFrequency", "\[RuleDelayed]", "$Failed"}]}], "}"}]}], "}"}]], "Output", CellChangeTimes->{3.4417247481114273`*^9, 3.441798275549579*^9, 3.4418052684749117`*^9, 3.441807025801824*^9}] }, Open ]], Cell["We try again :", "Text", CellChangeTimes->{{3.441439935792266*^9, 3.441439940428933*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "Fal"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input"], Cell[BoxData[ RowBox[{ RowBox[{"LetterFrequenciesInWord", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(CaseSensitive \[Rule] Fal\\) is invalid. \ \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(True | False\\) \ \"\>"}]], "Message", CellChangeTimes->{3.4417247490928383`*^9, 3.4417982773822145`*^9, 3.441805273482112*^9, 3.4418070291165905`*^9}], Cell[BoxData[ RowBox[{ RowBox[{"LetterFrequenciesInWord", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(CaseSensitive \[Rule] Fal\\) is invalid. \ \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(True | False\\) \ \"\>"}]], "Message", CellChangeTimes->{3.4417247490928383`*^9, 3.4417982773822145`*^9, 3.441805273482112*^9, 3.4418070291566477`*^9}], Cell[BoxData[ RowBox[{ RowBox[{"LetterFrequenciesInWord", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(CaseSensitive \[Rule] Fal\\) is invalid. \ \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(True | False\\) \ \"\>"}]], "Message", CellChangeTimes->{3.4417247490928383`*^9, 3.4417982773822145`*^9, 3.441805273482112*^9, 3.4418070292067204`*^9}], Cell[BoxData[ RowBox[{ RowBox[{"General", "::", "\<\"stop\"\>"}], RowBox[{ ":", " "}], "\<\"Further output of \\!\\(LetterFrequenciesInWord :: \ \\\"badopt\\\"\\) will be suppressed during this calculation. \ \\!\\(\\*ButtonBox[\\\"\[RightSkeleton]\\\", ButtonStyle->\\\"Link\\\", \ ButtonFrame->None, ButtonData:>\\\"paclet:ref/message/General/stop\\\", \ ButtonNote -> \\\"General::stop\\\"]\\)\"\>"}]], "Message", CellChangeTimes->{3.4417247490928383`*^9, 3.4417982773822145`*^9, 3.441805273482112*^9, 3.441807029256792*^9}], Cell[BoxData[ TagBox[ RowBox[{"{", "}"}], Short[#, 5]& ]], "Output", CellChangeTimes->{3.441724750755229*^9, 3.441798278634014*^9, 3.441805274804013*^9, 3.441807030478549*^9}] }, Open ]], Cell[TextData[{ "Now we see that an option is ok to ", StyleBox["AllWordsWithLetterFrequency", FontSlant->"Italic"], ", but not ok to ", StyleBox["LetterFrequenciesInWord", FontSlant->"Italic"], " which the former is using internally and to which it passes options.We \ now add the corresponding information :" }], "Text", CellChangeTimes->{{3.4414399826596575`*^9, 3.441440062875002*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"ResetOptionsInfo", "[", RowBox[{"\"\\"", ",", RowBox[{"{", RowBox[{"{", RowBox[{"CaseSensitive", ",", "_", ",", RowBox[{ "LetterFrequenciesInWord", "\[RuleDelayed]", " ", "$Failed"}]}], "}"}], "}"}]}], "]"}], ";"}]], "Input", CellChangeTimes->{{3.4414400788179264`*^9, 3.44144008026*^9}, { 3.441476171710779*^9, 3.441476176808109*^9}}], Cell["Check :", "Text", CellChangeTimes->{{3.4414464991236944`*^9, 3.4414465014570494`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"GetOptionsInfo", "[", "\"\\"", "]"}]], "Input"], Cell[BoxData[ RowBox[{"{", RowBox[{ RowBox[{"{", RowBox[{"CaseSensitive", ",", "_", ",", RowBox[{"{", RowBox[{ RowBox[{"LetterFrequenciesInWord", "\[RuleDelayed]", "$Failed"}], ",", RowBox[{"AllWordsWithLetterFrequency", "\[RuleDelayed]", "$Failed"}]}], "}"}]}], "}"}], ",", RowBox[{"{", RowBox[{"MaxWordLength", ",", RowBox[{"_", "?", RowBox[{"(", RowBox[{ RowBox[{"#1", "\[LessEqual]", "12"}], "&"}], ")"}]}], ",", RowBox[{"AllWordsWithLetterFrequency", "\[RuleDelayed]", "$Failed"}]}], "}"}]}], "}"}]], "Output", CellChangeTimes->{3.4417247531386557`*^9, 3.4417982839216175`*^9, 3.441805301662634*^9, 3.4418070397018113`*^9}] }, Open ]], Cell["\<\ Now there is no error message generated (which is probably a bad idea in this \ case, but I am just giving an illustration): \ \>", "Text", CellChangeTimes->{{3.4414462947097616`*^9, 3.441446360213952*^9}, 3.4418053201492157`*^9}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "Fal"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input"], Cell[BoxData[ TagBox[ RowBox[{"{", "}"}], Short[#, 5]& ]], "Output", CellChangeTimes->{3.4417247552116365`*^9, 3.4417982886083565`*^9, 3.441805328831701*^9, 3.441807042555915*^9}] }, Open ]], Cell["\<\ Thus, let us now return to the original option - checking pattern for this \ option :\ \>", "Text", CellChangeTimes->{{3.441446390557584*^9, 3.441446420801072*^9}, { 3.44147619272099*^9, 3.441476192831149*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"ResetOptionsInfo", "[", RowBox[{"\"\\"", ",", RowBox[{"{", RowBox[{"{", RowBox[{"CaseSensitive", ",", RowBox[{"True", "|", "False"}], ",", RowBox[{"{", RowBox[{ RowBox[{ "LetterFrequenciesInWord", "\[RuleDelayed]", " ", "$Failed"}], ",", RowBox[{ "AllWordsWithLetterFrequency", "\[RuleDelayed]", " ", "$Failed"}]}], "}"}]}], "}"}], "}"}]}], "]"}], ";"}]], "Input", CellChangeTimes->{{3.441446443163227*^9, 3.4414464591662383`*^9}, { 3.4414761960057135`*^9, 3.441476207061611*^9}}], Cell["Check :", "Text", CellChangeTimes->{{3.441446470121992*^9, 3.4414464717843823`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"GetOptionsInfo", "[", "\"\\"", "]"}]], "Input"], Cell[BoxData[ RowBox[{"{", RowBox[{ RowBox[{"{", RowBox[{"CaseSensitive", ",", RowBox[{"True", "|", "False"}], ",", RowBox[{"{", RowBox[{ RowBox[{"LetterFrequenciesInWord", "\[RuleDelayed]", "$Failed"}], ",", RowBox[{"AllWordsWithLetterFrequency", "\[RuleDelayed]", "$Failed"}]}], "}"}]}], "}"}], ",", RowBox[{"{", RowBox[{"MaxWordLength", ",", RowBox[{"_", "?", RowBox[{"(", RowBox[{ RowBox[{"#1", "\[LessEqual]", "12"}], "&"}], ")"}]}], ",", RowBox[{"AllWordsWithLetterFrequency", "\[RuleDelayed]", "$Failed"}]}], "}"}]}], "}"}]], "Output", CellChangeTimes->{3.441724756663725*^9, 3.4417982916527348`*^9, 3.4418053330277348`*^9, 3.4418070454200335`*^9}] }, Open ]], Cell["And now :", "Text", CellChangeTimes->{{3.4414464735369024`*^9, 3.4414464756098833`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "Fal"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input"], Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(CaseSensitive \[Rule] Fal\\) is invalid. \ \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(True | False\\) \ \"\>"}]], "Message", CellChangeTimes->{3.4417247577853374`*^9, 3.4417982929646206`*^9, 3.441805336793149*^9, 3.441807047382856*^9}], Cell[BoxData[ TagBox["$Failed", Short[#, 5]& ]], "Output", CellChangeTimes->{3.441724757795352*^9, 3.4417982930046787`*^9, 3.441805336833206*^9, 3.441807047412899*^9}] }, Open ]], Cell[TextData[{ "Note that we could use the < ", StyleBox["All ", FontWeight->"Bold", FontSlant->"Italic"], "> keyword to remove the option information for all functions that take this \ option, at once :" }], "Text", CellChangeTimes->{{3.441446589473611*^9, 3.4414466330162225`*^9}}], Cell[BoxData[ RowBox[{"ClearOptionsInfo", "[", RowBox[{"\"\\"", ",", RowBox[{"{", RowBox[{"CaseSensitive", "\[RuleDelayed]", "All"}], "}"}]}], "]"}]], "Input", CellChangeTimes->{3.4414466620780115`*^9}], Cell["Check :", "Text", CellChangeTimes->{{3.4414466653927774`*^9, 3.4414466664543037`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"GetOptionsInfo", "[", "\"\\"", "]"}]], "Input"], Cell[BoxData[ RowBox[{"{", RowBox[{"{", RowBox[{"MaxWordLength", ",", RowBox[{"_", "?", RowBox[{"(", RowBox[{ RowBox[{"#1", "\[LessEqual]", "12"}], "&"}], ")"}]}], ",", RowBox[{"AllWordsWithLetterFrequency", "\[RuleDelayed]", "$Failed"}]}], "}"}], "}"}]], "Output", CellChangeTimes->{3.4417247608797874`*^9, 3.4417982960390415`*^9, 3.441805342701645*^9, 3.4418070510881844`*^9}] }, Open ]], Cell["We again restore the option protection :", "Text", CellChangeTimes->{{3.4414466749865727`*^9, 3.441446689106877*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"ResetOptionsInfo", "[", RowBox[{"\"\\"", ",", RowBox[{"{", RowBox[{"{", RowBox[{"CaseSensitive", ",", RowBox[{"True", "|", "False"}], ",", RowBox[{"{", RowBox[{ RowBox[{ "LetterFrequenciesInWord", "\[RuleDelayed]", " ", "$Failed"}], ",", RowBox[{ "AllWordsWithLetterFrequency", "\[RuleDelayed]", " ", "$Failed"}]}], "}"}]}], "}"}], "}"}]}], "]"}], ";"}]], "Input", CellChangeTimes->{{3.4414762263894033`*^9, 3.441476237525416*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"GetOptionsInfo", "[", "\"\\"", "]"}]], "Input",\ CellChangeTimes->{{3.441556986156821*^9, 3.4415569901024942`*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{ RowBox[{"{", RowBox[{"MaxWordLength", ",", RowBox[{"_", "?", RowBox[{"(", RowBox[{ RowBox[{"#1", "\[LessEqual]", "12"}], "&"}], ")"}]}], ",", RowBox[{"AllWordsWithLetterFrequency", "\[RuleDelayed]", "$Failed"}]}], "}"}], ",", RowBox[{"{", RowBox[{"CaseSensitive", ",", RowBox[{"True", "|", "False"}], ",", RowBox[{"{", RowBox[{ RowBox[{"LetterFrequenciesInWord", "\[RuleDelayed]", "$Failed"}], ",", RowBox[{"AllWordsWithLetterFrequency", "\[RuleDelayed]", "$Failed"}]}], "}"}]}], "}"}]}], "}"}]], "Output", CellChangeTimes->{3.4417247633934016`*^9, 3.4417982988931456`*^9, 3.4418053462667713`*^9, 3.4418070540023746`*^9}] }, Open ]], Cell["\<\ When more than one option is bad, all individual responses for bad options \ are executed, but only the result of the last response is returned :\ \>", "Text", CellChangeTimes->{{3.441606012572466*^9, 3.441606047302405*^9}, { 3.4418070640968895`*^9, 3.44180709279816*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "Fal"}], ",", RowBox[{"MaxWordLength", "\[Rule]", " ", "\"\\""}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{{3.44160606206363*^9, 3.441606076254035*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(CaseSensitive \[Rule] Fal\\) is invalid. \ \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(True | False\\) \ \"\>"}]], "Message", CellChangeTimes->{{3.4417247657167425`*^9, 3.4417247823706894`*^9}, 3.441798300705752*^9, 3.441805348389824*^9, 3.441807055624707*^9}], Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(MaxWordLength \[Rule] \\\"a\\\"\\) is \ invalid. \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(_ ? \ \\(\\((\\(\\(\\(#1 \[LessEqual] 12\\)\\) &\\))\\)\\)\\) \"\>"}]], "Message", CellChangeTimes->{{3.4417247657167425`*^9, 3.4417247823706894`*^9}, 3.441798300705752*^9, 3.441805348389824*^9, 3.441807055664765*^9}], Cell[BoxData[ TagBox["$Failed", Short[#, 5]& ]], "Output", CellChangeTimes->{{3.4417247657467856`*^9, 3.4417247824107475`*^9}, 3.4417983007458096`*^9, 3.441805348520011*^9, 3.4418070557348657`*^9}] }, Open ]], Cell["\<\ If this is inappropriate, one can change the response behavior to, for \ example, throwing an exception (see the next subsection). In this case, only \ the first invalid option response will take effect.\ \>", "Text", CellChangeTimes->{{3.4416060823027325`*^9, 3.441606185501125*^9}}] }, Open ]] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell["Setting up arbitrary action in response to a bad option", "Section", CellChangeTimes->{{3.4415567582691345`*^9, 3.4415567986071377`*^9}}, FontWeight->"Plain"], Cell["\<\ This section describes how to set up more actions in response to passed \ inappropriate options\ \>", "Text", CellChangeTimes->{{3.4416151043958654`*^9, 3.4416151563706017`*^9}}], Cell[CellGroupData[{ Cell["Details", "Subsection", CellChangeTimes->{{3.4416151631002784`*^9, 3.4416151660344973`*^9}}, FontWeight->"Plain"], Cell[TextData[{ "Throughout this notebook, up to this point we only considered the following \ response to bad options passed: issue an error message and return ", StyleBox["$Failed", FontSlant->"Italic"], ". This may be not always desirable. Indeed, we can execute arbitrary code \ rather than just returning ", StyleBox["$Failed", FontSlant->"Italic"], ". For example, we can ", StyleBox["Throw $Failed", FontSlant->"Italic"], ", plain or with a tag being the name of the function that failed, for the \ ", StyleBox["CaseSensitive", FontSlant->"Italic"], " option:" }], "Text", CellChangeTimes->{{3.4415568032938766`*^9, 3.4415569732282305`*^9}, { 3.4415575287269983`*^9, 3.4415575373594112`*^9}, 3.441607346049912*^9, 3.441615090345662*^9, 3.4416172849713793`*^9}], Cell[BoxData[ RowBox[{ RowBox[{"ResetOptionsInfo", "[", RowBox[{"\"\\"", ",", RowBox[{"{", RowBox[{"{", RowBox[{"CaseSensitive", ",", RowBox[{"True", "|", "False"}], ",", RowBox[{"{", RowBox[{ RowBox[{"LetterFrequenciesInWord", "\[RuleDelayed]", " ", RowBox[{"Throw", "[", "$Failed", "]"}]}], ",", RowBox[{"AllWordsWithLetterFrequency", "\[RuleDelayed]", RowBox[{"Throw", "[", " ", "$Failed", "]"}]}]}], "}"}]}], "}"}], "}"}]}], "]"}], ";"}]], "Input", CellChangeTimes->{{3.4415570018694143`*^9, 3.4415570148580914`*^9}, { 3.4415576500314255`*^9, 3.441557668848483*^9}}], Cell["Now :", "Text", CellChangeTimes->{{3.441557542807245*^9, 3.441557544059045*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "Fal"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input", CellChangeTimes->{{3.4415590878188624`*^9, 3.441559089060648*^9}, 3.441559432624669*^9}], Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(CaseSensitive \[Rule] Fal\\) is invalid. \ \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(True | False\\) \ \"\>"}]], "Message", CellChangeTimes->{3.4417247861961904`*^9, 3.441798304591339*^9, 3.4418053699608417`*^9, 3.4418071070085936`*^9}], Cell[BoxData[ RowBox[{ RowBox[{"Throw", "::", "\<\"nocatch\"\>"}], RowBox[{ ":", " "}], "\<\"Uncaught \\!\\(Throw[$Failed]\\) returned to top level. \ \\!\\(\\*ButtonBox[\\\"\[RightSkeleton]\\\", ButtonStyle->\\\"Link\\\", \ ButtonFrame->None, ButtonData:>\\\"paclet:ref/message/Throw/nocatch\\\", \ ButtonNote -> \\\"Throw::nocatch\\\"]\\)\"\>"}]], "Message", CellChangeTimes->{3.4417247861961904`*^9, 3.441798304591339*^9, 3.4418053699608417`*^9, 3.441807107369112*^9}], Cell[BoxData[ RowBox[{"Hold", "[", RowBox[{"Throw", "[", "$Failed", "]"}], "]"}]], "Output", CellChangeTimes->{3.44172478653668*^9, 3.4417983049118*^9, 3.441805370251259*^9, 3.4418071074091697`*^9}] }, Open ]], Cell["Or we can print something instead :", "Text", CellChangeTimes->{{3.4415596934096594`*^9, 3.4415597071894736`*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"ResetOptionsInfo", "[", RowBox[{"\"\\"", ",", RowBox[{"{", RowBox[{"{", RowBox[{"CaseSensitive", ",", RowBox[{"True", "|", "False"}], ",", RowBox[{"{", RowBox[{ RowBox[{"LetterFrequenciesInWord", "\[RuleDelayed]", " ", RowBox[{"Print", "[", "\"\\"", " ", "]"}]}], ",", RowBox[{"AllWordsWithLetterFrequency", "\[RuleDelayed]", RowBox[{"Print", "[", "\"\\"", " ", "]"}]}]}], "}"}]}], "}"}], "}"}]}], "]"}], ";"}]], "Input", CellChangeTimes->{{3.4415597787924337`*^9, 3.4415598097870016`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "[", RowBox[{"\"\\"", ",", "3", ",", RowBox[{"CaseSensitive", "\[Rule]", " ", "Fal"}]}], "]"}], "//", RowBox[{ RowBox[{"Short", "[", RowBox[{"#", ",", "5"}], "]"}], "&"}]}]], "Input"], Cell[BoxData[ RowBox[{ RowBox[{"AllWordsWithLetterFrequency", "::", "\<\"badopt\"\>"}], RowBox[{ ":", " "}], "\<\"The option \\!\\(CaseSensitive \[Rule] Fal\\) is invalid. \ \\n\\t\\tThe pattern for the option's rhs to match is \\!\\(True | False\\) \ \"\>"}]], "Message", CellChangeTimes->{3.4417247962406335`*^9, 3.441798307635717*^9, 3.4418053755989485`*^9, 3.4418071155709057`*^9}], Cell[BoxData["\<\"Wrong option\"\>"], "Print", CellChangeTimes->{3.441724796250648*^9, 3.44179830766576*^9, 3.4418053756390066`*^9, 3.44180711558092*^9}], Cell[BoxData[ TagBox["Null", Short[#, 5]& ]], "Output", CellChangeTimes->{3.4417247963107347`*^9, 3.4417983077258463`*^9, 3.4418053757091074`*^9, 3.441807115630992*^9}] }, Open ]], Cell[TextData[{ "It is very important that the delayed rule is used in specifying the code \ to execute, in order to avoid its premature evaluation (", StyleBox["RuleDelayed ", FontSlant->"Italic"], "does not evaluate its rhs before the rule is applied). ", StyleBox["ResetOptionsInfo", FontSlant->"Italic"], " ought to catch the usage of ", StyleBox["Rule", FontSlant->"Italic"], " instead of ", StyleBox["RuleDelayed", FontSlant->"Italic"], " , but the code will be executed anyway - which may be bad if it contains \ side effects :" }], "Text", CellChangeTimes->{{3.4416070849344463`*^9, 3.4416072253563633`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"ResetOptionsInfo", "[", RowBox[{"\"\\"", ",", RowBox[{"{", RowBox[{"{", RowBox[{"CaseSensitive", ",", RowBox[{"True", "|", "False"}], ",", RowBox[{"{", RowBox[{ RowBox[{"LetterFrequenciesInWord", "->", " ", RowBox[{"Print", "[", "\"\\"", " ", "]"}]}], ",", RowBox[{"AllWordsWithLetterFrequency", "\[RuleDelayed]", RowBox[{"Print", "[", "\"\\"", " ", "]"}]}]}], "}"}]}], "}"}], "}"}]}], "]"}], ";"}]], "Input", CellChangeTimes->{{3.4416070705137105`*^9, 3.4416070715451937`*^9}, { 3.441618224111797*^9, 3.441618234006024*^9}}], Cell[BoxData["\<\"Side effect\"\>"], "Print", CellChangeTimes->{3.441724798704176*^9, 3.4417983090677757`*^9, 3.4418053821984386`*^9, 3.4418071172533245`*^9}], Cell[BoxData[ RowBox[{ RowBox[{"ResetOptionsInfo", "::", "\<\"badargs\"\>"}], RowBox[{ ":", " "}], "\<\"The first argument must be a string, and the second must \ follow the general option-protection information pattern \ {{(_String|_Symbol),_,((_Symbol:>_)|{(_Symbol:>_)..})}..}\"\>"}]], "Message", CellChangeTimes->{3.4417247995453854`*^9, 3.4417983099891005`*^9, 3.4418053830096045`*^9, 3.441807118164635*^9}] }, Open ]] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell["Summary", "Section", CellChangeTimes->{{3.4414468425374994`*^9, 3.4414468446104803`*^9}}, FontWeight->"Plain"], Cell[TextData[{ "The functionality of the present package allows one to \"protect\" given \ option - taking functions from passed options which are unknown to the \ function or are set to inappropriate values. One can do this protection both \ on the level of the entire package or individual functions. This protection \ is different from the traditional option-filtering, since it allows a called \ function to respond to a bad option in a certain specified way, rather than a \ calling function to restrict the set of options passed to a called one. In \ other words, this works \"from the other side\" of option-passing and \ complements traditional options filtering. In particular, it allows to \ discover cases of options not properly filtered, and do it the easy way, \ rather than doing it the hard way by tracing bugs caused by bad options \ (this last functionality is also provided by OptionPattern-OptionValue \ constructs in v.6.0+).\n\nAn absolute pre-requisite for the \ function-to-be-protected is that it (or at least, its relevant \ option-carrying definitions) is defined through ", StyleBox["DownValues", FontWeight->"Bold", FontSlant->"Italic"], " and the ", StyleBox["opts___?OptionQ", FontWeight->"Bold", FontSlant->"Italic"], " form is used to declare optional parameters (the name is \ arbitrary). \n \nSetting up the initial protection is a 2 - step process, \ where the first step can be performed before or after, but the second has to \ be performed after the functions to be protected are defined.\n \nThe first \ step consists of \"declaring\" the options with the patterns that their rhs - \ s have to match, and functions which take them. This is done by calling the \ <", StyleBox["SetOptionsInfo", FontWeight->"Bold", FontSlant->"Italic"], "> function.\n\nThe second step is done by calling the <", StyleBox["TurnOptionChecksOn", FontWeight->"Bold", FontSlant->"Italic"], "> function. If there is a need to protect a number of functions being \ currently interactively developed in the ", StyleBox["\"Global`\"", FontSlant->"Italic"], " context, one just has to pass ", StyleBox["\"Global`\"", FontSlant->"Italic"], " to both ", StyleBox["SetOptionsInfo", FontSlant->"Italic"], " and ", StyleBox["TurnOptionChecksOn", FontSlant->"Italic"], ". In other words, one can use the present functionality also for initial \ interactive development and before placing functions to a package (different \ context).\n \n After the initial protection is set up, a number of \ possibilities are available to change its level and scope. First, one can \ add/remove protection, both on the level of entire context (package) and \ individual functions. Second, one can change the option - protecting \ information. This can be done both from within the context containing \ functions of interest, and from the outside. This allows, for instance, to \ add information about new options/functions that emerged during incremental \ development, and/or change the level of protection for existing \ options/functions. \n \n One thing worth noting is that the information \ used to protect options/functions is based entirely on what is provided by \ the user to the information - setting functions ", StyleBox["SetOptionsInfo", FontSlant->"Italic"], ", ", StyleBox["ResetOptionsInfo", FontSlant->"Italic"], ", and has nothing to do with what is declared by ", StyleBox["Options[function] = { ...}", FontSlant->"Italic"], ". \n \n Another important thing is that while the option-protection \ functionality is completely independent of any one package (context) which we \ want to protect, the former does intrude into and change the functionality of \ the latter. I will describe this in more details below, but for all \ option-protected functions, new definitions are added and thus they are \ modified. It is hoped that these modifications will never affect their main \ functionality, but there is no guarantee for this, and moreover, it is \ certainly possible to give examples of the opposite, especially for functions \ which rely on/manipulate the internal/global rule ordering of their \ definitions and/or add/remove their own or other function's definitions \ dynamically (at run-time). But even in these cases, by executing ", StyleBox["TurnOptionChecksOn[context]", FontSlant->"Italic"], " after any changes to definitions have been made, it should be possible to \ keep the changed functions \"protected\" (for the price of possibly slowing \ these functions down).\n \n Yet another limitation is that the present \ functionality will work only for functions defined through ", StyleBox["DownValues", FontWeight->"Bold"], ". This excludes ", StyleBox["SubValues", FontSlant->"Italic"], " - and ", StyleBox["UpValues", FontSlant->"Italic"], " - based definitions - cases like these:\n \n \ f[n_?Integer][x_,y_,opts___?OptionQ]:=... (SubValues)\n \n or\n \n \ f/: g[a_,b_,f[x_,y_,opts___?OptionQ]]:=... (UpValues)\n \n Finally, \ with the caveats just mentioned, one can attempt to use the present \ functionality to protect functions also in packages written by someone else. \ In this case, the package code does not need to be modified at all. One just \ has to execute ", StyleBox["SetOptionsInfo[context, info]", FontSlant->"Italic"], " (with a proper option-protecting information <", StyleBox["info", FontSlant->"Italic"], ">), and then ", StyleBox["TurnOptionChecksOn[context]", FontSlant->"Italic"], ", after loading the package of interest. " }], "Text", CellChangeTimes->{{3.4414468460525537`*^9, 3.4414469386757393`*^9}, { 3.441446977131035*^9, 3.4414470014560127`*^9}, {3.4414470456896176`*^9, 3.441447906567499*^9}, {3.4414479381729455`*^9, 3.4414482541773376`*^9}, { 3.441450259490837*^9, 3.441450333947901*^9}, {3.4414504087955265`*^9, 3.4414505537038946`*^9}, {3.4416062432040977`*^9, 3.4416063122533855`*^9}, {3.441606371047928*^9, 3.4416067888386817`*^9}, { 3.4416069378429394`*^9, 3.4416069559089165`*^9}, {3.441606995125307*^9, 3.44160701502392*^9}, 3.441608489464061*^9, {3.4416085464860544`*^9, 3.4416087869017553`*^9}, {3.4416088292025805`*^9, 3.4416088588351903`*^9}, {3.4416089121618705`*^9, 3.441608940492608*^9}, { 3.4416090062571726`*^9, 3.441609020928269*^9}, {3.4416155222467055`*^9, 3.441615544558789*^9}, {3.4416158697764287`*^9, 3.441615885649253*^9}, { 3.441617292952856*^9, 3.441617311499525*^9}, {3.4418071451935005`*^9, 3.4418072235762095`*^9}}] }, Open ]], Cell[CellGroupData[{ Cell["Appendix: How option protection works", "Section", CellChangeTimes->{{3.4411173743993936`*^9, 3.4411173833522673`*^9}, { 3.4414485247163534`*^9, 3.4414485279610195`*^9}}, FontWeight->"Plain"], Cell[TextData[{ "The mechanism of option - protection is simple: take a list of definitions \ for a given function < f >, find all signatures containing options in the \ form opts___?OptionQ, construct for each of them a new definition with the \ same signature but an extra option-checking condition attached, and prepend \ these new definitions to the list of existing ones (since they have an extra \ condition attached , as compared to existing initial defs, they are \ rightfully considered more specific than the old ones by the ", StyleBox["Mathematica", FontSlant->"Italic"], " rule-ordering engine, and thus remain higher in the DownValues list. Thus, \ they are checked before the main ones). This is done by the \ package, specifically by the commands , \ . Most of the \"hard stuff\" is done there. The role of \ is to automate this process and make it most \ convenient to the user. If one is so inclined, one can use the functionality \ of directly.\n\nIt should be clear that, from a purist's \ viewpoint, the operation just described is a rather rough intrusion into the \ code of functions being protected, since effectively new code is generated \ and added to the existing one. It should work fine for most \"traditionally\" \ - written functions but may not work well with functions whose definitions \ are changed/manipulated at run-time (either by themselves or some other \ functions), unless such definition-manipulating functionality is written \ already with the in mind. It might be possible to add \ a more sophisticated code analysis to to detect such \ cases, but I did not do it yet." }], "Text", CellChangeTimes->{{3.4411173851348305`*^9, 3.44111738847964*^9}, { 3.4416073686023407`*^9, 3.4416076267435293`*^9}, {3.441607689343544*^9, 3.4416078186394625`*^9}, {3.4416078886401186`*^9, 3.4416082063970304`*^9}, {3.441608246064069*^9, 3.441608312289296*^9}, { 3.4416083622010655`*^9, 3.4416084615939856`*^9}, {3.441609087303712*^9, 3.4416091652958593`*^9}, {3.441617441396307*^9, 3.4416174422575455`*^9}, 3.4418074758589745`*^9}] }, Open ]] }, Open ]] }, WindowSize->{1017, 653}, WindowMargins->{{0, Automatic}, {Automatic, 0}}, ShowSelection->True, Magnification->1.5, FrontEndVersion->"6.0 for Microsoft Windows (32-bit) (April 28, 2007)", StyleDefinitions->"Default.nb" ] (* End of Notebook Content *) (* Internal cache information *) (*CellTagsOutline CellTagsIndex->{} *) (*CellTagsIndex CellTagsIndex->{} *) (*NotebookFileOutline Notebook[{ Cell[CellGroupData[{ Cell[590, 23, 293, 7, 117, "Subtitle"], Cell[CellGroupData[{ Cell[908, 34, 278, 9, 156, "Subsection"], Cell[1189, 45, 147, 2, 41, "Subsubsection"], Cell[1339, 49, 271, 7, 31, "Subsubsection"] }, Open ]], Cell[CellGroupData[{ Cell[1647, 61, 121, 2, 105, "Section"], Cell[1771, 65, 1869, 40, 387, "Text"] }, Open ]], Cell[CellGroupData[{ Cell[3677, 110, 149, 2, 105, "Section"], Cell[3829, 114, 1649, 40, 286, "Text"], Cell[CellGroupData[{ Cell[5503, 158, 155, 2, 54, "Subsection"], Cell[5661, 162, 198, 4, 41, "Text"], Cell[5862, 168, 8368, 219, 1868, "Input"] }, Open ]], Cell[CellGroupData[{ Cell[14267, 392, 204, 3, 54, "Subsection"], Cell[CellGroupData[{ Cell[14496, 399, 168, 3, 43, "Input"], Cell[14667, 404, 684, 20, 42, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[15388, 429, 331, 8, 43, "Input"], Cell[15722, 439, 685, 14, 112, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[16444, 458, 340, 8, 71, "Input"], Cell[16787, 468, 650, 13, 112, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[17474, 486, 397, 9, 71, "Input"], Cell[17874, 497, 727, 14, 112, "Output"] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell[18650, 517, 239, 3, 54, "Subsection"], Cell[CellGroupData[{ Cell[18914, 524, 317, 8, 43, "Input"], Cell[19234, 534, 163, 5, 61, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[19434, 544, 403, 9, 71, "Input"], Cell[19840, 555, 588, 12, 112, "Output"] }, Open ]], Cell[20443, 570, 422, 7, 90, "Text"] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell[20914, 583, 207, 3, 105, "Section"], Cell[CellGroupData[{ Cell[21146, 590, 138, 2, 54, "Subsection"], Cell[CellGroupData[{ Cell[21309, 596, 128, 2, 41, "Subsubsection"], Cell[21440, 600, 826, 23, 116, "Text"], Cell[22269, 625, 331, 8, 71, "Input"], Cell[22603, 635, 1329, 33, 166, "Text"], Cell[23935, 670, 396, 10, 118, "Input"], Cell[24334, 682, 269, 7, 41, "Text"], Cell[24606, 691, 1717, 43, 518, "Input"], Cell[26326, 736, 293, 7, 41, "Text"], Cell[CellGroupData[{ Cell[26644, 747, 208, 3, 43, "Input"], Cell[26855, 752, 3210, 88, 185, "Print"] }, Open ]], Cell[30080, 843, 573, 14, 91, "Text"], Cell[CellGroupData[{ Cell[30678, 861, 104, 1, 43, "Input"], Cell[30785, 864, 97, 1, 42, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[30919, 870, 194, 3, 43, "Input"], Cell[31116, 875, 124, 2, 42, "Output"] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell[31289, 883, 149, 2, 41, "Subsubsection"], Cell[31441, 887, 1236, 34, 214, "Text"], Cell[32680, 923, 2312, 78, 218, "Input"], Cell[34995, 1003, 623, 14, 90, "Text"], Cell[35621, 1019, 442, 7, 66, "Text"], Cell[36066, 1028, 6394, 173, 1093, "Input"] }, Open ]], Cell[CellGroupData[{ Cell[42497, 1206, 150, 2, 41, "Subsubsection"], Cell[42650, 1210, 344, 10, 41, "Text"], Cell[42997, 1222, 412, 10, 96, "Input"], Cell[43412, 1234, 97, 1, 41, "Text"], Cell[43512, 1237, 182, 5, 67, "Input"], Cell[43697, 1244, 1836, 47, 385, "Text"] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell[45582, 1297, 268, 4, 54, "Subsection"], Cell[45853, 1303, 253, 5, 41, "Text"], Cell[CellGroupData[{ Cell[46131, 1312, 207, 3, 41, "Subsubsection"], Cell[46341, 1317, 111, 1, 41, "Text"], Cell[CellGroupData[{ Cell[46477, 1322, 168, 3, 43, "Input"], Cell[46648, 1327, 850, 22, 42, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[47535, 1354, 331, 8, 43, "Input"], Cell[47869, 1364, 855, 16, 112, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[48761, 1385, 340, 8, 71, "Input"], Cell[49104, 1395, 816, 15, 112, "Output"] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell[49969, 1416, 162, 2, 41, "Subsubsection"], Cell[50134, 1420, 299, 5, 66, "Text"], Cell[CellGroupData[{ Cell[50458, 1429, 397, 9, 71, "Input"], Cell[50858, 1440, 463, 9, 32, "Message"], Cell[51324, 1451, 463, 9, 32, "Message"], Cell[51790, 1462, 461, 9, 32, "Message"], Cell[52254, 1473, 691, 12, 83, "Message"], Cell[52948, 1487, 330, 7, 61, "Output"] }, Open ]], Cell[53293, 1497, 190, 2, 41, "Text"], Cell[53486, 1501, 1498, 37, 188, "Text"], Cell[54987, 1540, 4846, 135, 793, "Input"], Cell[CellGroupData[{ Cell[59858, 1679, 327, 8, 71, "Input"], Cell[60188, 1689, 932, 17, 112, "Output"] }, Open ]], Cell[61135, 1709, 674, 14, 116, "Text"] }, Open ]], Cell[CellGroupData[{ Cell[61846, 1728, 239, 3, 41, "Subsubsection"], Cell[62088, 1733, 411, 10, 66, "Text"], Cell[CellGroupData[{ Cell[62524, 1747, 317, 8, 71, "Input"], Cell[62844, 1757, 542, 10, 58, "Message"], Cell[63389, 1769, 324, 6, 61, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[63750, 1780, 384, 9, 71, "Input"], Cell[64137, 1791, 425, 8, 61, "Message"], Cell[64565, 1801, 334, 7, 33, "Message"], Cell[64902, 1810, 196, 4, 61, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[65135, 1819, 403, 9, 71, "Input"], Cell[65541, 1830, 537, 9, 58, "Message"], Cell[66081, 1841, 269, 5, 61, "Output"] }, Open ]] }, Open ]] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell[66423, 1854, 196, 3, 105, "Section"], Cell[CellGroupData[{ Cell[66644, 1861, 168, 2, 54, "Subsection"], Cell[66815, 1865, 242, 5, 41, "Text"], Cell[67060, 1872, 143, 1, 41, "Text"], Cell[CellGroupData[{ Cell[67228, 1877, 168, 3, 43, "Input"], Cell[67399, 1882, 292, 6, 42, "Output"] }, Open ]], Cell[67706, 1891, 165, 3, 41, "Text"], Cell[CellGroupData[{ Cell[67896, 1898, 317, 8, 43, "Input"], Cell[68216, 1908, 234, 6, 61, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[68487, 1919, 403, 9, 71, "Input"], Cell[68893, 1930, 660, 13, 112, "Output"] }, Open ]], Cell[69568, 1946, 565, 11, 90, "Text"], Cell[CellGroupData[{ Cell[70158, 1961, 134, 2, 43, "Input"], Cell[70295, 1965, 545, 10, 108, "Message"], Cell[70843, 1977, 256, 4, 42, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[71136, 1986, 143, 3, 43, "Input"], Cell[71282, 1991, 285, 6, 42, "Output"] }, Open ]], Cell[71582, 2000, 123, 1, 41, "Text"], Cell[CellGroupData[{ Cell[71730, 2005, 317, 8, 43, "Input"], Cell[72050, 2015, 449, 9, 58, "Message"], Cell[72502, 2026, 229, 5, 61, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[72768, 2036, 403, 9, 71, "Input"], Cell[73174, 2047, 496, 9, 58, "Message"], Cell[73673, 2058, 225, 5, 61, "Output"] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell[73947, 2069, 159, 2, 54, "Subsection"], Cell[74109, 2073, 540, 16, 92, "Text"], Cell[CellGroupData[{ Cell[74674, 2093, 165, 3, 43, "Input"], Cell[74842, 2098, 199, 3, 42, "Output"] }, Open ]], Cell[75056, 2104, 196, 4, 41, "Text"], Cell[CellGroupData[{ Cell[75277, 2112, 163, 3, 43, "Input"], Cell[75443, 2117, 208, 4, 42, "Output"] }, Open ]], Cell[75666, 2124, 54, 0, 41, "Text"], Cell[CellGroupData[{ Cell[75745, 2128, 259, 6, 43, "Input"], Cell[76007, 2136, 246, 5, 42, "Output"] }, Open ]], Cell[76268, 2144, 126, 1, 41, "Text"], Cell[CellGroupData[{ Cell[76419, 2149, 335, 8, 71, "Input"], Cell[76757, 2159, 663, 13, 112, "Output"] }, Open ]], Cell[77435, 2175, 165, 3, 41, "Text"], Cell[CellGroupData[{ Cell[77625, 2182, 164, 3, 43, "Input"], Cell[77792, 2187, 213, 4, 42, "Output"] }, Open ]], Cell[78020, 2194, 93, 1, 41, "Text"], Cell[CellGroupData[{ Cell[78138, 2199, 163, 4, 43, "Input"], Cell[78304, 2205, 249, 5, 42, "Output"] }, Open ]], Cell[78568, 2213, 93, 1, 41, "Text"], Cell[CellGroupData[{ Cell[78686, 2218, 335, 8, 71, "Input"], Cell[79024, 2228, 494, 9, 58, "Message"], Cell[79521, 2239, 225, 5, 61, "Output"] }, Open ]], Cell[79761, 2247, 786, 12, 164, "Text"] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell[80596, 2265, 284, 6, 105, "Section"], Cell[80883, 2273, 535, 9, 90, "Text"], Cell[CellGroupData[{ Cell[81443, 2286, 121, 2, 54, "Subsection"], Cell[CellGroupData[{ Cell[81589, 2292, 129, 2, 41, "Subsubsection"], Cell[81721, 2296, 269, 5, 66, "Text"], Cell[81993, 2303, 1853, 52, 206, "Input"], Cell[CellGroupData[{ Cell[83871, 2359, 184, 3, 43, "Input"], Cell[84058, 2364, 364, 7, 42, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[84459, 2376, 193, 4, 43, "Input"], Cell[84655, 2382, 174, 4, 42, "Output"] }, Open ]], Cell[84844, 2389, 222, 5, 41, "Text"], Cell[CellGroupData[{ Cell[85091, 2398, 199, 4, 43, "Input"], Cell[85293, 2404, 481, 10, 33, "Message"], Cell[85777, 2416, 308, 8, 42, "Output"] }, Open ]], Cell[86100, 2427, 219, 4, 66, "Text"], Cell[CellGroupData[{ Cell[86344, 2435, 519, 12, 71, "Input"], Cell[86866, 2449, 149, 3, 42, "Output"] }, Open ]], Cell[87030, 2455, 109, 1, 41, "Text"], Cell[CellGroupData[{ Cell[87164, 2460, 131, 3, 43, "Input"], Cell[87298, 2465, 421, 8, 61, "Message"], Cell[87722, 2475, 177, 2, 42, "Output"] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell[87948, 2483, 125, 2, 41, "Subsubsection"], Cell[88076, 2487, 782, 17, 116, "Text"], Cell[88861, 2506, 422, 9, 66, "Text"], Cell[89286, 2517, 192, 7, 42, "Text"], Cell[CellGroupData[{ Cell[89503, 2528, 92, 1, 43, "Input"], Cell[89598, 2531, 843, 23, 93, "Output"] }, Open ]], Cell[90456, 2557, 217, 6, 41, "Text"], Cell[90676, 2565, 399, 9, 71, "Input"], Cell[91078, 2576, 190, 3, 41, "Text"], Cell[CellGroupData[{ Cell[91293, 2583, 164, 3, 43, "Input"], Cell[91460, 2588, 706, 18, 68, "Output"] }, Open ]], Cell[92181, 2609, 359, 6, 41, "Text"], Cell[CellGroupData[{ Cell[92565, 2619, 149, 2, 43, "Input"], Cell[92717, 2623, 274, 7, 42, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[93028, 2635, 131, 3, 43, "Input"], Cell[93162, 2640, 343, 7, 61, "Message"], Cell[93508, 2649, 99, 1, 42, "Output"] }, Open ]], Cell[93622, 2653, 171, 2, 41, "Text"], Cell[CellGroupData[{ Cell[93818, 2659, 391, 9, 43, "Input"], Cell[94212, 2670, 315, 7, 32, "Message"], Cell[94530, 2679, 178, 4, 61, "Output"] }, Open ]], Cell[94723, 2686, 476, 12, 67, "Text"], Cell[95202, 2700, 473, 11, 71, "Input"], Cell[95678, 2713, 105, 1, 41, "Text"], Cell[CellGroupData[{ Cell[95808, 2718, 92, 1, 43, "Input"], Cell[95903, 2721, 786, 21, 93, "Output"] }, Open ]], Cell[96704, 2745, 96, 1, 41, "Text"], Cell[CellGroupData[{ Cell[96825, 2750, 272, 7, 43, "Input"], Cell[97100, 2759, 393, 8, 58, "Message"], Cell[97496, 2769, 393, 8, 58, "Message"], Cell[97892, 2779, 393, 8, 58, "Message"], Cell[98288, 2789, 539, 10, 83, "Message"], Cell[98830, 2801, 184, 5, 61, "Output"] }, Open ]], Cell[99029, 2809, 400, 10, 66, "Text"], Cell[99432, 2821, 437, 11, 71, "Input"], Cell[99872, 2834, 93, 1, 41, "Text"], Cell[CellGroupData[{ Cell[99990, 2839, 92, 1, 43, "Input"], Cell[100085, 2842, 736, 20, 93, "Output"] }, Open ]], Cell[100836, 2865, 245, 5, 66, "Text"], Cell[CellGroupData[{ Cell[101106, 2874, 272, 7, 43, "Input"], Cell[101381, 2883, 188, 5, 61, "Output"] }, Open ]], Cell[101584, 2891, 223, 5, 41, "Text"], Cell[101810, 2898, 632, 16, 125, "Input"], Cell[102445, 2916, 91, 1, 41, "Text"], Cell[CellGroupData[{ Cell[102561, 2921, 92, 1, 43, "Input"], Cell[102656, 2924, 769, 21, 93, "Output"] }, Open ]], Cell[103440, 2948, 95, 1, 41, "Text"], Cell[CellGroupData[{ Cell[103560, 2953, 272, 7, 43, "Input"], Cell[103835, 2962, 395, 8, 58, "Message"], Cell[104233, 2972, 174, 4, 61, "Output"] }, Open ]], Cell[104422, 2979, 292, 8, 67, "Text"], Cell[104717, 2989, 240, 6, 43, "Input"], Cell[104960, 2997, 93, 1, 41, "Text"], Cell[CellGroupData[{ Cell[105078, 3002, 92, 1, 43, "Input"], Cell[105173, 3005, 424, 11, 42, "Output"] }, Open ]], Cell[105612, 3019, 124, 1, 41, "Text"], Cell[105739, 3022, 581, 15, 125, "Input"], Cell[CellGroupData[{ Cell[106345, 3041, 162, 3, 43, "Input"], Cell[106510, 3046, 771, 21, 93, "Output"] }, Open ]], Cell[107296, 3070, 285, 5, 66, "Text"], Cell[CellGroupData[{ Cell[107606, 3079, 403, 9, 71, "Input"], Cell[108012, 3090, 420, 8, 58, "Message"], Cell[108435, 3100, 470, 8, 58, "Message"], Cell[108908, 3110, 205, 4, 61, "Output"] }, Open ]], Cell[109128, 3117, 295, 5, 66, "Text"] }, Open ]] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell[109484, 3129, 166, 2, 105, "Section"], Cell[109653, 3133, 190, 4, 41, "Text"], Cell[CellGroupData[{ Cell[109868, 3141, 121, 2, 54, "Subsection"], Cell[109992, 3145, 792, 20, 115, "Text"], Cell[110787, 3167, 691, 16, 125, "Input"], Cell[111481, 3185, 87, 1, 41, "Text"], Cell[CellGroupData[{ Cell[111593, 3190, 366, 9, 43, "Input"], Cell[111962, 3201, 397, 8, 58, "Message"], Cell[112362, 3211, 483, 9, 32, "Message"], Cell[112848, 3222, 206, 4, 42, "Output"] }, Open ]], Cell[113069, 3229, 121, 1, 41, "Text"], Cell[113193, 3232, 674, 15, 125, "Input"], Cell[CellGroupData[{ Cell[113892, 3251, 272, 7, 43, "Input"], Cell[114167, 3260, 397, 8, 58, "Message"], Cell[114567, 3270, 157, 2, 32, "Print"], Cell[114727, 3274, 175, 4, 61, "Output"] }, Open ]], Cell[114917, 3281, 634, 17, 90, "Text"], Cell[CellGroupData[{ Cell[115576, 3302, 709, 16, 125, "Input"], Cell[116288, 3320, 162, 2, 32, "Print"], Cell[116453, 3324, 424, 8, 108, "Message"] }, Open ]] }, Open ]] }, Open ]], Cell[CellGroupData[{ Cell[116938, 3339, 118, 2, 105, "Section"], Cell[117059, 3343, 6610, 126, 1416, "Text"] }, Open ]], Cell[CellGroupData[{ Cell[123706, 3474, 202, 3, 105, "Section"], Cell[123911, 3479, 2227, 33, 409, "Text"] }, Open ]] }, Open ]] } ] *) (* End of internal cache information *)