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, just like it does. 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 because I want a function that can understand dates with periods as separators, eg f[2009.10.20]

. I realize this is a bizarre abuse of Mathematica, but I'm making a domain specific language and want to use Mathematica as the parser for this, just by doing eval (ToExpression). I can actually make this work if I can count on double digit days and months like 2009.01.02, but I want to allow 2009.1.2 as well and that ends up with what was above.

I suspect the only answer is to pass the thing as a string and then parse it, but there might be some trick in there that I don't know. Please note that this is related to this question: Mathematica: Unevaluated vs Defer vs Hold vs HoldForm vs HoldAllComplete vs etc. Etc.

+2


source to share


3 answers


I would not rely on Mathematica's mathematical analysis. Instead, I would define rules MakeExpression

for foo

. This allows you to intercept the input like boxes before it parses the floats. This couple of rules should be a good starting point, 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 need the second rule because the laptop interface will "help" insert a space if you try to put the second decimal in a number.



The EDIT: . To use this from the kernel you need to use an interface, but it's pretty easy in version 7. If you can get the expression as a string, use UsingFrontEnd

in conjunction with ToExpression

:

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

      

EDIT 2: . There are many possibilities if you want to play with $PreRead

, allowing you to apply special handling to the input as strings before they are parsed.

+6


source


$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 map foo [.20] as foo [0.20]. The InputForm of this will be Foo [0.2`2.]



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

+3


source


Floats, IIRC, are analyzed by Mathematica in real Floats, so there is no real way to do what you want.

+1


source







All Articles