Функция Mathematica foo, которая может отличить foo [.2] от foo [.20] - PullRequest
2 голосов
/ 27 октября 2009

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

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: Неоцененный против Задержки против Удержания против HoldForm против HoldAllComplete против и т.д. и т.д.

Ответы [ 3 ]

6 голосов
/ 27 октября 2009

Я бы не стал полагаться на парсинг 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, что позволяет применять специальную обработку для ввода, в виде строк , до того, как они ' разобран.

3 голосов
/ 16 февраля 2010
$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 более сложны это должно быть ...

1 голос
/ 27 октября 2009

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

...