SML中的“#”从何而来?

Where does "#" come from in SML?

我正在尝试制作接受字符串并将其转换为布尔表达式的函数。对于 example:for 输入 ((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)");

我不认为它是 SML 本身,而是 SML/NJ 默认 REPL 输出。在宏伟的计划中,REPL 是针对 development/debugging 的——而不是针对 运行 的完成程序的环境。诸如树之类的递归数据结构可以快速产生太大而无法方便打印的值。 REPL t运行 以几种方式对输出进行分类。对于列表,它将打印大约一打元素,然后使用 ...。对于树之类的东西,它会打印出几个级别,然后使用 # 表示您已经达到 t运行 发生的级别。如果你觉得这不方便,你可以做以下两件事之一:

1) SML/NJ 中的逻辑打印深度可以通过评估 REPL

中的 Control.Print.printDepth := 20;(或任何你想要的)来改变

2) 也许更有原则但更多的工作——为您的值编写自定义漂亮打印机(比如 pprint)并评估例如pprint v; 在 REPL 而不仅仅是 v;

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

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