2011-11-27 12 views
11

¿Cómo convierto una especificación de cuadro arbitraria extraída de una expresión de celda en una expresión de entrada?Problemas al interpretar expresiones de cuadro de celda de entrada

Esto surgió como un problema con mi respuesta a Save Mathematica code in FullForm syntax. En ese contexto, se usaba la coincidencia de patrones para extraer las especificaciones de las cajas de las expresiones de los portátiles leídas usando Import.

Pensé que ToExpression o MakeExpression harían el trabajo de interpretación de cajas, pero en algunas circunstancias no lo hacen.

considerar una celda de entrada que contiene la expresión:

StringForm["a = ``", 1] 

La expresión celular de una célula tal es así:

Cell[BoxData[ 
RowBox[{"StringForm", "[", 
    RowBox[{"\"\<a = ``\>\"", ",", " ", "1"}], "]"}]], "Input"] 

que puede tomar la subexpresión BoxData de esta célula y utilizar ToExpression para obtener el mismo resultado que si hubiera evaluado la celda original:

ToExpression @ 
    BoxData[ 
    RowBox[{"StringForm", "[", 
     RowBox[{"\"\<a = ``\>\"", ",", " ", "1"}], "]"}]] 

Pero ahora consideran la expresión siguiente entrada:

StringForm["a = ``", 1]

Vas a tener que mirar de cerca para ver la diferencia: la a está en cursiva. Aquí está la expresión de células correspondiente:

Cell[BoxData[ 
RowBox[{"StringForm", "[", 
    RowBox[{"\"\<\!\(\* 
StyleBox[\"a\", 
FontSlant->\"Italic\"]\) = ``\>\"", ",", " ", "1"}], "]"}]], "Input"] 

Si evalúo esta célula normalmente, consigo el resultado esperado. Pero si trato de aplicar ToExpression a la BoxData subexpresión como antes:

ToExpression @ 
    BoxData[ 
    RowBox[{"StringForm", "[", 
    RowBox[{"\"\<\!\(\* 
    StyleBox[\"a\", 
    FontSlant->\"Italic\"]\) = ``\>\"", ",", " ", "1"}], "]"}]] 

se produce un error:

StringForm::string : String expected at position 1 in StringForm[]\) = '', 
FontSlant->"\~\(\*\nStyleBox["a Italic, 1]. 

El mismo tipo de error se produce para muchos, si no todos, de la línea caja de escape de cadenas secuencias. He intentado especificar explícitamente el formulario a ToExpression y MakeExpression, pero obtengo el mismo error. Lo que me lleva a mi pregunta ...

¿Qué tengo que hacer para emular la forma en que Mathematica interpreta los cuadros de una expresión de celda de entrada?

Respuesta

5

Creo que esto es un error.Aquí es una solución temporal que trabajó en un par de ejemplos que probé:

Clear[toExpression]; 
toExpression[bd_BoxData] := 
    ToExpression[bd /. 
     s_String :> 
     StringReplace[ 
      StringReplace[s, "\n" :> ""], 
      ShortestMatch[(start : "\(\*") ~~ body__ ~~ (end : "\)")] :> 
        StringJoin[start, StringReplace[body, "\"" :> "\\\""], end] 
     ] 
    ]; 

Por ejemplo, comenzamos con su caso:

In[747]:= 
BoxData["\"\<\!\(\* 
    StyleBox[\"a\", 
     FontSlant->\"Italic\"]\) = ``\>\""]//toExpression 

Out[747]= a = `` 

Si examinamos la célula ahora, es:

BoxData["\<\"\\!\\(\\*StyleBox[\\\"a\\\",FontSlant->\\\"Italic\\\"]\\)\ = ``\"\>"] 

en lugar de

BoxData["\"\<\!\(\*StyleBox[\"a\",FontSlant->\"Italic\"]\) = ``\>\""] 

(que es el inicial con nuevas líneas eliminadas). Y, argumentaría, esto es lo que debería haber sido desde el principio. Ahora:

In[746]:= [email protected] 
    BoxData["\<\"\\!\\(\\*StyleBox[\\\"a\\\",FontSlant->\\\"Italic\\\"]\\) = ``\"\>"] 

Out[746]= a = `` 

Así que esto ya funciona bien.

No sé cuán universal es este trabajo, pero parece funcionar para los ejemplos que probé. El principal problema era que, al "codificar" cosas como a y Italic, debería haber sido \\\"a\\\" y \\\"Italic\\\" en lugar de \"a\" y \"Italic\" - los escapes para los escapes en sí no estaban.

+0

@WReach Tenga en cuenta que mi solución inicial no era del todo correcta, estaba fallando en expresiones más complejas, como acabo de descubrir. Lo modifiqué un poco, ahora parece funcionar correctamente. –

+0

Su versión actualizada maneja todos los casos con los que he chocado. Voy a aplazar el "aceptar" por un tiempo más en caso de que haya otras ideas de próxima aparición. Me inclino a aceptar que hay un error aquí, pero no puedo evitar la sensación de que me estoy perdiendo algo fundamental ... o tal vez sea solo una vana esperanza de que el analizador no esté usando funciones ocultas que no están disponibles para nosotros. – WReach

+0

@WReach Creo que este es el mismo tipo de pérdida de información que ocurre en el siguiente ejemplo simple: 'ToExpression [ToString [" a "]] // Head' (devuelve' Symbol'). 'ToExpression' reduce el nivel de" stringification "(no sé cómo hacerlo mejor) para una cadena. Entonces, para tener una cadena después de 'ToExpression', deberíamos haber usado aquí' "\" a \ "" '. El caso que nos ocupa es el mismo por naturaleza, pero estamos hablando de un nivel más profundo: stringification de "nivel 2" donde el error parece ser que solo se utilizó el "nivel 1". –

2

Honestamente, no estoy seguro de lo que estás tratando de hacer, pero sospecho que necesitarás usar el FrontEnd para el procesamiento. Aquí hay un ejemplo genérico:

[email protected]`CellPrint[ 
    BoxData[RowBox[{"StringForm", "[", RowBox[{"\"\<\!\(\* 
     StyleBox[\"a\", 
     FontSlant->\"Italic\"]\) = ``\>\"", ",", " ", "1"}], "]"}]] 
] 

Sin embargo, no sé qué formato realmente desea obtener.

+1

En el contexto de la pregunta vinculada original, el objetivo era reconstituir una expresión de entrada de su representación de celda obtenida utilizando 'Import' o' NotebookGet'. Me sorprendió mucho descubrir que 'ToExpression' no era adecuado para la tarea. – WReach

Cuestiones relacionadas