【问题标题】:Indentation with Let StatementsLet 语句的缩进
【发布时间】:2015-02-26 23:15:27
【问题描述】:

恐怕我在理解这一点和一般的 let 块时已经被挖掘出来了。

以下代码:

splitWith tf xs 
    |(null xs) = [[]]
    |((length xs) == 1) = [xs]
    |otherwise = let tpl = (break tf xs) 
                     x = (fst tpl) 
                     xrst =  (snd tpl)
         in [[x] ,(splitWith tf (tail xrst))]

创建此语法错误:

[1 of 1] 编译主程序(ch04_exercise.hs,解释)
ch04_exercise.hs:31:26: 输入‘x’解析错误

这发生在我去掉 Sublime Text 2 中的制表符并放入空格以排列变量之后。在我这样做之前,我在x 之后的 = 符号处遇到了语法错误。

知道我做错了什么吗?

【问题讨论】:

  • 看来我需要将实际作业放在下一行。对吗?
  • 发现 this description 的 Haskell 缩进。
  • 我认为我的示例在某种程度上弄乱了制表位,因此tpl let 之前的空格数与以下几行并不完全相同。

标签: haskell


【解决方案1】:

in 必须与let 对齐或在同一行:

| otherwise = let (x, xrst) = break tf xs
              in [[x], splitWith tf (tail xrst)]

这就是为什么我通常更喜欢将let 单独放在一行:

| otherwise =
    let (x, xrst) = break tf xs
    in [[x], splitWith tf (tail xrst)]

您也有不必要的括号,并且可以从一些模式匹配中受益(如上所示)。

【讨论】:

  • 否,在此示例中,in 可以位于除左列之外的后续行的任何位置。这是常年标签问题 - 绑定不对齐。
【解决方案2】:

此代码已编译(虽然类型错误)

我认为这里学到的一般教训是,如果您从下一行开始,排列 let 分配会更容易。

splitWith tf xs 
    |(null xs) = [[]]
    |((length xs) == 1) = [xs]
    |otherwise = let 
                    tpl = (break tf xs) 
                    x = (fst tpl) 
                    xrst =  (snd tpl)
                 in [[x] ,(splitWith tf (tail xrst))]

【讨论】:

    【解决方案3】:

    编译器抱怨x = (fst tpl),因为它的左边缘与tpl = 不一致。

    您只删除了一些选项卡。我将制表符设为<------>,空格设为.

    splitWith tf xs 
    <------><------>|(null xs) = [[]]
    <------><------>|((length xs) == 1) = [xs]
    <------><------>|otherwise = let tpl = (break tf xs) 
    .........................x = (fst tpl) 
    .........................xrst =  (snd tpl)
    <------><------>.....in [[x] ,(splitWith tf (tail xrst))]
    

    编译器使用 8 的倍数的制表位。您认为 tpl = 的位置与编译器认为的位置之间的差为 8 表明您的编辑器具有 4 的倍数的制表位,如下所示:

    splitWith tf xs 
    <--><-->|(null xs) = [[]]
    <--><-->|((length xs) == 1) = [xs]
    <--><-->|otherwise = let tpl = (break tf xs) 
    .........................x = (fst tpl) 
    .........................xrst =  (snd tpl)
    <--><-->.....in [[x] ,(splitWith tf (tail xrst))]
    

    这看起来不错且正确,但编译器不是这样看的!

    如果你坚持使用空格,那是最简单的。更改编辑器的设置。

    如果你只使用空格而不使用任何制表符,你就不会遇到这个问题,因为你的编辑器必须按照编译器的想法来显示它。

    我的编辑器让我指定当我按下制表符时,它应该插入制表符显示的空格数,所以我使用它,这对于 4 制表位是安全的。如果您的编辑器可以这样做,请使用该选项。 (如果没有,请考虑在编程时使用更聪明的编辑器。)

    我的编辑器也有自动缩进和outdent,下一行复制上一行的空白缩进——这避免了这个问题。如果您的编辑器支持它,请打开它,因为它可以节省您的精力并且您不太可能遇到解析错误。 (当我按下退格键时,我的编辑器会删除回上一级缩进,这很好。)

    几乎所有编辑器都可以更改标签的显示方式。如果你不能让它为制表符使用空格,你应该将制表位更改为 8,因为这与 ghc 匹配,并且你不太可能得到这个错误,但你最好还是使用空格。

    【讨论】:

    • 谢谢安德鲁。我今天早些时候在 Sublime 2 中做到了这一点,从那时起我的生活变得更好了。很好地展示信息!
    • @RaySalemi 我同意 bheklilr 的观点,即您有很多不必要的括号 - 您唯一需要的括号在最后一行 tail xrst。您也可能是指x:splitWith tf (tail xrst)。代码编译后还有另一个问题 - 试试 splitWith (==0) [1,2,3,0,4,5,6]splitWith (==0) [1,2,3,0,4,5,6,0,0,0,0]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-29
    • 1970-01-01
    • 2016-08-15
    • 2010-10-13
    • 1970-01-01
    • 2023-02-07
    相关资源
    最近更新 更多