我最近打开了GHC的-Wall
选项,其中包括-fwarn-name-shadowing
。所提供的基本原理是:与fwarn-name-shadowing的可读性权衡
该选项使要发射的警告每当内范围值具有相同的名称作为外范围的值,即内值阴影外一个。这可以避免印刷错误,变成难以发现的错误。
但在实践中我还没有抓到任何错误,但是我有在我的职能方面取得的变量命名了很多尴尬的解决它。缩写示例:
-- General method for parsing a paragraph.
paragraph :: Parser Node
paragraph = undefined -- omitted for brevity
blockquote :: Parser Node
blockquote = lookAhead (char '>')
>> Blockquote
<$> paragraph' `sepBy1` blankLine
where
-- Avoid shadowing a `paragraph` method defined above.
-- This one is more specialized and relevant only in
-- this context.
paragraph' = Paragraph <$> body
这似乎有点臭我,但我有其他的案件变得更糟 - 比如我有一个功能,我最终避免使用remainder'
和sections'
阴影remainder
和sections
,并然后在一个嵌套的where
条款我直接去r
和s
,以避免进一步阴影 - 我想知道-fwarn-name-shadowing
是否在平衡净积极。我认为我可以做一些重构来避免一些阴影而不会招致这些尴尬的名字的间接,但这并不总是可能的。
我最好是允许一些阴影,还是我应该重新考虑这样的例子来让气味消失?我怀疑后者,但我不确定。
有时也会让我感到厌烦。我真正想要的是某种方式让编译器神奇地警告我*意外地*影子名称,但不是当我故意重复使用名称时。没有魔法的唯一方法就是如果我标记故意的阴影案例;我也许应该标记阴影名称的*使用*,以确保我不会死脑筋,并试图从同一范围内引用具有相同名称的两个不同事物。但是很难想象一种标记允许阴影的方式,而不是仅仅停留在“事物上”,而是用更少的语法开销! – Ben
我始终坚持通过重命名绑定来消除警告,但我认为这是个人偏好的问题。我喜欢在代码中间看到一个标识符,并且知道如果它具有顶级绑定,那就是真的。此外,在定义辅助函数时,很容易重用一些参数名称,比如'xs',然后混淆两个绑定。有时候,也可以写一个意外的递归绑定。不过,我可以看到有时候这个警告有点烦人。 – chi
@ben,我认为你以'_'开头的任何内容都不会发出警告,所以这也是一个选项。这样,如果你想重复使用和嵌套'foo'两次,你可以做'_foo','_foo','_foo'而不是'foo','foo'','foo''。 – wincent