我已经学习Haskell几周了,我对使用underscore(_)作为函数参数有疑问.我想用一个具体的例子可以更好地问我的问题.假设我想定义一个函数,它根据提供的索引提取列表元素 - 是的,我意识到(!!)已经预先定义了.我可以定义函数的两种方式(我确定还有更多)如下:
版本1
indexedElement :: [a] -> Int -> a
indexedElement xs n | n < 0 = error "Index can not be negative."
indexedElement [] n = error "Index must be smaller than the length of the list."
indexedElement (x:xs) 0 = x
indexedElement (x:xs) n = indexedElement xs (n - 1)
Run Code Online (Sandbox Code Playgroud)
版本2
indexedElement :: [a] -> Int -> a
indexedElement _ n | n < 0 = error "Index can not be negative."
indexedElement [] _ = error "Index must be smaller than the length of the list."
indexedElement (x:_) 0 = x
indexedElement (_:xs) n = indexedElement xs (n - 1)
Run Code Online (Sandbox Code Playgroud)
这两个版本显然非常相似.两者之间的唯一区别是使用显式变量或下划线.对我来说_意味着任何事情都可以写在那里,而一个显式变量n就更明显,参数必须是一个整数.出于这个原因,我更喜欢第1版; 但GHC源代码的(!!)编写方式与版本2类似.第二版是否具有功能优势?如果没有,那么"硬核"Haskell程序员会不会对版本1有疑问?我理解使用一致的编写代码的方法的重要性,因此我尝试遵循用于特定语言编程的"不成文规则".这是一个我非常喜欢第一个版本的例子,我认为它不会让代码更难阅读.我不知道这是因为我的纯数学背景还是什么,但我想听听你更多经验丰富的人--Haskell兽医认为.
Sib*_*ibi 19
第二个版本有功能优势吗?
我不认为他们有任何操作上的差异.但我发现第二个版本更具可读性._表示根本没有使用它.因此,在阅读代码时,我可以忽略它,只关注其他参数.在第一个版本中,我会认为n已定义,但作者可能忘了使用它?或者也许这个论点不是必需的.第二个版本只是避免了这种心理超负荷.但这只是我的意见.:)
实际上,如果启用警告标志(-Wall)并编译代码,它将为您的第一个版本发出警告:
[1 of 1] Compiling Main ( code.hs, code.o )
code.hs:2:16: Warning: Defined but not used: ‘xs’
code.hs:3:19: Warning: Defined but not used: ‘n’
code.hs:4:19: Warning: Defined but not used: ‘xs’
code.hs:5:17: Warning: Defined but not used: ‘x’
code.hs:8:17: Warning: Defined but not used: ‘xs’
Run Code Online (Sandbox Code Playgroud)