Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 to 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

like image 991
dreeves Avatar asked Nov 20 '25 02:11

dreeves


1 Answers

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.

like image 110
Pillsy Avatar answered Nov 23 '25 10:11

Pillsy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!