【问题标题】:Mathematica function foo that can distinguish foo[.2] from foo[.20]Mathematica 函数 foo 可以区分 foo[.2] 和 foo[.20]
【发布时间】:2009-10-27 00:55:07
【问题描述】:

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

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

【问题讨论】:

    标签: parsing macros wolfram-mathematica


    【解决方案1】:

    我不会依赖 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,有很多可能性,它允许您对输入应用特殊处理,作为字符串,之前他们被解析了。

    【讨论】:

    • 天哪,你太棒了!我原以为这是不可能的。一个障碍:我没有使用前端,而只是内核处理的纯文本。在那种情况下,你认为我毕竟不走运吗? (我很快就会自己进行更多实验。这是一个很好的线索。非常感谢!)
    【解决方案2】:
    $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 中解析和显示数字格式比 应该是……

    【讨论】:

      【解决方案3】:

      浮点数是,IIRC,由 Mathematica 解析成实际的浮点数,所以没有真正的方法可以做你想做的事。

      【讨论】:

      • Mathematica 太灵活了,不能说“没有真正的方法”。你应该删除这个答案。
      猜你喜欢
      • 2010-12-12
      • 2013-01-30
      • 1970-01-01
      • 2017-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-09
      • 2017-07-04
      相关资源
      最近更新 更多