Я думаю, @ kvb дает очень хорошее объяснение, показывающее, как оценивается код. Код комбинирует вложенных функций и теневого копирования довольно запутанным способом :-). Я думаю, что полезно взглянуть на эти две концепции отдельно.
Затенение позволяет скрыть значение за новым значением в объявлении let
или привязкой значения в конструкции match
. Это означает, что вы больше не сможете получить доступ к исходному значению. Вот более простой пример:
let foo num =
let num = num + 20 // Line 2
let num = num * 2 // Line 3
num
Здесь мы объявляем функцию, которая принимает аргумент с именем num
. Допустим, мы вызываем функцию с 1 в качестве аргумента. Во второй строке мы объявляем новое значение с тем же именем - инициализируется 1 + 20 , что составляет 21 . Третья строка снова объявляет новое значение и инициализирует его как 21 * 2 (потому что она видит последний объявленный символ num , который имеет значение 21 ). В строке 4 мы снова получаем доступ к последнему объявленному символу num и возвращаем 42 .
Это полезно, главным образом, когда у вас есть какое-то вычисление, которое вычисляет какое-то новое значение, которое должно использоваться всеми последующими вычислениями. Затенение позволяет скрыть предыдущее значение, поэтому нет опасности, что вы случайно будете использовать исходное значение.
Вложенные функции весьма полезны, когда вам нужно выполнить локальное вычисление утилиты, которая использует параметры внешней функции. Например:
let times x nums =
let timesUtil y = y * x
for n in nums do
printfn "%d" (timesUtil n)
Здесь мы объявляем вложенную в утилиту функцию timesUtil
, которая умножает любое число на значение x
(которое является аргументом функции times
). Затем мы можем использовать его позже (в последней строке), чтобы выполнить операцию без необходимости снова передавать значение x
в качестве аргумента. Итак, главное, что интересно во вложенных функциях, это то, что они могут получать доступ к значениям, объявленным внешней функцией.