Подтвердить что ты не робот

Какая разница между "закрытием" и "блоком"?

Я обнаружил, что многие люди используют слова "закрытие" и блокируют взаимозаменяемость. Большинство из этих людей не могут объяснить, о чем они говорят.

Некоторые Java-программисты (даже из очень дорогих консультантов) говорят об анонимных внутренних классах как о "блоках" и "закрытиях", но я знаю, что это неверно. (Вы не можете передавать изменяемые переменные из области действия метода, в котором они определены...)

Я ищу:

  • точная, компьютерная наука определение блока
  • точная, компьютерная наука определение замыкания
  • и разъяснение разницы между ними.

Мне бы очень хотелось увидеть ссылки, статьи или книги на этих ссылках.

4b9b3361

Ответ 1

В то время как блок - это всего лишь фрагмент кода, который может быть составлен операторами и объявлениями, но ничто иное, закрытие не является реальным первоклассным объектом, переменная, которая имеет свой блок как значение.

Основное отличие состоит в том, что блок просто группирует команды вместе (например, тело оператора while), а замыкание - это переменная, содержащая некоторый код, который может быть выполнен.

Если у вас есть закрытие, вы можете передать его как параметр для функций, сгенерировать и разложить его, и в основном назвать его!

Closure c = { println 'Hello!' }
/* now you have an object that contains code */
c.call()

Конечно, замыкания более мощные, они являются переменными и могут использоваться для определения пользовательского поведения объектов (в то время как обычно вам приходилось использовать интерфейсы или другие подходы ООП в программировании).

Вы можете придумать закрытие как функцию, которая содержит то, что делает эта функция внутри себя.

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

for (int i = 0; i < 10; ++i)
{
     int t = i*2;
     printf("%d\r\n", t);
}

t определяется внутри блока (тело оператора for) и будет длиться только внутри этого блока.

Ответ 2

Блок - это нечто синтаксическое - логическая единица утверждений (больше связана с областью действия, чем с закрытием).

if (Condition) {
    // Block here 
} 
else {
    // Another block
}

Закрытие связано с анонимными функциями или классами - анонимным (функциональным) объектом, частью кода, привязанным к среде (с ее переменными).

def foo() {
   var x = 0
   return () => { x += 1; return x }
}

Здесь foo возвращает замыкание! Локальная переменная x сохраняется через закрытие даже после завершения foo и может быть увеличена посредством вызовов возвращенной анонимной функции.

val counter = foo()
print counter() // Returns 2
print counter() // Return 3

Обратите внимание, что только Ruby, в котором блок и закрытие обрабатываются аналогично, так как блок Ruby вызывает замыкание:

(1..10).each do |x|
    p x
end

Там each -метод передается функция замыкания (взятие параметра x), которая называется блоком в Ruby.

Ответ 3

Здесь много путаницы, потому что есть термины с несколькими определениями и несколько разных вещей, которые объединяются просто потому, что они обычно встречаются вместе.

Во-первых, у нас есть "блок". Это просто лексический фрагмент кода, который делает единицу - тело цикла, например. Если на самом деле язык имеет область блока, тогда могут быть определены переменные, которые существуют только внутри этого фрагмента кода.

Во-вторых, мы вызываем код как тип значения. В функциональных языках это значения функций, иногда называемые "funs", "анонимные функции" (потому что функция найдена в значении, а не в имени, которому он назначен, вам не нужно имя для их вызова), или "лямбда" (от оператора, используемого для их создания в исчислении лямбда Церкви). Их можно назвать "замыканиями", но они не являются автоматически истинными замыканиями; для того, чтобы квалифицироваться, они должны инкапсулировать ( "закрыть" ) лексическую область, окружающую их создание, то есть переменные, определенные вне области самой функции, но в пределах ее определения все еще доступны, когда функция вызывается, даже если вызывающая точка находится после того, как ссылочная переменная в противном случае вышла бы из области действия и была бы переработана ее хранилище.

Однако вы можете иметь вызываемые значения кода, которые не являются целыми функциями. Smalltalk называет эти "блокировки блоков", а Ruby называет их "procs". Но большинство рубистов просто называют их "блоками", потому что они являются обновленной версией того, что создано синтаксисом {... } или do... end. Что отличает их от lambdas (или "закрытия функций" ), так это то, что они не вводят новый уровень подпрограммы. Если код в кубе замыкания блока вызывает return, он возвращает из внешней функции/метода закрытие блока внутри, а не только самого блока.

Это поведение имеет решающее значение для сохранения того, что Р.Д. Тененент назвал "принципом соответствия", в котором говорится, что вы должны иметь возможность заменить любой код встроенной функцией, содержащей этот код в теле, и вызвать сразу. Например, в Javascript вы можете заменить это:

 x = 2;

с этим:

 (function(){x = 2;})();

Мой пример не очень интересен, но способность выполнять такое преобразование, не влияя на поведение программы, играет ключевую роль в функциональном рефакторинге. Проблема заключается в том, что, как только вы встроили инструкции return, принцип больше не выполняется.

Вот почему Ruby имеет как procs, так и лямбды - постоянный источник путаницы для новичков. Оба procs и lambdas являются объектами класса Proc, но они ведут себя по-другому, как указано выше: a return просто возвращается из тела лямбда, но возвращается из метода, окружающего proc. (Также, не относясь к разграничению, которое я здесь рисую, lambdas проверяет arity и жалуется, если вызвано с неправильным количеством аргументов. Вы можете указать, какой тип у вас есть, вызывая .lambda? на объекте.)

В настоящее время Javascript имеет только закрытие функций, хотя в таблице есть предложение ввести блокировки блоков для языка.

Ответ 4

Громкий бородатый говорит об закрытии и блоках:

http://martinfowler.com/bliki/Closure.html

В какой-то момент он говорит, что замыкание - это блок, который может быть передан как аргумент методу.

Ответ 5

Термины, которые вы используете, чаще всего используются в эти дни в Ruby, хотя конструкции ранее появились в Algol, Smalltalk и Scheme. Я бы назвал стандарт Ruby, если бы он был.

Я не уверен, что смогу ответить на ваш точный вопрос, но я могу проиллюстрировать. Мои извинения, если вы уже знаете это...

def f &x
  yield
  x
end

def g
  y = "block"
  t = f { p "I'm a #{y}" }
  y = "closure"
  t
end

t = g
t.call

А...

$ ruby exam.rb
"I'm a block"
"I'm a closure"
$ 

Таким образом, блок представляет собой анонимную функциональную последовательность кода, прикрепленную к вызову метода. Он использовался по всему Ruby API. Когда вы достаточно легко создаете анонимную функцию, оказывается, что они полезны для всех видов вещей.

Но обратите внимание, что после возврата f, тогда возвращается g, мы удерживаем его в блоке, возвращая его из f (как x), а затем из g (as t). Теперь мы вызываем блок второй раз. Опять же, обратите внимание, что g() вернулся. Но блок ссылается на локальную переменную в экземпляре функции (и области), который больше не существует?! И он получает новое значение y?!

Таким образом, замыкание функциональноподобного объекта, который закрывается по его лексической области. Их довольно сложно реализовать, поскольку они уничтожают модель do-it-with-a stack, которая так полезна для локальных переменных в экземплярах вызова функций.


1. Ruby имеет различные вкусы объектов типа закрытия; это только один из них.

Ответ 6

5

Это целое число.

Int workDaysInAWeek = 5

Это целочисленная переменная, и она может быть установлена ​​на другое целое число. (Если обстоятельства не позволяют вам изменить это значение, его можно назвать константой.)

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