了解 ML 编程中的 "let" 和 "in"

Understanding "let" & "in" in ML programming

我的老师最近复习了 ML 中使用“let”和“in”的函数,但函数的主体让我感到困惑,因为我不明白它们如何协同工作以产生结果。该函数获取您花园中的蔬菜列表,并用给定的替代品替换原始蔬菜,因此该列表将在原始元素所在的每个位置打印出替代品 in.This 是函数

image to function code

fun replaceVegetable(orig, subt, Garden([]) = Garden([])

  | replaceVegetable(orig, subt, Garden([first::rest]) =

      let val Garden(newRest) = 

          replaceVegetable(orig, subst, Garden(rest));

      in Garden((if first = orig then subst else first)::newRest)

      end

  | replaceVegetable(orig, subst, x) = x;

我不担心最后一个模式“replaceVegetable(orig, subst, x) = x;”,我主要关心理解第二个模式。我想我明白 Garden(newRest) 是函数的局部变量,无论 replaceVegetable(orig, subst, Garden(rest)) 产生什么都将存储在该局部变量中。我不完全知道在“in Garden((if first = orig then subst else first)::newRest)”上发生了什么,这是在应用递归,所以它可以 运行 通过我给它的列表来查看它必须在哪里用替代品代替原来的?如果是这样,我无法确切地看到它是如何做到这一点的,因为整个功能让我感到困惑。

letinend一起走; in Garden((if first ... 不是“语言单位”,没有任何意义。

在更简单的形式中,

let val x = y in e end

表示“在表达式'e'中,'x'与'y'具有相同的值。

如果函数只接受一个简单的列表,可能更容易理解:

fun replaceVegetable(orig, subst, []) = []
  | replaceVegetable(orig, subst, first::rest) =
    let val newRest  = 
            replaceVegetable(orig, subst, rest)
    in (if first = orig then subst else first)::newRest
    end
  | replaceVegetable(orig, subst, x) = x;

这里的第二种情况和

一模一样
| replaceVegetable(orig, subst, first::rest) =
      (if first = orig then subst else first)::(replaceVegetable(orig, subst, rest))

您的函数还有一个 pattern-matching 绑定而不是普通变量绑定。

let val Garden newRest = replaceVegetable(...)
in ...
end

匹配递归的结果并将“包装”列表绑定到 newRest

的意思完全一样
case replaceVegetable (...) of
     Garden newRest => ...