Functional programming 标准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函数绑定和其他语言构造时。 谢谢大家!

在标准ML中,变量阴影是否在一般情况下,特别是在模式匹配可接受时?对于此玩具示例:

  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