Mathematica函数foo可以区分foo [.2]和foo [.20]

dre*_*ves 2 macros parsing wolfram-mathematica

假设我想要一个带有数字的函数并将其作为字符串返回,与给定的完全一样.以下不起作用:

SetAttributes[foo, HoldAllComplete];
foo[x_] := ToString[Unevaluated@x]
Run Code Online (Sandbox Code Playgroud)

输出foo[.2]foo[.20]是相同的.

我想这样做的原因是我想要一个可以用点作为分隔符来理解日期的函数,例如f[2009.10.20].我意识到这是对Mathematica的一种奇怪的滥用,但我正在制作一种特定于域的语言,并希望通过eval(ToExpression)将Mathematica用作解析器.如果我可以依赖于两位数的日期和月份,我可以实现这项工作,例如2009.01.02,但我也想允许2009.1.2,最终沸腾到上述问题.

我怀疑唯一的答案是将事物作为字符串传递然后解析它,但也许有一些我不知道的技巧.请注意,这与此问题有关: Mathematica:Unevaluated vs Defer vs Hold vs HoldForm vs HoldAllComplete vs etc等

Pil*_*lsy 6

我不会依赖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]]
Run Code Online (Sandbox Code Playgroud)

我需要第二个规则,因为如果您尝试在数字中放入第二个小数位,笔记本界面将"有用"地插入空格.

编辑:为了从内核中使用它,您需要使用前端,但在版本7中通常很容易.如果您可以将表达式作为字符串,请UsingFrontEndToExpression以下内容一起使用:

 UsingFrontEnd[ToExpression["foo[2009.09.20]", StandardForm]
Run Code Online (Sandbox Code Playgroud)

编辑2:如果你想玩,有很多可能性$PreRead,它允许你在解析之前对输入应用特殊处理作为字符串.