Функция Mathematica foo, которая может отличить foo [.2] от foo [.20]

StackOverflow https://stackoverflow.com/questions/1628194

Вопрос

Предположим, мне нужна функция, которая принимает число и возвращает его в виде строки в точности так, как она была задана. Следующее не работает:

SetAttributes[foo, HoldAllComplete];
foo[x_] := ToString[Unevaluated@x]

Вывод для foo [.2] и foo [.20] идентичен.

Причина, по которой я хочу это сделать, заключается в том, что мне нужна функция, которая может понимать даты с точками в качестве разделителей, например, f [2009.10.20] . Я понимаю, что это странное злоупотребление Mathematica, но я делаю предметно-ориентированный язык и хочу использовать Mathematica в качестве парсера для него, просто выполняя eval (ToExpression). Я действительно могу сделать эту работу, если я могу полагаться на двузначные дни и месяцы, как 2009.01.02, но я хочу также разрешить 2009.1.2, и это в конечном итоге сводится к приведенному выше вопросу.

Я подозреваю, что единственный ответ - передать вещь в виде строки, а затем проанализировать ее, но, возможно, есть какой-то трюк, которого я не знаю. Обратите внимание, что это связано с этим вопросом: Mathematica: оценка без оценки, задержка, удержание, удержание, удержание, удержание, удержание, удержание, удержание, удержание, против и т. Д. И т. Д.

Это было полезно?

Решение

Я бы не стал полагаться на парсинг Mathematica. Вместо этого я бы определил правила для MakeExpression для foo . Это позволяет вам перехватывать ввод в виде блоков, прежде чем он будет проанализирован в числах с плавающей точкой. Эта пара правил должна быть хорошей отправной точкой, по крайней мере, для StandardForm :

MakeExpression[RowBox[{"foo", "[", dateString_, "]"}], StandardForm] :=
  With[{args = Sequence @@ Riffle[StringSplit[dateString, "."], ","]},
    MakeExpression[RowBox[{"foo", "[", "{", args, "}", "]"}], StandardForm]]

MakeExpression[RowBox[{"foo", "[", RowBox[{yearMonth_, day_}], "]"}], 
    StandardForm] :=
  With[{args = 
    Sequence @@ Riffle[Append[StringSplit[yearMonth, "."], day], ","]},
      MakeExpression[RowBox[{"foo", "[", "{", args, "}", "]"}], StandardForm]]

Мне нужно второе правило, потому что интерфейс ноутбука будет "услужливым". вставьте пробел, если вы пытаетесь поместить второе десятичное место в числе.

РЕДАКТИРОВАТЬ . Чтобы использовать это в ядре, вам нужно будет использовать внешний интерфейс, но это часто довольно просто в версии 7. Если вы можете получить выражение в виде строки, используйте UsingFrontEnd в сочетании с ToExpression :

 UsingFrontEnd[ToExpression["foo[2009.09.20]", StandardForm]

РЕДАКТИРОВАТЬ 2: Есть много возможностей, если вы хотите поиграть с $ PreRead , который позволяет применять специальную обработку для ввода, в виде строк , прежде чем они будут проанализированы.

Другие советы

$PreRead = If[$FrontEnd =!= Null, #1, 
StringReplace[#,x:NumberString /; StringMatchQ[x,"*.*0"] :>
     StringJoin[x, "`", ToString[
       StringLength[StringReplace[x, "-" -> ""]] - 
        Switch[StringTake[StringReplace[x, 
           "-" -> ""], 1], "0", 2, ".", 1, _, 
         1]]]]] & ; 

будет отображать foo [.20] как foo [0,20]. InputForm этого будет Foo [0.2`2.]

Я считаю, что анализ и отображение числовых форматов в Mathematica более сложны, чем это должно быть ...

Floats, IIRC, разбиты Mathematica на настоящие Float, поэтому реального способа сделать то, что вы хотите, нет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top