标准 ML:丑陋的 isLeapYear 函数

Standard ML: Ugly isLeapYear Function

我正在尝试使用 case of 在标准 ML 中编写一个函数,但我最终得到的代码为一堆 if / else 尖叫。这只是使用 case of 的一个糟糕的候选者,还是有更好的设置方法,所以我不会经常将布尔值映射到布尔值?

这是我的代码:

fun isLeapYear(y) =
    case (y mod 400 = 0) of
        true => true |
        false => (case ((y mod 100 = 0)) of
            true => false |
            false => (case (y mod 4 = 0) of
                true => true |
                false => false));

感谢您的帮助, 克莱曼

一般什么时候看到

case p of
  true => true
  | false => q

(或等效的if p then true else q)你应该写

p orelse q

同样

case p of
  false => false
  true => q

只是 p andalso q

终于

case p of
  true => true
  false => false

只是 p.

所以你的例子最好写成

y mod 400 = 0
orelse (y mod 100 <> 0
        andalso y mod 4 = 0)

首先,case X of true => E1 | false => E2" 直接对应于 if X then E1 else E2,我个人更喜欢。(毕竟,if ... then ... else ... 是一种特殊的 case 构造,它只适用于布尔值,对吧?)把它变成那个给我们:

fun isLeapYear(y) =
          if y mod 400 = 0 then true
     else if y mod 100 = 0 then false
     else if y mod   4 = 0 then true
     else                       false

这让我想到了第二点:您总是可以重写 if B then E1 else E2,其中 E 之一是 truefalse,使用以下代码table:

(请原谅丹麦语标题,它取自我们在哥本哈根大学教授 SML 时使用的书“IP-2: Supplerende noter i Introduktion til programmering”。)

无论如何,用这个重写,我们得到:

fun isLeapYear(y) =
              if y mod 400 = 0 then true
         else if y mod 100 = 0 then false
         else if y mod   4 = 0 then true
         else                       false

变成

fun isLeapYear(y) =
              if y mod 400 = 0 then true
         else if y mod 100 = 0 then false
         else                       y mod   4 = 0

变成

fun isLeapYear(y) =
              if y mod 400 = 0 then true
                               else not (y mod 100 = 0) andalso y mod 4 = 0

变成

fun isLeapYear(y) = y mod 400 = 0 orelse (not (y mod 100 = 0) andalso y mod 4 = 0)

最后我们可以将 not (y mod 100 = 0) 变成 y mod 100 <> 0,给出:

fun isLeapYear(y) = y mod 400 = 0 orelse (y mod 100 <> 0 andalso y mod 4 = 0)

如果您不在意一些额外的说明:

fun isLeapYear(y) = case (y mod 400, y mod 100, y mod 4) of
    (0, _, _) => true 
  | (_, 0, _) => false
  | (_, _, 0) => true
  | (_, _, _) => false