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

时间:2009-10-27 00:55:08

标签: parsing macros wolfram-mathematica

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

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

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 etc

3 个答案:

答案 0 :(得分: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]]

我需要第二条规则,因为如果您尝试在数字中添加第二个小数位,笔记本界面将“有用”地插入空格。

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

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

编辑2:如果您想使用$PreRead,可以使用特殊处理,作为字符串,有很多可能性,在他们被解析之前。

答案 1 :(得分:3)

$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中解析和显示数字格式比比较困难 它应该是......

答案 2 :(得分:1)

浮动是IIRC,由Mathematica解析为实际浮动,因此没有真正的方法可以做你想要的。