Functional programming 标准ML样式:变量阴影样式好吗?
在标准ML中,变量阴影是否在一般情况下,特别是在模式匹配可接受时?对于此玩具示例:Functional programming 标准ML样式:变量阴影样式好吗?,functional-programming,sml,ml,Functional Programming,Sml,Ml,在标准ML中,变量阴影是否在一般情况下,特别是在模式匹配可接受时?对于此玩具示例: case xs of [] => 0 | x::xs => x + sum xs 下面的款式更好吗 fun sum(xs) = case xs of [] => 0 | x::xs' => x + sum xs' 在没有阴影的情况下,必须选择不同的名称,这会使代码变得混乱,尤其是在使用嵌套模式、let函数绑定和其他语言构造时。 谢谢大家!
case xs of
[] => 0
| x::xs => x + sum xs
下面的款式更好吗
fun sum(xs) =
case xs of
[] => 0
| x::xs' => x + sum xs'
在没有阴影的情况下,必须选择不同的名称,这会使代码变得混乱,尤其是在使用嵌套模式、let
函数绑定和其他语言构造时。
谢谢大家!
可变阴影是好的风格吗
没有
但是xs
和xs'
也不好:它们的类型相同,因此很容易意外地使用其中一个而不是另一个。在您的例子中,这可能会导致无限递归,并且很快就会被检测到。但在其他情况下,它可能会导致更微妙的错误。这条建议并不特别适用于函数式编程
编辑:对于totality,我将molbdnilo关于y::ys
的建议包括在内:
另一种方法是只匹配和绑定实际需要的值。在您的sum
示例中,除了拆分之外,实际上不需要完整的输入。所以你可以这样写
fun sum [] = 0
| sum (x::xs) = x + sum xs
或者使用更隐式的模式匹配:
val sum = foldl op+ 0
另一个例子,可以通过先对输入进行消毒,然后对其进行分类来解决:
datatype diction = Yelling | Asking | YellingAsking | Whatever
fun strip message = ...
fun classify message = ...
fun answer diction = ...
val response = answer o classify o strip
此处,函数
条带的消息将包含未压缩的空白,而分类函数的消息将不包含空白。因此,不要有多个消息
s,一个有空格,另一个没有空格,而是将它们放在单独的函数范围内,这些函数可以做不同的事情。通常会对代码进行结构化,这样,如果代码变得笨拙,就不会使用嵌套模式和复杂的let构造,但是我想大多数人会选择你的建议。我认为这个问题有一个明确的答案——不,这不是好的风格。然而,解决这一问题的办法相当主观,往往是根据具体情况选择的。此外,在总体方案中,代码库中有比一些阴影变量或一些后缀变量更重要的东西(如果它们用于职责明确的小函数中,我可以接受错误的变量命名)。我个人喜欢它,当引用阴影变量不再有效时,它不可能通过引用阴影变量来出错。我也喜欢它,因为它让我避免了我觉得非常混乱的素数名称。(虽然我不是MLer)建议y::ys
对于通用代码来说是很好的,但是当代码使用特定的名称,例如card
,grade
,等等时,替换这些名称就成了一个挑战,而且很可能,我们必须使用card'
和grade'
等名称。是的,因此,y::ys
的优势在于它在视觉上与xs
完全不同。对于特定于域的值绑定,如card
,您可以做一件类似的事情,将其命名为cardHand
,gradeBefore
,或者任何澄清上下文的东西:如果变量共存于同一名称空间中,则不会很容易得到错误的变量,并且读取错误的变量可能会触发“嘿,这是错误的。”
datatype diction = Yelling | Asking | YellingAsking | Whatever
fun strip message = ...
fun classify message = ...
fun answer diction = ...
val response = answer o classify o strip