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.
source to share
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.
source to share
$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 ...
source to share