“#”在哪里来自SML?

时间:2015-11-22 21:30:28

标签: sml smlnj

我正在尝试创建接受字符串并将其转换为布尔表达式的函数。例如:对于输入((x10+~1)*x132),它应该提供times(plus(var 10,compl 1),var 132),但它会提供times(plus(var #,compl #),var 132)。主题标签来自哪里?

datatype boolexp = zero
                 | one 
                 | plus of boolexp * boolexp 
                 | times of boolexp * boolexp
                 | var of int
                 | compl of boolexp

exception InvalidInput

(* takes the first n elements *)
fun take (_, 0) = nil
  | take (nil, _) = raise InvalidInput
  | take (h::t, n) = if n < 0
                     then raise InvalidInput
                     else h::take(t, n-1)

(* drops the frist n elements *)
fun drop (xs, 0) = xs
  | drop (nil, _) = raise InvalidInput
  | drop (h::t,n) = if n < 0
                    then raise InvalidInput
                    else drop (t, n-1)

(* converts string to integer *)
fun charlist_to_int (nil) = raise InvalidInput 
  | charlist_to_int (xs) =
    let fun helper_int_rev (nil) = 0
          | helper_int_rev (h::t) = if h >= #"0" andalso h <= #"9"
                                    then helper_int_rev t * 10 + (ord h - ord #"0")
                                    else raise InvalidInput
    in helper_int_rev (rev xs) end;

(* finds the operator and its position *)
fun searchfor_oper (nil,_,_) = raise InvalidInput
  | searchfor_oper (#"("::t, np, pos) = searchfor_oper (t, np+1, pos+1)
  | searchfor_oper (#")"::t, np, pos) = searchfor_oper(t, np-1, pos+1)
  | searchfor_oper (#"+"::t, 0, pos) = (pos, #"+")
  | searchfor_oper (#"*"::t, 0, pos) = (pos, #"*")
  | searchfor_oper (h::t, np, pos) = searchfor_oper (t, np, pos+1)

fun beparse_helper (nil) = raise InvalidInput
  | beparse_helper (h::t) =
    if h = #"x" then if hd(t)= #"0" then raise InvalidInput
    else var (charlist_to_int (t))
    else if h = #"0" then if t = nil then zero else raise InvalidInput
    else if h = #"1" then if t = nil then one else raise InvalidInput
    else if h = #"~" then compl(beparse_helper(t))
    else if h = #"(" then
    let
        val lst = if hd (rev t)= #")" then take(t, length(t)-1) else raise InvalidInput
        val (pos, oper) = searchfor_oper (lst, 0, 1)
    in
        if oper = (#"+")
        then plus(beparse_helper(take(lst,pos-1)), beparse_helper(drop(lst,pos)))
        else if oper = (#"*")
             then times(beparse_helper(take(lst,pos-1)),beparse_helper(drop(lst,pos)))
             else raise InvalidInput 
    end
    else raise InvalidInput;

fun beparse(s) = beparse_helper(explode(s));

(*TESTING*)
beparse ("((x10+~1)*x132)");

2 个答案:

答案 0 :(得分:3)

我认为SML/NJ本身不是...默认的REPL输出。在宏观方案中,REPL用于开发/调试 - 而不是完成程序运行它的环境。诸如树之类的递归数据结构可以快速产生太大而不方便打印的值。 REPL以两种方式截断输出。对于列表,它将打印大约十几个元素,然后使用#。对于树之类的东西,它将打印几个级别,然后使用Control.Print.printDepth := 20;表示您已达到截断发生的级别。如果您觉得不方便,可以做以下两件事之一:

1)通过在REPL中评估pprint(或者你想要的多少),可以改变SML / NJ中的逻辑打印深度

2)也许更原则但更多的工作 - 为您的值编写一个自定义漂亮的打印机(比如pprint v;)并评估,例如REPL中的v;而非console.time

答案 1 :(得分:0)

另外,请考虑更多地使用模式匹配:

fun beparse_helper [] = raise InvalidInput
  | beparse_helper (#"x"::cs) = var (charlist_to_int cs)
  | beparse_helper (#"0"::[]) = zero
  | beparse_helper (#"1"::[]) = one
  | beparse_helper (#"~"::cs) = compl (beparse_helper cs)
  | beparse_helper (#"("::(cs as (_::_))) =
    let val lst = if List.last cs = #")"
                  then take (cs, length cs - 1)
                  else raise InvalidInput
    in case searchfor_oper (lst, 0, 1) of
          (pos, #"+") => plus (beparse_helper (take (lst, pos-1)),
                               beparse_helper(drop (lst, pos)))
        | (pos, #"*") => times (beparse_helper (take (lst, pos-1)),
                                beparse_helper(drop (lst, pos)))
    end
  | beparse_helper _ = raise InvalidInput