Определить частную функцию в пакете Mathematica - PullRequest
5 голосов
/ 27 февраля 2011

Я не уверен, что понял, как правильно определять частные функции.Когда я пишу пакет mathematica, я просто делаю это:

BeginPackage["myPackage`"]
myPublicFunction::usage="myPublicFunction blahblahblah";
Begin["Private"]
myPrivateFunction[input_]:= ... ;
myPublicFunction[input_]:= ... ;
End[]
EndPackage[]

Это правильный путь или я что-то упустил?

1 Ответ

12 голосов
/ 28 февраля 2011

Да, это правильный путь.Это может окупиться, чтобы понять некоторые внутренние механизмы пакета.Контексты Mathematica похожи на пространства имен в других языках.Они могут быть вложенными.Каждый символ принадлежит некоторому контексту.В любой момент некоторый контекст является «текущим».Всякий раз, когда создается новый символ, система должна решить, к какому контексту будет принадлежать символ.Это происходит в разбор времени.Фундаментальная величина (переменная) здесь равна $ContextPath.Это в основном путь поиска символов.Это список контекстов, и всякий раз, когда система видит новый символ, она проверяет, существует ли символ с таким же коротким именем (то есть, собственно именем символа, без контекста) в некотором контексте в $ContextPath,Если он существует, то данное вхождение символа будет связано с существующим.Если это не так, то символ создается в текущем контексте.Обратите внимание, что это динамическая вещь - если вы измените $ContextPath в любой момент, следующее вхождение символа может быть связано с другим символом.

В любом случае, BeginPackage делает то, что он просто заменяет текущее значение $ ContextPath на {youPublicPackageContext, "System'"}, плюс, возможно, дополнительные контексты, которые вы публично импортируете через второй необязательный аргумент BeginPackage.Следовательно, все символы, находящиеся в разделе «public», анализируются в общедоступном контексте, если они не находятся в «System» или других контекстах, которые вы импортируете.И что EndPackage делает, чтобы восстановить значение $ContextPath до того, что было до того, как вы начали загружать пакет.Итак, технически сообщение об использовании - не единственный способ сделать символ общедоступным в вашем основном контексте - вы также можете просто ввести символ с точкой с запятой, например myFunction; (эта практика не рекомендуется, я только упомянул ее, чтобы уточнитьмеханизм).Теперь, когда вы вводите Begin["'Private'"], текущий контекст становится YourContext'Private' (подконтекст).$ContextPath не изменяется.Поэтому любой введенный там символ, которого нет в вашем общедоступном пакете или других импортированных пакетах (то есть контекстах, которые в данный момент находятся в $ContextPath), автоматически анализируется в подконтексте 'Private'.делает эти символы закрытыми, так как всякий раз, когда вы импортируете свой пакет в какой-то другой контекст (пакет), в $ContextPath добавляется только основной пакет, но не его подпакеты.Технически вы можете нарушить инкапсуляцию, вручную добавив YourPackage'Private' в $ ContextPath (скажем, PrependTo[$ContextPath, YourPackage'Private']), и тогда все ваши личные функции и другие символы станут общедоступными в этом конкретном контексте, в котором вы выполняете импорт.Опять же, эта практика не рекомендуется, но она объясняет механику.Суть в том, что понятие частного или общедоступного может быть полностью понято, когда мы знаем, как анализируются символы и каковы манипуляции с $ContextPath и $Context (другой системной переменной, задающей значение текущего контекста), чтовыполняются такими командами, как Begin и BeginPackage.Иными словами, в принципе можно эмулировать действия BeginPackage, Begin, End и EndPackage с помощью пользовательского кода.Здесь действуют всего несколько принципов (которые я попытался обрисовать выше), и сам механизм на самом деле очень открыт для пользователя, так что, если в некоторых редких случаях кому-то может понадобиться другое поведение, можно сделатьнекоторые «пользовательские» манипуляции с $ContextPath и Context, чтобы обеспечить какой-то нестандартный способ синтаксического анализа символов и, следовательно, контролировать инкапсуляцию в масштабе пакета некоторым «нестандартным» способом.Я не поощряю это, просто упомяну, чтобы подчеркнуть, что механизм на самом деле намного проще и гораздо более управляем, чем может показаться на первый взгляд.

...