【问题标题】:Why to replace `in` with `let` in sml?为什么在 sml 中用 `let` 替换 `in`?
【发布时间】:2017-05-09 05:30:00
【问题描述】:

我有一个 local 块,它的辅助方法很少。之后是一个主函数(在inend 块之间):

datatype color = BLACK | RED;
datatype 'a RBTree = Nil
        | Br of (int * 'a * color) * 'a RBTree * 'a RBTree;
datatype Balance = RR | LR | LL | RL;

exception NotFound;  

local   
    fun max (num1, num2) ...    
    fun get_hight ...
    fun get_balance_factor ...
    fun LL_rotate ...
    fun LR_rotate ...
    fun RR_rotate ...
    fun RL_rotate ...
fun balance_tree (Nil) = (Nil)
    | balance_tree (Br(node, Nil, Nil)) = (Br(node, Nil, Nil))
    | balance_tree (Br(node, left, right)) = 
        if (get_balance_factor (Br(node, left, right))) = 2 then 
            if (get_balance_factor left) = ~1 then (* LR *)
                LR_rotate (Br(node, left, right))
            else if (get_balance_factor left) > ~1 then (* LL *)
                LL_rotate (Br(node, left, right))
        else if (get_balance_factor Br(node, left, right)) = ~2 then
            if (get_balance_factor right) = 1 then  (* RL *)
                RL_rotate (Br(node, left, right))
            else if (get_balance_factor right) < 1 then (* RR *)
                RR_rotate (Br(node, left, right))
        else (Br(node, left, right))
in
    fun insert ((Nil), item) = Br(item, (Nil), (Nil) )
        | insert ( (Br(node, left, right)), item) = 
            if (#1(node) = #1(node)) then  
                (Br(item, left, right))
            else if (#1(node) < #1(node)) then              
                balance_tree (Br(node, insert(left, item), right))
            else                
                balance_tree (Br(node, left, insert(right, item)))
end;

... 代表实现。 而insert 是“主要”功能。 SML 给了我这个输出:

- use "ex4.sml";
[opening ex4.sml]
datatype color = BLACK | RED
datatype 'a RBTree = Br of (int * 'a * color) * 'a RBTree * 'a RBTree | Nil
datatype Balance = LL | LR | RL | RR
exception NotFound
ex4.sml:58.1-58.3 Error: syntax error: replacing  IN with  LET
ex4.sml:69.1 Error: syntax error found at END

uncaught exception Compile [Compile: "syntax error"]
  raised at: ../compiler/Parse/main/smlfile.sml:15.24-15.46
             ../compiler/TopLevel/interact/evalloop.sml:44.55
             ../compiler/TopLevel/interact/evalloop.sml:296.17-296.20

我不明白为什么要把in 替换为let

【问题讨论】:

  • 该错误消息不是建议——它表明编译器对您的代码感到困惑。某些东西导致它推断您正在尝试 let ... in 构造,但它发现 in 在它期望 let 的地方 - 或类似的东西。编译器语法错误消息通常是难以理解的。实际问题可能隐藏在fun balance_tree ... 的省略号中。或许您应该展示更多相关代码。
  • @JohnColeman 我为balance_tree 添加了代码,我认为你是对的,因为当我注释掉这个函数时,代码似乎没问题,但我找不到它有什么问题
  • 您似乎没有足够的else 子句。你有 6 个if,6 个then,但只有 4 个else
  • @JohnColeman,你是对的!我在两个 [内部] else if 之后添加了else,它解决了我的问题。我还是不明白为什么这会让口译员期待“让”?
  • 它在then 子句的中间看到了一个in——只有在同一个子句中有一个匹配的let 时才有意义。

标签: sml smlnj


【解决方案1】:

SML/NJ 的解析器错误有点奇怪。当它说“用 LET 替换 IN”时,它的意思是它在第 58 行的开头看到了标记“IN”(即关键字“in”),但由于无法解析,所以在解析时卡住了IN 有什么用。在这种情况下,它通过假装你写了一些不同的东西来执行错误恢复,我认为是基于一些硬编码的规则。这些规则并非旨在修复您的程序,只是为了允许解析继续,以便您可以在一次编译尝试中看到多个解析错误。在这种情况下,它只是说它假装看到“LET”(即关键字“let”)而不是“IN”,然后继续尝试解析。根据我的经验,正确的方法是查看第一个解析错误的位置,修复它,然后重新编译。后面的错误可能非常令人困惑,并且它关于如何尝试恢复的消息通常是无用的。

【讨论】:

    猜你喜欢
    • 2021-11-06
    • 2021-07-11
    • 2016-03-26
    • 2020-06-11
    • 1970-01-01
    • 2012-01-06
    • 1970-01-01
    • 2015-03-17
    • 2012-04-04
    相关资源
    最近更新 更多