Information / Information`InformationValueForm usando Full- ou InputForm
Eu tenho um problema com a Informationfunção embutida para símbolos definidos pelo usuário com StandardForm personalizado no Mathematica 12.1.1.0:
Por exemplo, com as definições de função
ClearAll[CM];
CM[1, a__] := CM[a]
CM /: Format[CM[a_, b___], StandardForm] := Row[{a, b}, " "]
CM::usage = "CM";
a consulta Information[CM]resulta em:
As definições na saída são formatadas usando StandardForm, mesmo sem exibi-lo corretamente. O mesmo problema ocorre quando se define UpValues . Neste ponto, isso torna a caixa de Informações ilegível, mas fica pior quando é usada InterpretationBox. Com
ClearAll[CM];
CM[1, a__] := CM[a]
CM /: Format[CM[a_, b___], StandardForm] := With[{box = ToBoxes[Row[{a, b}," "]]},
RawBoxes[InterpretationBox[RowBox[{box}], CM[a, b]]]
];
CM::usage = "CM";
Uma chamada para Information[CM]resulta em uma recursão infinita e vários avisos e erros:
Inspecionando os FullFormresultados das Information[CM]revelações
InformationData[Association[
...
Rule["DownValues",Information`InformationValueForm[DownValues,CM,List[RuleDelayed[CM[1,Pattern[a,BlankSequence[]]],CM[a]]]]],
...
Rule["FormatValues",Information`InformationValueForm[FormatValues,CM,List[RuleDelayed[MakeBoxes[CM[Pattern[a,Blank[]],Pattern[b,BlankNullSequence[]]],StandardForm],Format[With[List[Set[box,ToBoxes[Row[List[a,b]," "]]]],RawBoxes[InterpretationBox[RowBox[List[box]],CM[a,b]]]],StandardForm]]]]],
...
]]
e com ela a função interna e, claro, não documentada, ...InformationValueFormque é usada para gerar as definições encontradas.
Existe uma maneira de configurar ou manipular Informationou o subjacente InformationValueFormpara exibir as definições de função usando Full- ou InputForm ? Consegui manipular a saída FullForm convertendo os argumentos de RuleDelayedinside InformationValueFormem Strings, mas não fui capaz de anexar essa correção a Informationou InformationValueForm.
Eu não entendo a decisão de design por trás do uso de StandardForm na saída de Informationfunções definidas pelo usuário e toda a situação é basicamente um bug na minha opinião. O verdadeiro problema são as recursões e erros infinitos para funções de formatação mais envolvidas, que podem travar o kernel e / ou front-end. Tendo a documentar minhas funções e às vezes gosto de usar Informationpara me lembrar da ordem dos argumentos. A solução alternativa bastante insatisfatória que estou usando atualmente é desativar Informationminhas funções formatadas usando UpValues:
CM /: Information[CM, opts___] := CM::usage;
Dessa forma, pelo menos tenho acesso à mensagem de uso, mas as definições, opções e todos os outros Informationdados não podem ser acessados com esta solução alternativa.
Respostas
Eu encontrei a resposta para minha pergunta no código-fonte de várias funções centrais do Mathematica. Usar a função imensamente útil GeneralUtilities`PrintDefinitionsem eg InterpolatingFunction(ou qualquer outra função central usada BoxForm` ArrangeSummaryBoxpara sua saída formatada) revela a função / variável protegida do kernel BoxForm`UseIcons. Esta parece ser uma variável dinâmica relacionada à BoxFormqual é falsa para as caixas geradas por Information. O código a seguir permite a formatação personalizada no notebook, mas não na saída de Information(incluindo ?e ??) e outros ambientes com BoxForm`UseIcons=False:
MakeBoxes[..., StandartForm] /; BoxForm`UseIcons := ...
Anexar a formatação personalizada em MakeBoxesvez de Formate verificar a variável BoxForm`UseIconsresolve e responde minha pergunta para minha satisfação. Essa solução é de longe a melhor em comparação com minha resposta anterior e o método de escolha para pelo menos algumas funções principais com saída formatada sofisticada. Publiquei esta nova resposta porque a estratégia da solução é diferente da anterior.
É uma pena que este não está documentada ao lado Formatou MakeBoxesou até mesmo uma opção ou padrão dessas funções.
Eu encontrei uma solução um tanto viável com base em UpValues nos métodos / símbolos do usuário problemáticos, por exemplo:
ClearAll[CM];
CM[1, a__] := CM[a]
CM /: Format[CM[a_, b__], StandardForm] := Row[{a, b}, " "]
CM /: Format[CM[a_], StandardForm] := a
Unprotect[CMinfo]; ClearAll[CMinfo];
CMinfo /: Format[CMinfo, StandardForm] = "CM";
Attributes[CMinfo] = {Protected, Constant};
CM /: Information`InformationValueForm[val_, CM, exp_List] :=
With[{s = ReleaseHold[Hold[exp] /. CM -> CMinfo]},
Information`InformationValueForm[val, CMinfo, s]]
CM /: Information`InformationValueForm[FormatValues, CM, exp_List] :=
With[{s = {Skeleton[Length[exp]]}},
Information`InformationValueForm[val, CMinfo, s]]
CM::usage = "CM::usage";
que resulta na saída
O símbolo CMinfoé usado em em ...InformationValueForm[...]vez de CMpara evitar a formatação nas definições. A saída de FormatValuesainda está formatada e, portanto, não é muito informativa, portanto, inseri um marcador de posição. Talvez com um pouco mais de trabalho se pudesse fazer o FormatValuestrabalho também.
Esta abordagem funciona bem para mim, mas ainda não estou satisfeito com a necessidade de tais medidas. O Information[...]método deve funcionar fora da caixa em funções de usuário válidas. Portanto, ainda sou a favor de chamar toda essa bagunça de bug, mas agradeço a @Michael E2 por apontar nos comentários sob a pergunta que a tag 'bug' requer verificação. Não li a descrição da tag e usei incorretamente - desculpe por isso.
Observe que ambos Information[CM]e ??CMfuncionam conforme pretendido ao modificar ...InformationValueForm[...], o que, surpreendentemente, não é o caso para a correção apresentada em minha pergunta (cenário CM /: Information[CM] := CM::usage).
As formas especiais de entrada ?e ??não são apenas especial pelo nome, mas também especiais porque upvalues contornar para Informationque novamente apenas soa muito razoável para mim.