Ресурсы, связанные с замыканиями в ОД? - PullRequest
0 голосов
/ 14 ноября 2011

Я беру урок, в котором используется ML, и мы переходим к замыканиям, но я не совсем понимаю их, особенно в ML.Я делал заметки в классе, и они не имеют особого смысла для меня / предоставляют достаточно деталей.Я пытался искать в Интернете для получения дополнительной информации, но не мог найти.

Кто-нибудь знает какие-либо ресурсы о замыканиях в ML (или о ML / замыканиях в целом), которые довольно хороши?

Или, если кто-то может опубликовать несколько общих мыслей / объяснений о том, как реализовать замыкание в ML или как будет выглядеть замыкание в ML, что такое замыкание и т. Д. Я бы очень признателен.Я просто пытаюсь понять концепцию / использование замыканий.

Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 17 ноября 2011

Я не знаю ML, поэтому мой ответ будет в Scheme, который является другим функциональным языком программирования. Я предполагаю, что вы не знаете Scheme, и хорошо прокомментируете мой код.

** Примечание. Схема типизируется динамически, поэтому вы не увидите никаких объявлений типов (например, int, float, char и т. Д.).

(define (double x)       ;this defines a new function called "double" which takes one argument called x
   (* 2 x))              ;return 2 times its argument. Function application in Scheme takes the form (function arg1 arg2 ...)

Мы будем использовать эту вновь определенную функцию следующим образом:

(double 10)  ;returns 20
(double 8)   ;returns 16

В этой функции переменная x является локальной переменной . x является формальным параметром double. Всякий раз, когда мы используем x в теле double, нет никаких сомнений относительно того, какое значение мы имеем в виду. Но что по этому поводу:

(define (foo x)          ;define a function "foo" which takes on argument called x
   (* x a))              ;return x times a

Еще раз, x является формальным параметром. Но как насчет a? Что мы имеем в виду, когда используем a в теле foo? a не определен в foo, поэтому он называется свободной переменной . Чтобы увидеть, что означает a, нам нужно взглянуть за пределы foo. Например, предположим, что foo был определен в этом контексте:

(define (bar a)        ;define a function "bar" which takes one argument called "a"
   (define (foo x)     ;define "foo" as an inner function of bar
      (* x a)))        ;foo returns x * a

Теперь мы знаем, что означает a. Схема (а также ML) лексически ограничена , что означает, что, чтобы узнать, что означает переменная a, мы смотрим на текстовый контекст (надеюсь, это имеет смысл).

Теперь вышеприведенное определение bar на самом деле неверно: даже мысль foo что-то возвращает, bar ничего не возвращает. Он определяет foo как внутреннюю функцию, но после этого определения нет никаких утверждений. Давайте исправим это:

(define (bar a)        ;define a function "bar" which takes one argument called "a"
   (define (foo x)     ;define "foo" as an inner function of bar
      (* x a))         ;foo returns x * a
   foo)                ;bar returns the function foo

Теперь bar возвращает функцию foo. Мы только что превратили bar в функцию высшего порядка , потому что она возвращает другую функцию.

Но есть проблема. Обычно, когда возвращается bar, локальная переменная a больше не нужна и ее значение теряется. Но foo все еще ссылается на a! Так что a нужно немного подождать. Вот здесь и возникают замыкания. Значение a «закрыто», поэтому оно остается неизменным, пока существует функция foo. Таким образом, мы можем вызвать foo даже после того, как bar завершит выполнение. Теперь давайте переименуем foo и bar, чтобы понять, почему это полезно:

(define (make-multiplier a)
   (define (multiplier x)
      (* x a))
   multiplier)

Теперь мы можем сделать это:

(define triple (make-multiplier 3))   ;call make-multiplier with the value 3. Bind the function which is returned to the variable "triple."
(triple 5)                            ;call triple with the value 5. Since the 3 was "closed over", (triple 5) returns 5 * 3, which is 15.

Итак - когда функция имеет «свободную переменную», для функции создается замыкание, которое «закрывает» свободную переменную и сохраняет ее в течение времени жизни функции. Таким образом, когда функция передается и покидает контекст, в котором она была определена, «свободная переменная» продолжает оставаться действительной.

0 голосов
/ 14 ноября 2011

замыкания означают в ML (или в Ocaml, Scheme, Lisp) для реализации функций. Таким образом, все функции являются замыканиями (то есть смесь кода и данных). Например (с использованием синтаксиса Ocaml)

 (* function making an incrementer, returning a function *)
 let make_incr i = fun x -> x + i;;

 (* use it to define the successor function *)
 let succ = make_incr 1;;

 (* compute the successor of 4 *)
 succ 4;;

Переводчик ocaml, конечно, успешно отвечает

val make_incr : int -> int -> int = <fun>
val succ : int -> int = <fun>
 - : int = 5

вы видите, что make_incr - это функция высшего порядка: при наличии некоторого целого числа она создает новую функцию. Таким образом, учитывая 1, он производит succ в приведенном выше примере. И succ содержит и код сложения, и целое число 1. Таким образом, он смешивает код и данные (среду для закрытых переменных) в замыкании.

Подробнее о публикации Википедии о закрытии и любом хорошем учебнике: SICP (автор Sussman), или C.Queinnec Lisp in Small Pieces, или любая хорошая вводная книга об Ocaml или книга Аппеля "Сборник с продолжениями" и т. д.

...