Вы, конечно, можете сделать это. Вот один из способов:
exportCode[fname_String] :=
Function[code,
Export[fname, ToString@HoldForm@FullForm@code, "String"],
HoldAllComplete]
Например:
fn = exportCode["C:\\Temp\\mmacode.m"];
fn[
Clear[getWordsIndices];
getWordsIndices[sym_, words : {__String}] :=
Developer`ToPackedArray[words /. sym["Direct"]];
];
И импортировать это как строку:
In[623]:= Import["C:\\Temp\\mmacode.m","String"]//InputForm
Out[623]//InputForm=
"CompoundExpression[Clear[getWordsIndices], SetDelayed[getWordsIndices[Pattern[sym, Blank[]], \
Pattern[words, List[BlankSequence[String]]]], Developer`ToPackedArray[ReplaceAll[words, \
sym[\"Direct\"]]]], Null]"
Однако, переход на другой язык для выполнения метапрограммирования для Mathematica звучит для меня нелепо, учитывая, что Mathematica очень хорошо подходит для этого. В Mathematica доступно множество методов для выполнения метапрограммирования и избежания преждевременной оценки. Тот, что приходит мне в голову, я описал в этом ответе, но есть много других. Поскольку вы можете работать с проанализированным кодом и использовать сопоставление с образцом в Mathematica, вы экономите много . Вы можете просмотреть теги SO Mathematica (прошлые вопросы) и найти множество примеров метапрограммирования и контроля оценки.
EDIT
Чтобы облегчить вашу боль с помощью автоматической оценки символов (на самом деле их всего несколько, Infinity
является одним из них). Если вам просто нужно получить имя символа для данного символа, то эта функция поможет:
unevaluatedSymbolName = Function[sym, SymbolName@Unevaluated@sym, HoldAllComplete]
Вы используете его как
In[638]:= unevaluatedSymbolName[Infinity]//InputForm
Out[638]//InputForm="Infinity"
Кроме того, вы можете просто добавить атрибут HoldFirst
к функции SymbolName
через SetAttributes
. Один из способов - сделать это глобально:
* +1033 * SetAttributes [SymbolName, HoldFirst];
SymbolName [Бесконечность] // InputForm
Глобальное изменение встроенных функций, однако, опасно, поскольку может привести к непредсказуемым последствиям для такой большой системы, как Mathematica:
ClearAttributes[SymbolName, HoldFirst];
Вот макрос для локального использования:
ClearAll[withUnevaluatedSymbolName];
SetAttributes[withUnevaluatedSymbolName, HoldFirst];
withUnevaluatedSymbolName[code_] :=
Internal`InheritedBlock[{SymbolName},
SetAttributes[SymbolName, HoldFirst];
code]
Теперь
In[649]:=
withUnevaluatedSymbolName[
{#,StringLength[#]}&[SymbolName[Infinity]]]//InputForm
Out[649]//InputForm= {"Infinity", 8}
Вы также можете сделать некоторые замены в фрагменте кода, скажем, заменить данный символ на его имя. Вот пример кода (который я обертываю в Hold
, чтобы предотвратить его оценку):
c = Hold[Integrate[Exp[-x^2], {x, -Infinity, Infinity}]]
Общий способ сделать замены в таких случаях - использовать атрибуты Hold (см. этот ответ) и замены внутри удерживаемых выражений (см. этот вопрос). Для данного случая:
In[652]:=
withUnevaluatedSymbolName[
c/.HoldPattern[Infinity]:>RuleCondition[SymbolName[Infinity],True]
]//InputForm
Out[652]//InputForm=
Hold[Integrate[Exp[-x^2], {x, -"Infinity", "Infinity"}]]
, хотя это не единственный способ сделать это. Вместо того, чтобы использовать вышеупомянутый макрос, мы также можем закодировать модификацию SymbolName
в самом правиле (здесь я использую более многословную форму (трюк Тротта - Стржебонски) для оценки на месте, но вы можете использовать RuleCondition
как хорошо:
ClearAll[replaceSymbolUnevaluatedRule];
SetAttributes[replaceSymbolUnevaluatedRule, HoldFirst];
replaceSymbolUnevaluatedRule[sym_Symbol] :=
HoldPattern[sym] :> With[{eval = SymbolName@Unevaluated@sym}, eval /; True];
Теперь, например:
In[629]:=
Hold[Integrate[Exp[-x^2],{x,-Infinity,Infinity}]]/.
replaceSymbolUnevaluatedRule[Infinity]//InputForm
Out[629]//InputForm=
Hold[Integrate[Exp[-x^2], {x, -"Infinity", "Infinity"}]]
На самом деле, весь этот ответ является хорошей демонстрацией различных методов метапрограммирования. Исходя из своего собственного опыта, я могу направить вас к этому , этому , этому , этому и этому ответам мой, где метапрограммирование было важно для решения проблемы, которую я решал. Вы также можете судить по доле функций в Mathematica, несущих атрибуты Hold ко всем функциям - это около 10-15 процентов, если память мне хорошо служит. Все эти функции по сути являются макросами, работающими над кодом. Для меня это очень показательный факт, говорящий мне, что Mathematica активно использует свои возможности метапрограммирования.