Затенение и Вложенная функция

Я хочу понять, как механизм Затенения и Вложенной функции работает. Например:

let func y =
    let dup y = y + y
    let z = dup y
    let dup y =
        let dup z =
            let y = y * z
            y
        let z = y
        y
    dup z + z;;

val func : int -> int

> func 3;;
val it : int = 12

Кто-то может объяснить, что происходит здесь?

8
задан Guy Coder 27 February 2016 в 22:09
поделиться

2 ответа

Ваш код эквивалентно следующему, где я просто пронумеровал экземпляры ваших имен, чтобы помочь вам визуализировать, как происходит затенение.

let func y0 = 
  let dup0 y1 = y1 + y1
  let z0 = dup0 y0
  let dup1 y2 = 
    let dup2 z1 = 
      let y3 = y2 * z1 
      y3
    let z2 = y2 
    y2 
  dup1 z0 + z0

Конечно, это можно упростить. Поскольку dup2 и z2 никогда не используются, dup1 эквивалентно let dup1 y2 = y2 , а вся функция эквивалентна

let func y0 =
  let dup0 y1 = y1 + y1
  let z0 = dup0 y0
  dup1 z0 + z0

Что эквивалентно

let func y0 =
  let z0 = y0 + y0
  z0 + z0

заменой. Это то же самое, что и

let func y0 = 4 * y0

. Это помогает?

16
ответ дан 5 December 2019 в 05:44
поделиться

Думаю, @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 (которое является аргументом функции раз ). . Затем мы можем использовать его позже (в последней строке) для выполнения операции без повторной передачи значения x в качестве аргумента. Итак, самое интересное во вложенных функциях - это то, что они могут получать доступ к значениям, объявленным внешней функцией.

13
ответ дан 5 December 2019 в 05:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: