开发者

Mathematica function foo that can distinguish foo[.2] from foo[.20]

Suppose I want a function that takes a number and returns it as a string, exactly as it was given. The following doesn't work:

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

The output for foo[.2] and foo[.20] is identical.

The reason I want to do this is that I want a function that can understand dates with dots as delimiters, eg, f[2009.10.20]. I realize that's a bizarre abuse of Mathematica but I'm making a domain-specific language and want to use Mathematica as the parser for it by just doing an eval (ToExpression). I can actually make this work if I can rely on double-digit days and months, like 2009.01.02 but I want to also allow 2009.1.2 and that ends up boiling down to the above question.

I suspect the only answer is t开发者_如何学Goo pass the thing in as a string and then parse it, but perhaps there's some trick I don't know. Note that this is related to this question: Mathematica: Unevaluated vs Defer vs Hold vs HoldForm vs HoldAllComplete vs etc etc


I wouldn't rely on Mathematica's float-parsing. Instead I'd define rules on MakeExpression for foo. This allows you to intercept the input, as boxes, prior to it being parsed into floats. This pair of rules should be a good starting place, at least for 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]]

I needed the second rule because the notebook interface will "helpfully" insert a space if you try to put a second decimal place in a number.

EDIT: In order to use this from the kernel, you'll need to use a front end, but that's often pretty easy in version 7. If you can get your expression as a string, use UsingFrontEnd in conjunction with ToExpression:

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

EDIT 2: There's a lot of possibilities if you want to play with $PreRead, which allows you to apply special processing to the input, as strings, before they're parsed.


$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]]]]] & ; 

will display foo[.20] as foo[0.20]. The InputForm of it will be foo[0.2`2.]

I find parsing and displaying number formats in Mathematica more difficult than it should be...


Floats are, IIRC, parsed by Mathematica into actual Floats, so there's no real way to do what you want.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜