F#:如何将表达式转换为字符串

时间:2018-09-21 01:28:26

标签: f# tostring

你好,我被告知了这个问题:

  

编写F#函数 toString:aexpr->字符串以格式化表达式   作为字符串,二进制运算符以inix格式编写。对于   例如,它可以将 Sub(Var“ x”,CstI 34)格式化为字符串“ x-   34“ 。为简单起见,请在所有子表达式中加上括号,即使是   当它们根据标准优先规则是多余的时   适用于算术运算符。使用预定义的函数字符串进行转换   字符串表示形式的整数值。

     

提示:toString具有与eval函数几乎相同的结构,   尽管它不需要环境参数,因为它使用变量   名称,而不是变量值。

是的,这是硬件问题。任何帮助将不胜感激与解释。下面我包括了一个评估函数

这些是我们一直在使用的数据类型:

type oper1 = Neg | Not
type oper2 = Add | Mul | Sub | Less | Eq | And

type aexpr = 
  | C of int
  | V of string
  | Op1 of oper1 * aexpr
  | Op2 of oper2 * aexpr * aexpr

let rec eval e (env : (string * int) list) : int =
  match e with
  | CstI i            -> i
  | Var x             -> lookup env x 
  | Prim("+", e1, e2) -> (eval e1 env) + (eval e2 env)
  | Prim("*", e1, e2) -> (eval e1 env) * (eval e2 env)
  | Prim("-", e1, e2) -> (eval e1 env) - (eval e2 env)
  | Prim _ -> failwith "unknown primitive"
  | Let(x, e1, e2) -> eval e2 ((x, eval e1 env) :: env)

所以对于给定的问题,我写了:

let rec toString e (env : (string * int) list) : string
   match e with 
   | Prim("+", e1, e2) -> "e1 + e2"
   | Prim("*", e1, e2) -> "e1 - e2"
   | Prim("-", e1, e2) -> "e1 * e2"

这看起来很愚蠢,还是我走对了?对F#来说还很新

1 个答案:

答案 0 :(得分:1)

问题指出:

  

[...]尽管不需要环境参数[...]

所以您的函数toString应该看起来像这样:

let rec toString e =
    match e with
    | CstI i            -> sprintf "%i" i // format number as string
    | Var  x            -> x              // already a string
    | Prim("+", e1, e2) -> sprintf "(%s + %s)" (toString e1) (toString e2)
    | Prim("*", e1, e2) -> sprintf "(%s * %s)" (toString e1) (toString e2)
    | Prim("-", e1, e2) -> sprintf "(%s - %s)" (toString e1) (toString e2)

对于嵌套表达式,toString首先在子表达式上被调用。然后将所得的字符串插入%s中的sprintf中。